1
0
mirror of https://github.com/anope/anope.git synced 2026-07-10 20:23:14 +02:00

Compare commits

..

83 Commits

Author SHA1 Message Date
Sadie Powell c9f199d7c8 Release 2.1.25. 2026-07-10 09:10:09 +01:00
Sadie Powell 1338316152 Update the change log. 2026-07-10 09:08:43 +01:00
Kufat 076af6bba9 Handle edge cases relating to IRCd-sent account names. 2026-07-10 09:04:37 +01:00
Sadie Powell d3bf09b65b Split up big timezones into multiple help categories. 2026-07-09 21:40:07 +01:00
Sadie Powell 9b609c1ccb Various improvements to the timezone list.
- Correctly translate the time region message.
- Squash time regions with only one zone like Antactica into Misc.
- Make sure we use a comma in the zone list even at the end of a
  line.
2026-07-09 21:03:35 +01:00
Sadie Powell cf05a92401 Consistently use imperative statements in command descriptions. 2026-07-09 19:08:35 +01:00
Sadie Powell 673b04f1fc Make the description of nickserv/sendpass more accurate. 2026-07-09 18:55:05 +01:00
Sadie Powell 215eba2704 Redocument nickserv/set/keepmodes. 2026-07-09 18:50:13 +01:00
Sadie Powell eb37dd0af1 Fix places where "user modes" is written as usermodes. 2026-07-09 18:23:26 +01:00
Sadie Powell 58e278410d Update the change log. 2026-07-09 17:22:59 +01:00
Sadie Powell 13f99f1ca7 Update utfcpp. 2026-07-08 14:05:16 +01:00
Sadie Powell f15f8e3454 Drop support for the draft reply tag. 2026-07-08 12:20:26 +01:00
Kufat ff52ade0cc Fix setting the chosen channel founder/successor in db_atheme. 2026-07-08 12:18:56 +01:00
Sadie Powell 4c81f45232 Fix a crash in the ns_cert module when upgrading fingerprints. 2026-07-06 14:40:34 +01:00
Sadie Powell cdccfaf99a Run irctest on Ubuntu 26.04 ARM. 2026-07-05 12:13:55 +01:00
Kufat e47d379d98 Fix a crash on exit when uplink lost and globaloncycledown set. 2026-07-05 08:18:59 +01:00
dependabot[bot] c784f08002 Bump actions/cache from 5 to 6
Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v5...v6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-01 20:20:23 +01:00
dependabot[bot] 6de2ae0046 Bump actions/checkout from 6 to 7
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7.
- [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/v6...v7)

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

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-01 20:19:59 +01:00
Sadie Powell c26f742662 Run irctest on GitHub Actions.
[skip alpine ci]
[skip ubuntu ci]
[skip windows ci]
2026-06-29 17:45:04 +01:00
Sadie Powell e3bff85339 Disable unity builds for targets with only one source file. 2026-06-29 17:17:43 +01:00
TehPeGaSuS 5819c1fcf3 Document the ns_flexible and ns_monospace options. 2026-06-29 12:21:06 +01:00
Sadie Powell 4b8f073cb7 Improve configuring paths. 2026-06-29 01:31:55 +01:00
Kufat 67026b184d Enhance Atheme database import functionality. 2026-06-29 01:28:59 +01:00
Sadie Powell b49f984598 Improve support for versioning builds.
- Don't increment the build id when doing reproducible builds.
- Generate the build date in build.h so it always gets updated.
2026-06-17 22:52:14 +01:00
Sadie Powell b9cacf1d0f Fix HostServ request timeouts for DNS validated vhosts. 2026-06-14 18:16:43 +01:00
Sadie Powell 09d0bd6987 Fix the bcrypt/md5 vendored libraries not being marked as extern C. 2026-06-14 17:45:06 +01:00
Sadie Powell f150ee857f Build vendored libraries as static libraries and link against them.
This avoids rebuilding code we've already built.
2026-06-14 12:45:18 +01:00
Sadie Powell d60c80a4a3 Build with -fPIC. 2026-06-14 12:44:49 +01:00
Sadie Powell 44b7493eb1 Add support for HostServ request cooldowns. 2026-06-13 23:53:16 +01:00
Sadie Powell a03e765172 Fix a crash when FindFromService can not find a command.
Closes #583.
2026-06-12 19:23:39 +01:00
Sadie Powell 17cd10ef21 Fix a crashed caused by invalidation of an iterator in os_mode.
Closes #582.
2026-06-12 10:47:58 +01:00
Sadie Powell ca8fcbe119 Allow protocol modules to apply tags to sent messages.
This is useful because for some IRCv3 specifications we need to
apply tags to all messages and its annoying to have to do this
inline when sending each message.
2026-06-10 09:14:09 +01:00
Sadie Powell b9d0762f2b Add a function for building an ISO 8601 timestamp. 2026-06-10 09:14:09 +01:00
Sadie Powell 4878b1787e Only send tags on InspIRCd when we are done syncing. 2026-06-09 23:29:35 +01:00
Sadie Powell 0163d92b1d Fix showing tags in the protocoldebug output for sent messages. 2026-06-09 23:23:18 +01:00
Sadie Powell a861a059f6 Fix the config parser using int for values that can not be negative. 2026-06-08 15:41:00 +01:00
Sadie Powell 90da25f84f Add Block::GetBlocks which returns an iterable list of blocks. 2026-06-08 15:39:28 +01:00
Sadie Powell ab362c9828 Pascalize some typedefs in Configuration::Block. 2026-06-08 14:17:30 +01:00
Kufat d1f6da1817 Allow specifying the order of ns_set_misc entries. 2026-06-08 09:36:18 +01:00
Sadie Powell 9280d90aba Make it clear that the hmac-* algos can't be used in the config. 2026-06-08 09:09:19 +01:00
Sadie Powell c71f69208d Add various config options to the argon2 algo in anope-mkpasswd. 2026-06-08 09:08:19 +01:00
Sadie Powell d0080b85a7 Fix a typo in the default Argon2 priority in the example config. 2026-06-08 09:07:16 +01:00
Sadie Powell 745e94783d Respect BCRYPT_ROUNDS from the environment in anope-mkpasswd. 2026-06-08 08:58:15 +01:00
Sadie Powell c32be6a711 Fix a missing colon when REPRODUCIBLE_BUILD is defined. 2026-06-08 08:54:46 +01:00
Kufat 9dd3acfc87 Append EXTRA_CONFIG_ARGS to CMake command 2026-06-05 20:34:09 +01:00
Sadie Powell 82b6da3763 Merge branch '2.0' into 2.1. 2026-05-26 10:48:07 +01:00
Sadie Powell 8e691eac80 Update the change log. 2026-05-26 10:44:44 +01:00
Sadie Powell 2327c6ac9a Fix an escaped value that wasn't escaped enough in chanstats. 2026-05-26 10:36:50 +01:00
Sadie Powell e23ea8f8ea Escape user-provided values in ldap_authentication and ldap_oper. 2026-05-26 09:30:15 +01:00
Sadie Powell 449cfa6503 Add EscapeDN and EscapeSF to the LDAP API. 2026-05-26 09:29:57 +01:00
Sadie Powell 59c60849b6 Remove hard coded references to default access levels. 2026-05-21 11:52:32 +01:00
Sadie Powell 6d2c4fb612 Merge branch '2.0' into 2.1. 2026-05-20 22:14:37 +01:00
Sadie Powell 01fc7421b6 Backport the pull request checks from 2.0. 2026-05-20 22:13:38 +01:00
TehPeGaSuS 3a59a81aa4 Update the Portuguese translation. 2026-05-20 20:57:10 +01:00
Sadie Powell c24de0ca8f Fix update.sh on recent gettext. 2026-05-20 17:42:17 +01:00
KidProtect 18555638c9 Update the Romanian translation. 2026-05-20 09:59:48 +01:00
Sadie Powell d5a653fe94 Make it clearer how to enable localisation. 2026-05-19 16:14:14 +01:00
Sadie Powell ad3be96283 Increase {nickserv}:regdelay to 15 minutes, add {ns_group}:delay. 2026-05-17 16:06:42 +01:00
Sadie Powell d689c0686d Update the Conan dependencies. 2026-05-16 20:57:44 +01:00
Sadie Powell 4ca2952069 Update the change log. 2026-05-16 20:57:44 +01:00
Sadie Powell caf904c938 Fix updating the access description in cs_flags. 2026-05-16 11:23:25 +01:00
Sadie Powell 8930cc2a92 Avoid potential crashes from calling strftime on a weird value. 2026-05-15 19:51:57 +01:00
Sadie Powell 47b927d788 Fix a crash from an uninitialised field in migrated flags. 2026-05-15 19:45:28 +01:00
Sadie Powell 647a07ff96 Fix an crash when a user migrates their own access. 2026-05-15 15:54:57 +01:00
Sadie Powell a856e80b1e Move migration messages to cs_flags, split non-migratable and non-migrated. 2026-05-15 09:06:02 +01:00
Sadie Powell 55746e1098 Fix users getting extra privileges when migrating to flags. 2026-05-15 08:43:03 +01:00
Sadie Powell e0da3bae18 Fix confirming accounts when admin-only confirmation is enabled. 2026-05-14 19:24:29 +01:00
Sadie Powell c1cf7b0bcc Fix checking if an access entry has a flag when migrating.
Closes #574.
2026-05-13 23:41:01 +01:00
Sadie Powell 1cf64a49c0 Fix the unique runtime library names on Windows. 2026-05-12 14:20:21 +01:00
Sadie Powell 92ed0071d7 Make the runtime copy error more verbose. 2026-05-12 14:10:04 +01:00
Sadie Powell 9469cb8b0e Merge branch '2.0' into 2.1 2026-05-12 13:53:36 +01:00
Sadie Powell e0b715b185 Sync the CI scripts. 2026-05-12 11:28:28 +01:00
Sadie Powell e6d7306202 Backport the mailmap changes from 2.1. 2026-05-12 11:26:06 +01:00
Sadie Powell 2107d18d9e Remove suggestion to email language file updates to team@.
Its 2026 and its way easier for everyone involved to just file a
pull request.
2026-05-11 13:00:55 +01:00
Sadie Powell acb9428635 Backport the locales-all advice from 2.1. 2026-05-11 12:58:47 +01:00
Sadie Powell d942da1df5 Update author list. 2026-05-06 12:01:57 +01:00
Sadie Powell a961259556 Merge branch '2.0' into 2.1. 2026-05-06 12:00:21 +01:00
Sadie Powell 27a19dcc52 Update the mailmap. 2026-05-06 11:59:03 +01:00
Sadie Powell e45814bfd6 Deduplicate the timer constructors with delegation. 2026-05-02 15:40:19 +01:00
Sadie Powell f12b590a6d Change Timer::Tick to return bool, get rid of the repeating field. 2026-05-02 15:40:19 +01:00
Sadie Powell c0bafe10b4 Avoid double deleting the ban timer in cs_ban. 2026-05-02 10:55:25 +01:00
dependabot[bot] 5f40d0d6bb Bump negrutiu/nsis-install from 2 to 3
Bumps [negrutiu/nsis-install](https://github.com/negrutiu/nsis-install) from 2 to 3.
- [Release notes](https://github.com/negrutiu/nsis-install/releases)
- [Commits](https://github.com/negrutiu/nsis-install/compare/v2...v3)

---
updated-dependencies:
- dependency-name: negrutiu/nsis-install
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-01 21:27:36 +01:00
Sadie Powell 6b416cc64d Bump for 2.1.25-git. 2026-05-01 12:39:20 +01:00
138 changed files with 6055 additions and 812 deletions
+2 -1
View File
@@ -35,5 +35,6 @@ I have ensured that:
- [ ] The code I am submitting is my own work and/or I have permission from the author to share it.
- [ ] Generative AI (Copilot, ChatGPT, etc) was not used to create any part of this pull request.
- [ ] I have documented any features added by this pull request.
- [ ] If the pull request contains a security fix I have followed the reporting rules mentioned in [the security policy](https://github.com/anope/anope/security/policy) (delete if not applicable).
- [ ] I have documented any features added by this pull request (delete if not applicable).
- [ ] This pull request does not introduce any incompatible API changes (stable branches only, delete if not applicable).
+25 -16
View File
@@ -3,21 +3,18 @@ on:
pull_request:
push:
schedule:
- cron: '0 0 * * 0'
- cron: 0 0 * * 0
workflow_dispatch:
jobs:
build:
if: "!contains(github.event.head_commit.message, '[skip alpine ci]')"
container: alpine:edge
container: alpine:latest
runs-on: ubuntu-latest
env:
CXX: ${{ matrix.compiler }}
CXXFLAGS: -Werror
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Install dependencies
run: |
run: |-
echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
apk update
apk add \
@@ -37,24 +34,36 @@ jobs:
tre-dev
- name: Enable extras
run: |
run: |-
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
- name: Run CMake
run: |
mkdir build && cd build
cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=DEBUG -DINSTDIR:STRING=$(readlink -f ../run) ..
env:
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
CXXFLAGS: -Werror
run: |-
cmake -B "build" \
-D "CMAKE_BUILD_TYPE=Debug" \
-D "INSTDIR=$(readlink -f ../run)" \
-G "Ninja" \
-Wdeprecated \
-Wdev
- name: Build Anope
run: |
ninja -C build install
- name: Build and install
env:
VERBOSE: ${{ runner.debug }}
run: |-
ninja -C "build" ${{ runner.debug == '1' && '-v' || '' }} install
strategy:
fail-fast: false
matrix:
compiler:
- clang++
- g++
- cc: clang
cxx: clang++
- cc: gcc
cxx: g++
+25 -16
View File
@@ -3,20 +3,17 @@ on:
pull_request:
push:
schedule:
- cron: '0 0 * * 0'
- cron: 0 0 * * 0
workflow_dispatch:
jobs:
build:
if: "!contains(github.event.head_commit.message, '[skip ubuntu ci]')"
runs-on: ubuntu-24.04
env:
CXX: ${{ matrix.compiler }}
CXXFLAGS: -Werror
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Install dependencies
run: |
run: |-
sudo apt-get update --assume-yes
sudo apt-get install --assume-yes --no-install-recommends \
clang \
@@ -34,24 +31,36 @@ jobs:
ninja-build
- name: Enable extras
run: |
run: |-
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
- name: Run CMake
run: |
mkdir build && cd build
cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=DEBUG -DINSTDIR:STRING=${{ github.workspace }}/run ..
env:
CC: ${{ matrix.compiler.cc }}
CXX: ${{ matrix.compiler.cxx }}
CXXFLAGS: -Werror
run: |-
cmake -B "build" \
-D "CMAKE_BUILD_TYPE=Debug" \
-D "INSTDIR=${{ github.workspace }}/run" \
-G "Ninja" \
-Wdeprecated \
-Wdev
- name: Build Anope
run: |
ninja -C ${{ github.workspace }}/build install
- name: Build and install
env:
VERBOSE: ${{ runner.debug }}
run: |-
ninja -C "build" ${{ runner.debug == '1' && '-v' || '' }} install
strategy:
fail-fast: false
matrix:
compiler:
- clang++
- g++
- cc: clang
cxx: clang++
- cc: gcc
cxx: g++
+41 -28
View File
@@ -6,77 +6,90 @@ on:
types:
- published
schedule:
- cron: '0 0 * * 0'
- cron: 0 0 * * 0
workflow_dispatch:
jobs:
build:
if: "!contains(github.event.head_commit.message, '[skip windows ci]')"
runs-on: windows-2025
env:
BUILD_PATH: ${{ github.workspace }}\build
BUILD_TYPE: ${{ github.event_name == 'release' && 'Release' || 'Debug' }}
CONAN_FILE: ${{ github.workspace }}\src\win32\conanfile.txt
CONAN_HOME: ${{ github.workspace }}\build\conan
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- name: Install NSIS
uses: negrutiu/nsis-install@v2
- name: Setup MSVC
uses: TheMrMilchmann/setup-msvc-dev@v4
with:
arch: x64
- name: Setup NSIS
uses: negrutiu/nsis-install@v3
with:
distro: official
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v3
- name: Setup Conan
uses: turtlebrowser/get-conan@v1.2
- name: Create Conan profile
- name: Create Conan configuration
run: |-
conan profile detect
(Get-Content ${{ env.CONAN_HOME }}\profiles\default).replace('build_type=Release', 'build_type=${{ env.BUILD_TYPE }}') | Set-Content ${{ env.CONAN_HOME }}\profiles\default
(Get-Content ${{ env.CONAN_HOME }}\profiles\default).replace('compiler.cppstd=14', 'compiler.cppstd=17') | Set-Content ${{ env.CONAN_HOME }}\profiles\default
Write-Output 'core.sources:download_urls=["origin", "https://c3i.jfrog.io/artifactory/conan-center-backup-sources/"]' | Out-File -Append ${{ env.CONAN_HOME }}\global.conf
Write-Output 'tools.cmake.cmaketoolchain:generator=Ninja' | Out-File -Append ${{ env.CONAN_HOME }}\global.conf
Write-Output 'user.openssl:windows_use_jom=True' | Out-File -Append ${{ env.CONAN_HOME }}\global.conf
- name: Try to restore libraries from the cache
uses: actions/cache/restore@v5
if: github.event_name != 'release'
uses: actions/cache/restore@v6
id: library-cache
with:
key: conan-${{ env.BUILD_TYPE }}-${{ hashFiles('src\win32\conanfile.txt') }}
path: ${{ env.CONAN_HOME }}\p
key: Conan VS${{ env.VisualStudioVersion }} ${{ env.BUILD_TYPE }} ${{ hashFiles(env.CONAN_FILE) }}
path: ${{ env.CONAN_HOME }}/p
- name: Install libraries
run: |
(Get-Content ${{ github.workspace }}\src\win32\conanfile.txt).replace('##', '') | Set-Content ${{ github.workspace }}\src\win32\conanfile.txt
conan install ${{ github.workspace }}\src\win32 --build missing --deployer runtime_deploy --deployer-folder ${{ github.workspace }}\build\extradll --output-folder .
working-directory: ${{ env.BUILD_PATH }}
run: |-
(Get-Content ${{ env.CONAN_FILE }}).replace('##', '') | Set-Content ${{ env.CONAN_FILE }}
conan install ${{ env.CONAN_FILE }} --build missing --deployer runtime_deploy --deployer-folder extradll --output-folder .
conan cache clean "*"
- name: Save libraries to the cache
if: ${{ steps.library-cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v5
if: steps.library-cache.outputs.cache-hit != 'true' && github.event_name != 'release'
uses: actions/cache/save@v6
with:
key: ${{ steps.library-cache.outputs.cache-primary-key }}
path: ${{ env.CONAN_HOME }}\p
- name: Run CMake
shell: cmd # work around a conan-io/conan-center-index bug #21823
working-directory: ${{ github.workspace }}\build
run: |
call ${{ github.workspace }}\conanbuild.bat
cmake -A x64 -D "CMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}" -D CMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -G "Visual Studio 17 2022" ..
working-directory: ${{ env.BUILD_PATH }}
run: |-
cmake -D "CMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }}" `
-D "CMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake" `
-G "Ninja Multi-Config" `
-S "${{ github.workspace }}" `
-Wdeprecated `
-Wdev
- name: Build Anope
working-directory: ${{ github.workspace }}\build
run: |
msbuild PACKAGE.vcxproj /M:5 /P:Configuration=${{ env.BUILD_TYPE }} /P:Platform=x64 /VERBOSITY:MINIMAL
- name: Build installer
working-directory: ${{ env.BUILD_PATH }}
run: |-
ninja -f "build-${{ env.BUILD_TYPE }}.ninja" ${{ runner.debug == '1' && '-v' || '' }} package
- name: Upload installer
if: "${{ github.event_name == 'release' }}"
working-directory: ${{ github.workspace }}\build
if: github.event_name == 'release'
working-directory: ${{ env.BUILD_PATH }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload ${{ github.event.release.tag_name }} $(Get-ChildItem anope-*.exe)
- name: Upload artifact
if: "${{ github.event_name != 'release' }}"
if: github.event_name != 'release'
uses: actions/upload-artifact@v7
with:
name: windows-installer
+223
View File
@@ -0,0 +1,223 @@
name: irctest
# Last checked: 2026-06-29
env:
INSPIRCD_REF: v4.11.0 # 2026-06-06
IRCTEST_REF: ff6ef19d96cacd79ea8033dda2cf660fe5cdba52 # 2026-06-20
SOLANUM_REF: a17cc145a7de564e49b84807d335289f30b12d00 # 2026-06-23
UNREALIRCD_REF: 1250b7f014dbbe1dae13138dbef6e52c6dcd5557 # 2026-05-15 (6.2.5)
on:
pull_request:
push:
schedule:
- cron: 0 0 * * 0
workflow_dispatch:
jobs:
check-skip:
if: "!contains(github.event.head_commit.message, '[skip irctest ci]')"
runs-on: ubuntu-26.04-arm
steps:
- run: true # Avoids skip check duplication.
build-anope:
needs:
- check-skip
runs-on: ubuntu-26.04-arm
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Build
run: |-
sudo apt-get install build-essential cmake --assume-yes
cmake \
-B "${{ github.workspace }}/build" \
-D "CMAKE_UNITY_BUILD=ON" \
-D "CMAKE_UNITY_BUILD_BATCH_SIZE=0" \
-D "INSTDIR=$HOME/software/anope" \
-G "Ninja" \
-S "${{ github.workspace }}"
ninja -C "${{ github.workspace }}/build" install
- name: Make artifact
run: |-
tar \
--auto-compress \
--create \
--file installed-anope.tar.gz \
$HOME/software/anope
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: installed-anope
path: installed-anope.tar.gz
retention-days: 1
build-inspircd:
needs:
- check-skip
runs-on: ubuntu-26.04-arm
steps:
- name: Checkout
uses: actions/checkout@v7
with:
ref: ${{ env.INSPIRCD_REF }}
repository: inspircd/inspircd
- name: Build
run: |-
sudo apt-get install build-essential --assume-yes
./configure \
--development \
--disable-auto-extras \
--prefix $HOME/software/inspircd
export CXXFLAGS="-DINSPIRCD_UNLIMITED_MAINLOOP"
make -j$(($(getconf _NPROCESSORS_ONLN) + 1)) install
- name: Make artifact
run: |-
tar \
--auto-compress \
--create \
--file installed-inspircd.tar.gz \
$HOME/software/inspircd
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: installed-inspircd
path: installed-inspircd.tar.gz
retention-days: 1
build-solanum:
needs:
- check-skip
runs-on: ubuntu-26.04-arm
steps:
- name: Checkout
uses: actions/checkout@v7
with:
ref: ${{ env.SOLANUM_REF }}
repository: solanum-ircd/solanum
- name: Build
run: |-
sudo apt-get install build-essential libltdl-dev --assume-yes
./autogen.sh
./configure \
--enable-fhs-paths \
--prefix $HOME/software/solanum
make -j$(($(getconf _NPROCESSORS_ONLN) + 1)) install
- name: Make artifact
run: |-
tar \
--auto-compress \
--create \
--file installed-solanum.tar.gz \
$HOME/software/solanum
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: installed-solanum
path: installed-solanum.tar.gz
retention-days: 1
build-unrealircd:
needs:
- check-skip
runs-on: ubuntu-26.04-arm
steps:
- name: Checkout
uses: actions/checkout@v7
with:
ref: ${{ env.UNREALIRCD_REF }}
repository: unrealircd/unrealircd
- name: Build
run: |-
sudo apt-get install build-essential libssl-dev --assume-yes
wget --output-document src/modules/third/metadata2.c https://raw.githubusercontent.com/progval/unrealircd-contrib/metadata2/files/metadata2.c
echo "BASEPATH=$HOME/software/unrealircd" >> config.settings
echo "GEOIP=none" >> config.settings
yes "" | ./Config
make -j$(($(getconf _NPROCESSORS_ONLN) + 1)) install
- name: Make artifact
run: |-
tar \
--auto-compress \
--create \
--file installed-unrealircd.tar.gz \
$HOME/software/unrealircd
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: installed-unrealircd
path: installed-unrealircd.tar.gz
retention-days: 1
test:
runs-on: ubuntu-26.04-arm
needs:
- build-anope
- build-inspircd
- build-solanum
- build-unrealircd
steps:
- name: Download Anope artifact
uses: actions/download-artifact@v8
with:
name: installed-anope
- name: Download server artifact
uses: actions/download-artifact@v8
with:
name: installed-${{ matrix.server }}
- name: Unpack artifacts
run: |-
for ARCHIVE in installed-anope installed-${{ matrix.server }}
do
tar \
--directory / \
--extract \
--file ${ARCHIVE}.tar.gz
done
for SOFTWARE in $HOME/software/*
do
echo "Adding ${SOFTWARE} to the PATH"
export PATH=$SOFTWARE/bin:$SOFTWARE/sbin:$PATH
done
echo PATH=$PATH >> $GITHUB_ENV
- name: Checkout irctest
uses: actions/checkout@v7
with:
ref: ${{ env.IRCTEST_REF }}
repository: progval/irctest
- name: Install irctest dependencies
run: |-
sudo apt-get install faketime
pip3 install --requirement requirements.txt pytest-xdist pytest-timeout
- name: Run irctest
env:
IRCTEST_DEBUG_LOGS: ${{ runner.debug }}
PYTEST_ARGS: --color=yes --verbose
run: |-
make ${{ matrix.server}}-anope
strategy:
fail-fast: false
matrix:
server:
- inspircd
- solanum
- unrealircd
+2 -1
View File
@@ -51,7 +51,8 @@ Robby <robby@chatbelgie.be> <robby@chat.be>
Robert Scheck <robert@fedoraproject.org> <robert-scheck@users.noreply.github.com>
Robin Burchell <w00t@inspircd.org> <rburchell@5417fbe8-f217-4b02-8779-1006273d7864>
Robin Burchell <w00t@inspircd.org> <Robin Burchell w00t@inspircd.org@5417fbe8-f217-4b02-8779-1006273d7864>
Sadie Powell <sadie@witchery.services> <petpow@saberuk.com>
Sadie Powell <sadie@sadiepowell.dev> <petpow@saberuk.com>
Sadie Powell <sadie@sadiepowell.dev> <sadie@witchery.services>
Sebastian Barfurth <github@afreshmelon.com>
Sebastian V. <hal9000@denorastats.org>
Sebastian V. <hal9000@denorastats.org> <pimpmylinux@5417fbe8-f217-4b02-8779-1006273d7864>
+42 -31
View File
@@ -1,8 +1,8 @@
# This usage of CMake requires at least version 3.20
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
# Set the project as C++ primarily
project(Anope CXX)
# Set the project as C++ primarily with C for the vendored libraries
project(Anope CXX C)
# Force the locale to C for later uses of things like gcc so the messages come up in English, not the user's default language
set(ENV{LC_ALL} C)
@@ -25,6 +25,7 @@ include(CheckFunctionExists)
include(CheckTypeSize)
include(CheckLibraryExists)
include(CheckCXXCompilerFlag)
include(CheckPIESupported)
if(NOT WIN32)
include(FindPkgConfig)
@@ -40,15 +41,19 @@ if(EXTRA_LIBS)
link_directories(${EXTRA_LIBS})
endif()
# Enable -fPIC for all targets.
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
check_pie_supported()
# Find gettext
find_package(Gettext)
find_package(Intl)
if(GETTEXT_FOUND AND Intl_FOUND)
if(Gettext_FOUND AND Intl_FOUND)
set(HAVE_LOCALIZATION ON)
include_directories(${Intl_INCLUDE_DIRS})
link_libraries(${Intl_LIBRARIES})
else()
message("Unable to find gettext and libintl; disabling localization")
message(STATUS "Unable to find gettext and/or libintl -- read docs/LANGUAGE for how to enable localization")
set(HAVE_LOCALIZATION OFF)
endif()
@@ -144,28 +149,37 @@ elseif(NOT CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/anope-${VERSION_MAJOR}-${VERSION_MINOR}")
endif()
function(configure_path VARIABLE DEFAULT)
if(NOT DEFINED ${VARIABLE})
set(${VARIABLE} ${DEFAULT} CACHE PATH "Location of the ${DEFAULT} directory")
endif()
if(WIN32)
set(ABSOLUTE_${VARIABLE} ${${VARIABLE}})
else()
cmake_path(
APPEND CMAKE_INSTALL_PREFIX "${${VARIABLE}}"
OUTPUT_VARIABLE ABSOLUTE_${VARIABLE}
)
cmake_path(NORMAL_PATH ABSOLUTE_${VARIABLE})
endif()
set(ABSOLUTE_${VARIABLE} ${ABSOLUTE_${VARIABLE}} CACHE INTERNAL "" FORCE)
install(
DIRECTORY
DESTINATION ${${VARIABLE}}
)
endfunction()
# Set default paths for various directories if not already defined
if(NOT BIN_DIR)
set(BIN_DIR "bin")
endif()
if(NOT DATA_DIR)
set(DATA_DIR "data")
endif()
if(NOT DOC_DIR)
set(DOC_DIR "doc")
endif()
if(NOT CONF_DIR)
set(CONF_DIR "conf")
endif()
if(NOT MODULE_DIR)
set(MODULE_DIR "modules")
endif()
if(NOT LOCALE_DIR)
set(LOCALE_DIR "locale")
endif()
if(NOT LOG_DIR)
set(LOG_DIR "logs")
endif()
configure_path(BIN_DIR "bin")
configure_path(DATA_DIR "data")
configure_path(DOC_DIR "doc")
configure_path(CONF_DIR "conf")
configure_path(MODULE_DIR "modules")
configure_path(LOCALE_DIR "locale")
configure_path(LOG_DIR "logs")
# Version number processing
# Find all lines in src/version.sh that start with VERSION_
@@ -218,12 +232,9 @@ set(SERVICES_BINARY "$<TARGET_FILE:${PROGRAM_NAME}>")
cmake_path(GET SERVICES_BINARY FILENAME SERVICES_BINARY)
# At install time, create the following additional directories
file(REAL_PATH ${DATA_DIR} ABSOLUTE_DATA_DIR BASE_DIRECTORY ${CMAKE_INSTALL_PREFIX})
file(REAL_PATH ${LOG_DIR} ABSOLUTE_LOG_DIR BASE_DIRECTORY ${CMAKE_INSTALL_PREFIX})
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/backups\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_LOG_DIR}\")")
install(DIRECTORY DESTINATION "${DATA_DIR}/backups")
if(WIN32)
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/runtime\")")
install(DIRECTORY DESTINATION "${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)
@@ -238,7 +249,6 @@ if(WIN32)
)
endif()
file(REAL_PATH ${MODULE_DIR} ABSOLUTE_MODULE_DIR BASE_DIRECTORY ${CMAKE_INSTALL_PREFIX})
install(CODE "file(REMOVE_RECURSE \"$ENV{DESTDIR}${ABSOLUTE_MODULE_DIR}\")")
# Only process the CPack section if we have CPack
@@ -289,6 +299,7 @@ endif()
add_subdirectory(data)
add_subdirectory(docs)
add_subdirectory(language)
add_subdirectory(vendor)
add_subdirectory(src)
add_subdirectory(modules)
add_subdirectory(include)
+4
View File
@@ -58,6 +58,10 @@ Run_Build_System () {
CMAKE_COMMAND="${CMAKE_COMMAND} -D EXTRA_LIBS=$EXTRA_LIB_DIRS"
fi
if [ "$EXTRA_CONFIG_ARGS" != "" ] ; then
CMAKE_COMMAND="${CMAKE_COMMAND} $EXTRA_CONFIG_ARGS"
fi
echo $CMAKE_COMMAND
$CMAKE_COMMAND
+1 -1
View File
@@ -1296,7 +1296,7 @@ module
/** The memory hardness in kibibytes of the Argon2 algorithm. Defaults to
* 128 mebibytes.
*/
#memory_cost = 121072
#memory_cost = 131072
/** The time hardness (iterations) of the Argon2 algorithm. Defaults to 3.
*/
+5
View File
@@ -252,6 +252,7 @@ privilege
rank = 10
level = 3
flag = "f"
flag_migration_requires = "ACCESS_CHANGE"
xop = "VOP"
}
@@ -496,6 +497,7 @@ privilege
rank = 110
level = 4
flag = "h"
flag_migration_requires = "HALFOP"
xop = "HOP"
}
@@ -638,6 +640,7 @@ privilege
rank = 220
level = 5
flag = "o"
flag_migration_requires = "OP"
xop = "AOP"
}
@@ -710,6 +713,7 @@ privilege
rank = 300
level = 10
flag = "a"
flag_migration_requires = "PROTECT"
xop = "SOP"
}
@@ -853,6 +857,7 @@ privilege
rank = 60
level = 3
flag = "v"
flag_migration_requires = "VOICE"
xop = "VOP"
}
+13
View File
@@ -201,6 +201,19 @@ module
{
name = "hs_request"
/*
* How long after a requested vhost is activated does a user have to wait
* before they can request a new vhost. Defaults to 24 hours.
*/
#activationcooldown = 24h
/*
* How long after a requested vhost is rejected does a user have to wait
* before they can request a new vhost. Defaults to 24 hours.
*/
#rejectioncooldown = 24h
/*
* If set, Anope will send a memo to the user requesting a vhost when it's been
* approved or rejected.
+15 -2
View File
@@ -120,6 +120,10 @@ module
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
* - protect: Protects the registered nickname from use by unidentified users.
* - ns_stats: Enable Chanstats for newly registered nicks
* - ns_flexible: Set FLEXIBLE as layout for messages from services (can not be set at the same
* time as ns_monospace)
* - ns_monospace: Set MONOSPACE as layout for messages from services (can not be set as the same
* time as ns_flexible)
*
* This directive is optional, if left blank, the options will default to memo_signon, and
* memo_receive. If you really want no defaults, use "none" by itself as the option.
@@ -128,9 +132,9 @@ 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.
* directive is optional, but recommended. If not set, it defaults to 15 minutes.
*/
regdelay = 5m
regdelay = 15m
/*
* The length of time before a nick's registration expires.
@@ -416,6 +420,12 @@ module
{
name = "ns_group"
/*
* The minimum length of time between consecutive uses of the GROUP command. This directive is
* optional, but recommended. If not set, it defaults to 5 minutes.
*/
delay = 5m
/*
* The maximum number of nicks allowed in a group.
*
@@ -741,6 +751,9 @@ command { service = "NickServ"; name = "SASET LAYOUT"; command = "nickserv/saset
*
* misc_description: A description of the command to show in the help.
* misc_title: A human-readable description of the stored data.
* misc_priority: Positive integer representing display order in nickserv/info
* and (if enabled) WHOIS output. Entries with unspecified
* priority will be prioritized in the order of declaration.
* misc_pattern: If defined then a regex pattern (using the engine specified
* in <options:regexengine> to validate the data with).
* misc_syntax: If defined then the syntax to show in the help output and, if
+3 -3
View File
@@ -3,7 +3,7 @@ and other useful contributions to Anope. These people, ordered by the number of
contributions they have made, are:
* Adam <adam@anope.org>
* Sadie Powell <sadie@witchery.services>
* Sadie Powell <sadie@sadiepowell.dev>
* Robin Burchell <w00t@inspircd.org>
* Naram Qashat <cyberbotx@anope.org>
* Pieter Bootsma <geniusdex@anope.org>
@@ -20,8 +20,8 @@ contributions they have made, are:
* Adam Kramer <ribosome@anope.org>
* Attila Molnar <attilamolnar@hush.com>
* Michael Wobst <wobst.michael@web.de>
* Matt Schatz <genius3000@g3k.solutions>
* PeGaSuS <droider.pc@gmail.com>
* Matt Schatz <genius3000@g3k.solutions>
* Mark Summers <mark@goopler.net>
* Daniel Vassdal <shutter@canternet.org>
* MatthewM <mcm@they-got.us>
@@ -49,6 +49,7 @@ contributions they have made, are:
* Robert Scheck <robert@fedoraproject.org>
* Dennis Friis <peavey@inspircd.org>
* Filippo Cortigiani <simos@simosnap.org>
* KidProtect
* Michał Zegan <webczat_200@poczta.onet.pl>
* AlphaTech <alphat3ch@icloud.com>
* Austin Ellis <siniStar@IRC4Fun.net>
@@ -71,7 +72,6 @@ contributions they have made, are:
* Jason Foster <retsofaj@gmail.com>
* Jeremy <jeremy@ssnet.ca>
* Josh Soref
* KidProtect
* KindOne <ineedalifetoday@live.com>
* linuxdaemon
* Mantas Mikulėnas <grawity@gmail.com>
+77 -1
View File
@@ -1,6 +1,82 @@
# Anope Change Log
## Anope 2.1.24 (unreleased)
## Anope 2.1.25 (2026-07-10)
### General Changes
* Added a cooldown timer to `hs_request` for after a vhost is approved or rejected.
* Added environment variables for configuring hashing algorithms to `anope-mkpasswd`.
* Added support for building with position-independent code on supported platforms.
* Added support for prioritising WHOIS entries in `ns_set_misc`.
* Documented the `ns_flexible` and `ns_monospace` account options.
* Dropped support for the `+draft/reply` tag in favour of the non-draft variant.
* Fixed a crash on shutdown when trying to send a global without an uplink.
* Fixed a crash when a temporary ban expires.
* Fixed a crash when trying to upgrade TLS fingerprints from an older algorithm.
* Fixed a potential crash caused by unusual timestamps being passed to `Anope::strftime`.
* Fixed confirming accounts when `{ns_register}:registration` is set to "admin".
* Fixed edge cases relating to IRCd-sent account names.
* Fixed extra CMake arguments from `./Config` being ignored.
* Fixed flag migration sometimes giving users higher privileges than they had originally when a flag provides multiple privileges.
* Fixed not being able to update the description of a flags access entry.
* Fixed not migrating the last seen time with an access entry.
* Fixed not using the extra CMake arguments from `./Config`.
* Fixed some command descriptions not being imperative statements.
* Fixed some help messages that did not reflect the default flag/level/xop access when changed in the configuration.
* Fixed the default memory hardness in the `enc_argon2` module.
* Improved configuring paths at build time.
* Improved help output for the `nickserv/set/timezone` command.
* Improved importing databases from Atheme.
* Improved support for reproducible builds.
* Redocumented the `nickserv/set/keepmodes` command.
* Separated the delay between nickname registrations from the delay between grouping nicknames.
* Updated the Portuguese translation.
* Updated the Romanian translation.
### Developer Changes
* Added `Block::GetBlocks` to allow using a range-based for loop to iterate config blocks.
* Added an event to `IRCDProto` to populate common tags onto a S2S message.
* Added automated testing on InspIRCd, Solanum, and UnrealIRCd using irctest.
* Added support for adding ajoin entries from modules.
* Changed various configuration block index fields to use an unsigned integer.
* Changed vendored libraries to be built as static libraries and linked into the modules that require them.
* Simplified timer repeat logic by allowing tick events to return bool to control whether the timer continues running.
## Anope 2.1.24 (2026-04-01)
### Breaking Changes
+1 -2
View File
@@ -32,8 +32,7 @@ Anope Multi Language Support
but 0x1B is special to Anope and is used to prevent the automatic linewrapper from breaking messages in the middle of
text that should not be split (e.g. commands). Your editor may not show these so be careful you don't delete them!
If you have finished a language file translation and you want others to use it, please file a pull request on GitHub
or send it to team@anope.org (don't forget to mention clearly your (nick)name, your email and the language name).
If you have finished a language file translation and you want others to use it, please file a pull request on GitHub.
You'll of course get full credit for it.
3) Using languages with modules
+3
View File
@@ -67,6 +67,9 @@ public:
*/
virtual ChanAccess *Create() = 0;
virtual void GetAccess(CommandSource& source, const Privilege *p, Anope::map<Anope::string> &access) = 0;
static void SendAccess(CommandSource &source, const Anope::string &pname);
private:
static std::list<AccessProvider *> Providers;
public:
-4
View File
@@ -362,10 +362,6 @@ namespace Anope
template<typename T>
using unordered_map = std::unordered_map<string, T, hash_ci, compare>;
#if !REPRODUCIBLE_BUILD
static const char *const compiled = __TIME__ " " __DATE__;
#endif
/** The time Anope started.
*/
extern CoreExport time_t StartTime;
+13 -10
View File
@@ -18,6 +18,7 @@
#include "regchannel.h"
#include "users.h"
#include "opertype.h"
#include "miscutils.h"
namespace Configuration
{
@@ -26,14 +27,15 @@ namespace Configuration
friend class Configuration::Conf;
public:
typedef Anope::map<Anope::string> item_map;
typedef Anope::multimap<Block> block_map;
typedef Anope::map<Anope::string> ItemMap;
typedef Anope::multimap<Block> BlockMap;
typedef Anope::iterator_range<BlockMap::const_iterator> BlockList;
private:
Anope::string name;
item_map items;
block_map blocks;
int linenum;
ItemMap items;
BlockMap blocks;
unsigned linenum;
/* Represents a missing tag. */
static Block EmptyBlock;
@@ -41,9 +43,10 @@ namespace Configuration
public:
Block(const Anope::string &);
const Anope::string &GetName() const;
int CountBlock(const Anope::string &name) const;
const Block &GetBlock(const Anope::string &name, int num = 0) const;
Block *GetMutableBlock(const Anope::string &name, int num = 0);
size_t CountBlock(const Anope::string &name) const;
BlockList GetBlocks(const Anope::string &name) const;
const Block &GetBlock(const Anope::string &name, size_t num = 0) const;
Block *GetMutableBlock(const Anope::string &name, size_t num = 0);
template<typename T> T Get(const Anope::string &tag, const Anope::string &def = "") const
{
@@ -51,7 +54,7 @@ namespace Configuration
}
bool Set(const Anope::string &tag, const Anope::string &value);
const item_map &GetItems() const;
const ItemMap &GetItems() const;
};
template<> CoreExport const Anope::string Block::Get(const Anope::string &tag, const Anope::string &def) const;
@@ -85,7 +88,7 @@ namespace Configuration
{
private:
/** Replaces defined variables within a string. */
Anope::string ReplaceVars(const Anope::string &str, const File &file, int linenumber);
Anope::string ReplaceVars(const Anope::string &str, const File &file, unsigned linenumber);
public:
/* options:readtimeout */
-4
View File
@@ -142,10 +142,6 @@ namespace Language
#define CHAN_ACCESS_LEVEL_RANGE _("Access level must be between %d and %d inclusive.")
#define CHAN_ACCESS_MALFORMED _("You cannot add a malformed mask to an access list. Did you mean to add %s instead?")
#define CHAN_ACCESS_FOREIGN N_("%u access entry from other access systems not shown; use \002%s\033ALL\002 to view all access entries.", "%u access entries from other access systems not shown; use \002%s\033ALL\002 to view all access entries.")
#define CHAN_ACCESS_MIGRATED_1 _("\002%s\002 has been migrated to the %s access system.")
#define CHAN_ACCESS_MIGRATED_N N_("\002%u\002 entry has been migrated to the %s access system.", "\002%u\002 entries have been migrated to the %s access system.")
#define CHAN_ACCESS_NOT_MIGRATED_1 _("\002%s\002 can not be migrated to the %s access system because they have privileges that you do not.")
#define CHAN_ACCESS_NOT_MIGRATED_N N_("\002%u\002 entry can not be migrated to the %s access system because they have privileges that you do not.", "\002%u\002 entries can not be migrated to the %s access system because they have privileges that you do not.")
#define CHAN_EXCEPTED _("\002%s\002 matches an except on %s and cannot be banned until the except has been removed.")
#define CHAN_INFO_HEADER _("Information about channel \002%s\002:")
#define CHAN_LIMIT_EXCEEDED _("You have already exceeded your limit of \002%d\002 channels.")
+87
View File
@@ -0,0 +1,87 @@
// Anope IRC Services <https://www.anope.org/>
//
// Copyright (C) 2003-2026 Anope Contributors
//
// Anope is free software. You can use, modify, and/or distribute it under the
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
// for the complete terms of this license and docs/AUTHORS.txt for a list of
// contributors.
//
// Based on the original code of Epona by Lara
// Based on the original code of Services by Andy Church
//
// SPDX-License-Identifier: GPL-2.0-only
#pragma once
#include <iterator>
#include <utility>
namespace Anope
{
template <typename Iterator>
class iterator_range;
/** Returns a range containing all elements equivalent to \p value.
* @param collection The collection to search within.
* @param value The value to search for.
*/
template <typename Collection, typename Value>
auto equal_range(const Collection& collection, const Value& value)
{
return iterator_range(collection.equal_range(value));
}
/** Returns a range representing a reverse iterator for the specified colleciton.
* @param collection The collection to create a reverse iterator for.
*/
template <typename Collection>
auto reverse_range(const Collection& collection)
{
return iterator_range(collection.rbegin(), collection.rend());
}
}
/** Represents a range of iterators. */
template <typename Iterator>
class Anope::iterator_range final
{
private:
/** An iterator which points to the start of the range. */
const Iterator begini;
/* An iterator which points to one past the end of the range. */
const Iterator endi;
public:
/** Initialises a new iterator range with the specified iterators.
* @param begin An iterator which points to the start of the range.
* @param end An iterator which points to one past the end of the range.
*/
explicit iterator_range(Iterator begin, Iterator end)
: begini(begin)
, endi(end)
{
}
/** Initialises a new iterator range from a pair of iterators.
* @param range A pair of iterators in the format [first, last).
*/
explicit iterator_range(std::pair<Iterator, Iterator> range)
: begini(range.first)
, endi(range.second)
{
}
/** Determines whether the iterator range is empty. */
bool empty() const { return begini == endi; }
/** Retrieves an iterator which points to the start of the range. */
const Iterator& begin() const { return begini; }
/** Retrieves an iterator which points to one past the end of the range. */
const Iterator& end() const { return endi; }
/** Retrieves the number of hops within the iterator range. */
typename std::iterator_traits<Iterator>::difference_type count() const { return std::distance(begini, endi); }
};
+2 -1
View File
@@ -194,12 +194,13 @@ namespace DNS
/** Used to time out the query, xalls OnError and lets the TimerManager
* delete this request.
*/
void Tick() override
bool Tick() override
{
Log(LOG_DEBUG_2) << "Resolver: timeout for query " << this->name;
Query rr(*this);
rr.error = ERROR_TIMEDOUT;
this->OnError(&rr);
return false;
}
};
+10
View File
@@ -173,4 +173,14 @@ public:
* @param attributes The attributes to modify
*/
virtual void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) = 0;
/** Escapes a LDAP string for use in a DN.
* @param str The string to escape.
*/
virtual Anope::string EscapeDN(const Anope::string &str) const = 0;
/** Escapes a LDAP string for use in a search filter.
* @param str The string to escape.
*/
virtual Anope::string EscapeSF(const Anope::string &str) const = 0;
};
+47
View File
@@ -0,0 +1,47 @@
// Anope IRC Services <https://www.anope.org/>
//
// Copyright (C) 2003-2026 Anope Contributors
//
// Anope is free software. You can use, modify, and/or distribute it under the
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
// for the complete terms of this license and docs/AUTHORS.txt for a list of
// contributors.
//
// Based on the original code of Epona by Lara
// Based on the original code of Services by Andy Church
//
// SPDX-License-Identifier: GPL-2.0-only
#pragma once
#define NICKSERV_AJOIN_LIST_EXT "ajoinlist"
struct AJoinEntry;
struct AJoinList
: Serialize::Checker<std::vector<AJoinEntry *> >
{
AJoinList(Extensible *) : Serialize::Checker<std::vector<AJoinEntry *> >("AJoinEntry") { }
virtual ~AJoinList() = default;
};
struct AJoinEntry final
: Serializable
{
Serialize::Reference<NickCore> owner;
Anope::string channel;
Anope::string key;
AJoinEntry(Extensible *) : Serializable("AJoinEntry") { }
~AJoinEntry() override
{
auto *channels = owner->GetExt<AJoinList>(NICKSERV_AJOIN_LIST_EXT);
if (channels)
{
auto it = std::find((*channels)->begin(), (*channels)->end(), this);
if (it != (*channels)->end())
(*channels)->erase(it);
}
}
};
+9 -1
View File
@@ -58,6 +58,14 @@ public:
*/
virtual bool Parse(const Anope::string &message, Anope::map<Anope::string> &tags, Anope::string &source, Anope::string &command, std::vector<Anope::string> &params);
/* Populates the tags that should be sent on all messages.
* @param tags The location to store tags.
* @param source Source of the message.
* @param command Command name.
* @param params Any extra parameters.
*/
virtual void PopulateTags(Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, const std::vector<Anope::string> &params);
/* Formats an outgoing message so it can be sent to the IRC server.
* @param message The location to store the formatted message.
* @param tags IRCv3 message tags.
@@ -279,7 +287,7 @@ public:
virtual void SendSVSHold(const Anope::string &, time_t) { }
virtual void SendSVSHoldDel(const Anope::string &) { }
virtual void SendSWhois(const MessageSource &source, User *target, const Anope::string &tag, const Anope::string &message) { };
virtual void SendSWhois(const MessageSource &source, User *target, const Anope::string &tag, time_t priority, const Anope::string &message) { };
virtual void SendSWhoisDel(const MessageSource &source, User *target, const Anope::string &tag, const Anope::string &message) { }
/** Introduces a server to the uplink
+6
View File
@@ -79,6 +79,12 @@ namespace Anope
*/
extern CoreExport Anope::string FormatCTCP(const Anope::string &name, const Anope::string &body = "");
/** Formats a date/time as an IS0 8601 timestamp.
* @param ts UNIX timestamp to format.
* @param ms Number of milliseconds to format.
*/
extern CoreExport Anope::string FormatISO8601(time_t ts, unsigned long long ms);
/** 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.
+3 -14
View File
@@ -31,23 +31,17 @@ private:
*/
time_t secs;
/** True if this is a repeating timer
*/
bool repeat;
public:
/** Constructor, initializes the triggering time
* @param time_from_now The number of seconds from now to trigger the timer
* @param repeating Repeat this timer every time_from_now if this is true
*/
Timer(time_t time_from_now, bool repeating = false);
Timer(time_t time_from_now);
/** Constructor, initializes the triggering time
* @param creator The creator of the timer
* @param time_from_now The number of seconds from now to trigger the timer
* @param repeating Repeat this timer every time_from_now if this is true
*/
Timer(Module *creator, time_t time_from_now, bool repeating = false);
Timer(Module *creator, time_t time_from_now);
/** Destructor, removes the timer from the list
*/
@@ -63,11 +57,6 @@ public:
*/
time_t GetTimer() const;
/** Returns true if the timer is set to repeat
* @return Returns true if the timer is set to repeat
*/
bool GetRepeat() const;
/** Set the interval between ticks
* @paramt t The new interval
*/
@@ -86,7 +75,7 @@ public:
/** Called when the timer ticks
* This should be overridden with something useful
*/
virtual void Tick() = 0;
virtual bool Tick() = 0;
};
/** This class manages sets of Timers, and triggers them at their defined times.
+17 -2
View File
@@ -18,6 +18,8 @@
#include <sstream>
#include <map>
#include "sysconf.h"
static std::string get_git_hash(const std::string &git_dir)
{
std::fstream fd;
@@ -78,14 +80,18 @@ static bool read_version_sh(const std::string &version_sh, std::map<std::string,
static bool write_build_h(const std::string &buildh, const std::string &git_version)
{
std::fstream fd(buildh.c_str(), std::ios::in);
std::fstream fd;
std::string build = "#define BUILD 1";
#if !REPRODUCIBLE_BUILD
fd.open(buildh.c_str(), std::ios::in);
if (fd.is_open())
{
for (std::string filebuf; getline(fd, filebuf);)
{
if (!filebuf.find("#define BUILD"))
if (!filebuf.find("#define BUILD\t"))
{
size_t tab = filebuf.find(' ');
@@ -101,6 +107,8 @@ static bool write_build_h(const std::string &buildh, const std::string &git_vers
}
fd.clear();
#endif
fd.open(buildh.c_str(), std::ios::out);
if (!fd.is_open())
{
@@ -111,6 +119,13 @@ static bool write_build_h(const std::string &buildh, const std::string &git_vers
fd << "/* This file is automatically generated by version.cpp - do not edit it! */" << std::endl
<< "#pragma once" << std::endl
<< build << std::endl;
#if !REPRODUCIBLE_BUILD
auto time_now = time(NULL);
auto *local_tm = localtime(&time_now);
char buffer[100];
strftime(buffer, sizeof(buffer), "%a %b %e %Y %T %Z", local_tm);
fd << "#define BUILD_DATE \"" << buffer << "\"" << std::endl;
#endif
if (!git_version.empty())
fd << "#define VERSION_GIT \"" << git_version << "\"" << std::endl;
fd.close();
+256 -227
View File
@@ -16,13 +16,13 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-04-26 18:25+0100\n"
"PO-Revision-Date: 2026-04-26 18:25+0100\n"
"Last-Translator: Sadie Powell <sadie@witchery.services>\n"
"POT-Creation-Date: 2026-07-09 21:01+0100\n"
"PO-Revision-Date: 2026-07-09 21:02+0100\n"
"Last-Translator: Sadie Powell <sadie@sadiepowell.dev>\n"
"Language-Team: English\n"
"Language: en_US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.4.2\n"
@@ -129,7 +129,12 @@ msgstr ""
msgid "%s already exists on the EXCEPTION list."
msgstr ""
#: ../include/language.h
#: ../modules/chanserv/cs_flags.cpp
#, c-format
msgid "%s can not be migrated to the %s access system because they have no migratable privileges."
msgstr ""
#: ../modules/chanserv/cs_flags.cpp
#, c-format
msgid "%s can not be migrated to the %s access system because they have privileges that you do not."
msgstr ""
@@ -141,7 +146,7 @@ msgstr ""
#: ../modules/operserv/os_mode.cpp
#, c-format
msgid "%s changed your usermodes to %s."
msgid "%s changed your user modes to %s."
msgstr ""
#: ../modules/operserv/os_list.cpp
@@ -215,7 +220,7 @@ msgstr ""
msgid "%s has been joined to %s."
msgstr ""
#: ../include/language.h
#: ../modules/chanserv/cs_flags.cpp
#, c-format
msgid "%s has been migrated to the %s access system."
msgstr ""
@@ -428,14 +433,21 @@ msgstr ""
msgid "%s will now permanently be ignored."
msgstr ""
#: ../include/language.h
#: ../modules/chanserv/cs_flags.cpp
#, c-format
msgid "%u entry can not be migrated to the %s access system because they have no migratable privileges."
msgid_plural "%u entries can not be migrated to the %s access system because they have no migratable privileges."
msgstr[0] ""
msgstr[1] ""
#: ../modules/chanserv/cs_flags.cpp
#, c-format
msgid "%u entry can not be migrated to the %s access system because they have privileges that you do not."
msgid_plural "%u entries can not be migrated to the %s access system because they have privileges that you do not."
msgstr[0] ""
msgstr[1] ""
#: ../include/language.h
#: ../modules/chanserv/cs_flags.cpp
#, c-format
msgid "%u entry has been migrated to the %s access system."
msgid_plural "%u entries have been migrated to the %s access system."
@@ -1007,6 +1019,13 @@ msgstr ""
msgid "user [reason]"
msgstr ""
#: ../modules/nickserv/ns_set_timezone.cpp
#, c-format
msgid " %s (%zu timezone)"
msgid_plural " %s (%zu timezones)"
msgstr[0] ""
msgstr[1] ""
#: ../modules/operserv/os_oper.cpp
#, c-format
msgid " %s is online using this oper block."
@@ -1845,11 +1864,11 @@ msgid "Activate the requested vhost for the given nick."
msgstr ""
#: ../modules/hostserv/hs_on.cpp
msgid "Activates the vhost currently assigned to the nick in use. When you use this command any user who performs a /whois on you will see the vhost instead of your real host/IP address."
msgid "Activate your assigned vhost"
msgstr ""
#: ../modules/hostserv/hs_on.cpp
msgid "Activates your assigned vhost"
msgid "Activates the vhost currently assigned to the nick in use. When you use this command any user who performs a /whois on you will see the vhost instead of your real host/IP address."
msgstr ""
#: ../modules/botserv/bs_badwords.cpp
@@ -2339,7 +2358,7 @@ msgid "As a Services Operator, you may drop any nick."
msgstr ""
#: ../modules/botserv/bs_assign.cpp
msgid "Assigns a bot to a channel"
msgid "Assign a bot to a channel"
msgstr ""
#: ../modules/botserv/bs_assign.cpp
@@ -2452,6 +2471,10 @@ msgstr ""
msgid "Bad words list is now empty."
msgstr ""
#: ../modules/chanserv/cs_ban.cpp
msgid "Ban a given nick or mask on a channel"
msgstr ""
#: ../modules/botserv/bs_set.cpp
msgid "Ban expiry may not be longer than 1 day."
msgstr ""
@@ -2471,14 +2494,7 @@ msgid "Ban type for channel %s is now #%d."
msgstr ""
#: ../modules/chanserv/cs_ban.cpp
msgid "Bans a given nick or mask on a channel"
msgstr ""
#: ../modules/chanserv/cs_ban.cpp
msgid ""
"Bans a given nick or mask on a channel. An optional expiry may be given to cause services to remove the ban after a set amount of time.\n"
"\n"
"By default, limited to AOPs or those with level 5 access and above on the channel. Channel founders may ban masks."
msgid "Bans a given nick or mask on a channel. An optional expiry may be given to cause services to remove the ban after a set amount of time. Channel founders may ban masks."
msgstr ""
#: ../modules/chanserv/cs_enforce.cpp
@@ -2671,6 +2687,11 @@ msgstr ""
msgid "Bot won't kick for repeats anymore."
msgstr ""
#: ../src/access.cpp
#, c-format
msgid "By default, the %s command is limited to:"
msgstr ""
#: ../modules/operserv/os_info.cpp
msgid "CLEAR target"
msgstr ""
@@ -2751,7 +2772,7 @@ msgstr ""
#: ../modules/operserv/os_mode.cpp
#, c-format
msgid "Changed usermodes of %s to %s."
msgid "Changed user modes of %s to %s."
msgstr ""
#: ../modules/botserv/bs_bot.cpp
@@ -2826,7 +2847,7 @@ msgstr ""
#: ../src/users.cpp
#, c-format
msgid "Changing your usermodes to %s"
msgid "Changing your user modes to %s"
msgstr ""
#: ../src/users.cpp
@@ -2997,12 +3018,12 @@ msgstr ""
msgid "Chanstats statistics are now enabled for your nick."
msgstr ""
#: ../modules/chanserv/cs_seen.cpp
msgid "Checks for the last time nick was seen joining, leaving, or changing nick on the network and tells you when and, depending on channel or user settings, where it was."
#: ../modules/memoserv/ms_check.cpp
msgid "Check if last memo to a nick was read"
msgstr ""
#: ../modules/memoserv/ms_check.cpp
msgid "Checks if last memo to a nick was read"
#: ../modules/chanserv/cs_seen.cpp
msgid "Checks for the last time nick was seen joining, leaving, or changing nick on the network and tells you when and, depending on channel or user settings, where it was."
msgstr ""
#: ../modules/memoserv/ms_check.cpp
@@ -3031,25 +3052,73 @@ msgid "Command"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures AMSG kicker"
msgid "Configure AMSG kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures badwords kicker"
msgid "Configure badwords kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures bolds kicker"
msgid "Configure bolds kicker"
msgstr ""
#: ../modules/botserv/bs_set.cpp
msgid "Configure bot options"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure caps kicker"
msgstr ""
#: ../modules/chanserv/cs_log.cpp
msgid "Configure channel logging settings"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure color kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure flood kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure italics kicker"
msgstr ""
#: ../modules/nickserv/ns_set_keepmodes.cpp
msgid "Configure keeping user modes set across connections"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure kickers"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure repeat kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure reverses kicker"
msgstr ""
#: ../modules/nickserv/ns_set_layout.cpp
msgid "Configure the layout used for services messages"
msgstr ""
#: ../modules/botserv/bs_set.cpp
msgid "Configure the time bot bans expire in"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configure underlines kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures bot kickers. option can be one of:"
msgstr ""
#: ../modules/botserv/bs_set.cpp
msgid "Configures bot options"
msgstr ""
#: ../modules/botserv/bs_set.cpp
msgid ""
"Configures bot options.\n"
@@ -3057,36 +3126,8 @@ msgid ""
"Available options:"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures caps kicker"
msgstr ""
#: ../modules/chanserv/cs_log.cpp
msgid "Configures channel logging settings"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures color kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures flood kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures italics kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures kickers"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures repeat kicker"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures reverses kicker"
#: ../modules/nickserv/ns_set_keepmodes.cpp
msgid "Configures keeping user modes set across connections. If this is enabled, your last user modes will be remembered and will be re-set the next time you identify."
msgstr ""
#: ../modules/nickserv/ns_set_layout.cpp
@@ -3100,10 +3141,6 @@ msgid ""
"When the layout is set to MONOSPACE services will format messages similar to FIXED but will prefix all messages with a monospace formatting character to force it to display correctly. This requires client support for monospace text formatting."
msgstr ""
#: ../modules/nickserv/ns_set_layout.cpp
msgid "Configures the layout used for services messages"
msgstr ""
#: ../modules/nickserv/ns_set_layout.cpp
msgid ""
"Configures the layout used for services messages.\n"
@@ -3115,14 +3152,6 @@ msgid ""
"When the layout is set to MONOSPACE services will format messages similar to FIXED but will prefix all messages with a monospace formatting character to force it to display correctly. This requires client support for monospace text formatting."
msgstr ""
#: ../modules/botserv/bs_set.cpp
msgid "Configures the time bot bans expire in"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Configures underlines kicker"
msgstr ""
#: ../modules/nickserv/ns_register.cpp
msgid "Confirm a previous account registration"
msgstr ""
@@ -3311,11 +3340,11 @@ msgid "Date/Time"
msgstr ""
#: ../modules/hostserv/hs_off.cpp
msgid "Deactivates the vhost currently assigned to the nick in use. When you use this command any user who performs a /whois on you will see your real host/IP address."
msgid "Deactivate your assigned vhost"
msgstr ""
#: ../modules/hostserv/hs_off.cpp
msgid "Deactivates your assigned vhost"
msgid "Deactivates the vhost currently assigned to the nick in use. When you use this command any user who performs a /whois on you will see your real host/IP address."
msgstr ""
#: ../modules/chanserv/cs_access.cpp
@@ -3348,6 +3377,10 @@ msgstr ""
msgid "Delete a memo or memos"
msgstr ""
#: ../modules/hostserv/hs_del.cpp
msgid "Delete the vhost for all nicks in an account"
msgstr ""
#: ../modules/hostserv/hs_del.cpp
msgid "Delete the vhost of another user"
msgstr ""
@@ -3488,10 +3521,6 @@ msgstr ""
msgid "Deletes the vhost assigned to the given nick from the database."
msgstr ""
#: ../modules/hostserv/hs_del.cpp
msgid "Deletes the vhost for all nicks in an account"
msgstr ""
#: ../modules/hostserv/hs_del.cpp
msgid "Deletes the vhost for all nicks in the same account as that of the given nick."
msgstr ""
@@ -3537,6 +3566,46 @@ msgid ""
"Reason may be required on certain networks."
msgstr ""
#: ../modules/nickserv/ns_info.cpp
msgid "Display information about a given nickname"
msgstr ""
#: ../modules/memoserv/ms_info.cpp
msgid "Display information about your memos"
msgstr ""
#: ../modules/hostserv/hs_list.cpp
msgid "Display one or more vhost entries"
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Display the top 10 users of a channel"
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Display the top 10 users of the network"
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Display the top 3 users of a channel"
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Display the top 3 users of the network"
msgstr ""
#: ../modules/help.cpp
msgid "Display this list and give information about commands"
msgstr ""
#: ../modules/chanserv/cs_fantasy_stats.cpp
msgid "Display your Channel Stats"
msgstr ""
#: ../modules/chanserv/cs_fantasy_stats.cpp
msgid "Display your Global Stats"
msgstr ""
#: ../modules/hostserv/hs_request.cpp
#, c-format
msgid "Displayed %d records (%d total)."
@@ -3565,26 +3634,14 @@ msgstr ""
msgid "Displays any new memos."
msgstr ""
#: ../modules/nickserv/ns_info.cpp
msgid "Displays information about a given nickname"
msgstr ""
#: ../modules/nickserv/ns_info.cpp
msgid "Displays information about the given nickname, such as the nick's owner, last seen address and time, and nick options. If no nick is given, and you are identified, your account name is used, else your current nickname is used."
msgstr ""
#: ../modules/memoserv/ms_info.cpp
msgid "Displays information about your memos"
msgstr ""
#: ../modules/memoserv/ms_read.cpp
msgid "Displays memos numbered 2 through 5 and 7 through 9."
msgstr ""
#: ../modules/hostserv/hs_list.cpp
msgid "Displays one or more vhost entries"
msgstr ""
#: ../modules/nickserv/ns_cert.cpp
msgid "Displays the current certificate list of nickname as well as the details about who added each entry and when they added it."
msgstr ""
@@ -3593,34 +3650,6 @@ msgstr ""
msgid "Displays the current certificate list of nickname."
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Displays the top 10 users of a channel"
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Displays the top 10 users of the network"
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Displays the top 3 users of a channel"
msgstr ""
#: ../modules/chanserv/cs_fantasy_top.cpp
msgid "Displays the top 3 users of the network"
msgstr ""
#: ../modules/help.cpp
msgid "Displays this list and give information about commands"
msgstr ""
#: ../modules/chanserv/cs_fantasy_stats.cpp
msgid "Displays your Channel Stats"
msgstr ""
#: ../modules/chanserv/cs_fantasy_stats.cpp
msgid "Displays your Global Stats"
msgstr ""
#: ../modules/nickserv/ns_cert.cpp
msgid "Displays your current certificate list as well the details about who added each entry and when they added it."
msgstr ""
@@ -3712,10 +3741,6 @@ msgstr ""
msgid "Enable greet messages"
msgstr ""
#: ../modules/nickserv/ns_set_keepmodes.cpp
msgid "Enable or disable keep modes"
msgstr ""
#: ../modules/botserv/bs_info.cpp ../modules/botserv/bs_kick.cpp
msgid "Enabled"
msgstr ""
@@ -3750,11 +3775,7 @@ msgid "Enables or disables keepmodes for the given channel. If keep modes is ena
msgstr ""
#: ../modules/nickserv/ns_set_keepmodes.cpp
msgid "Enables or disables keepmodes for the given nick. If keep modes is enabled, services will remember users' usermodes and attempt to re-set them the next time they authenticate."
msgstr ""
#: ../modules/nickserv/ns_set_keepmodes.cpp
msgid "Enables or disables keepmodes for your nick. If keep modes is enabled, services will remember your usermodes and attempt to re-set them the next time you authenticate."
msgid "Enables or disables keepmodes for the given nick. If keep modes is enabled, services will remember users' user modes and attempt to re-set them the next time they authenticate."
msgstr ""
#: ../modules/chanserv/cs_set.cpp
@@ -4000,6 +4021,10 @@ msgstr ""
msgid "Fixed layout"
msgstr ""
#: ../modules/chanserv/cs_flags.cpp
msgid "Flag"
msgstr ""
#: ../modules/chanserv/cs_flags.cpp
msgid "Flags"
msgstr ""
@@ -4127,10 +4152,6 @@ msgstr ""
msgid "Greet mode is now on on channel %s."
msgstr ""
#: ../modules/nickserv/ns_resetpass.cpp
msgid "Helps you reset lost passwords"
msgstr ""
#: ../modules/nickserv/ns_info.cpp
msgid "Hide certain pieces of nickname information"
msgstr ""
@@ -4263,7 +4284,7 @@ msgid "Invalid value for LIMIT. Must be numerical."
msgstr ""
#: ../modules/chanserv/cs_invite.cpp
msgid "Invites you or an optionally specified nick into a channel"
msgid "Invite you or an optionally specified nick into a channel"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
@@ -4293,6 +4314,10 @@ msgstr ""
msgid "Key for channel %s is %s."
msgstr ""
#: ../modules/chanserv/cs_kick.cpp
msgid "Kick a specified nick from a channel"
msgstr ""
#: ../modules/operserv/os_kick.cpp
msgid "Kick a user from a channel"
msgstr ""
@@ -4303,14 +4328,7 @@ msgid "Kicked %d/%d users matching %s from %s."
msgstr ""
#: ../modules/chanserv/cs_kick.cpp
msgid "Kicks a specified nick from a channel"
msgstr ""
#: ../modules/chanserv/cs_kick.cpp
msgid ""
"Kicks a specified nick from a channel.\n"
"\n"
"By default, limited to AOPs or those with level 5 access and above on the channel. Channel founders can also specify masks."
msgid "Kicks a specified nick from a channel. Channel founders can also specify masks."
msgstr ""
#: ../modules/operserv/os_kill.cpp
@@ -4424,10 +4442,30 @@ msgstr ""
msgid "Limit"
msgstr ""
#: ../modules/operserv/os_list.cpp
msgid "List all channel records"
msgstr ""
#: ../modules/nickserv/ns_group.cpp
msgid "List all nicknames in your account"
msgstr ""
#: ../modules/chanserv/cs_list.cpp
msgid "List all registered channels matching the given pattern"
msgstr ""
#: ../modules/nickserv/ns_list.cpp
msgid "List all registered nicknames that match a given pattern"
msgstr ""
#: ../modules/operserv/os_list.cpp
msgid "List all user records"
msgstr ""
#: ../modules/botserv/bs_botlist.cpp
msgid "List available bots"
msgstr ""
#: ../modules/nickserv/ns_alist.cpp
msgid "List channels you have access on"
msgstr ""
@@ -4437,6 +4475,10 @@ msgstr ""
msgid "List for modes %s is full."
msgstr ""
#: ../modules/chanserv/cs_info.cpp
msgid "List information about the specified registered channel"
msgstr ""
#: ../modules/operserv/os_modinfo.cpp
msgid "List loaded modules"
msgstr ""
@@ -4520,10 +4562,6 @@ msgstr ""
msgid "Lists all bad word entries set on #channel."
msgstr ""
#: ../modules/operserv/os_list.cpp
msgid "Lists all channel records"
msgstr ""
#: ../modules/operserv/os_list.cpp
msgid ""
"Lists all channels currently in use on the IRC network, whether they are registered or not.\n"
@@ -4538,18 +4576,10 @@ msgid ""
"Channels that have the NOEXPIRE option set will be prefixed by an exclamation mark. The nickname parameter is limited to Services Operators."
msgstr ""
#: ../modules/nickserv/ns_group.cpp
msgid "Lists all nicknames in your account"
msgstr ""
#: ../modules/nickserv/ns_group.cpp
msgid "Lists all nicknames that belong to your account."
msgstr ""
#: ../modules/chanserv/cs_list.cpp
msgid "Lists all registered channels matching the given pattern"
msgstr ""
#: ../modules/chanserv/cs_list.cpp
msgid ""
"Lists all registered channels matching the given pattern. Channels with the PRIVATE option set will only be displayed to Services Operators with the proper access. Channels with the NOEXPIRE option set will have a ! prefixed to the channel for Services Operators to see.\n"
@@ -4608,10 +4638,6 @@ msgstr ""
msgid "Lists all registered nicks within the given range (51-100)."
msgstr ""
#: ../modules/operserv/os_list.cpp
msgid "Lists all user records"
msgstr ""
#: ../modules/operserv/os_list.cpp
msgid ""
"Lists all users currently online on the IRC network, whether their nick is registered or not.\n"
@@ -4627,10 +4653,6 @@ msgstr ""
msgid "Lists any new memos."
msgstr ""
#: ../modules/botserv/bs_botlist.cpp
msgid "Lists available bots"
msgstr ""
#: ../modules/botserv/bs_badwords.cpp
msgid "Lists bad word entries set on #channel numbered 2 through 5 and 7 through 9."
msgstr ""
@@ -4643,10 +4665,6 @@ msgstr ""
msgid "Lists currently loaded modules."
msgstr ""
#: ../modules/chanserv/cs_info.cpp
msgid "Lists information about the specified registered channel"
msgstr ""
#: ../modules/chanserv/cs_info.cpp
msgid "Lists information about the specified registered channel, including its founder, time of registration, last time used, and description. If the user issuing the command has the appropriate access for it, then the successor, last topic set, settings and expiration time will also be displayed when applicable."
msgstr ""
@@ -4729,12 +4747,16 @@ msgid ""
"The %sCLEAR command is an easy way to clear modes on a channel. what may be any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If what is not given then all basic modes are removed."
msgstr ""
#: ../modules/botserv/bs_bot.cpp
msgid "Maintain network bot list"
msgstr ""
#: ../modules/chanserv/cs_akick.cpp
msgid "Maintain the AutoKick list"
msgstr ""
#: ../modules/botserv/bs_bot.cpp
msgid "Maintains network bot list"
#: ../modules/botserv/bs_badwords.cpp
msgid "Maintain the bad words list"
msgstr ""
#: ../modules/chanserv/cs_xop.cpp
@@ -4782,22 +4804,18 @@ msgid ""
"The CLEAR command clears all entries from the bad words list."
msgstr ""
#: ../modules/botserv/bs_badwords.cpp
msgid "Maintains the bad words list"
#: ../modules/botserv/bs_control.cpp
msgid "Make the bot do the equivalent of a \"/me\" command"
msgstr ""
#: ../modules/botserv/bs_control.cpp
msgid "Makes the bot do the equivalent of a \"/me\" command"
msgid "Make the bot say the specified text on the specified channel"
msgstr ""
#: ../modules/botserv/bs_control.cpp
msgid "Makes the bot do the equivalent of a \"/me\" command on the specified channel using the specified text."
msgstr ""
#: ../modules/botserv/bs_control.cpp
msgid "Makes the bot say the specified text on the specified channel"
msgstr ""
#: ../modules/botserv/bs_control.cpp
msgid "Makes the bot say the specified text on the specified channel."
msgstr ""
@@ -4819,7 +4837,7 @@ msgid "Manage your auto join list"
msgstr ""
#: ../modules/global/gl_queue.cpp
msgid "Manages your pending message queue."
msgid "Manage your pending message queue."
msgstr ""
#: ../modules/operserv/os_sxline.cpp
@@ -4863,7 +4881,7 @@ msgid "Masks and unregistered users may not be on access lists."
msgstr ""
#: ../modules/nickserv/ns_email.cpp
msgid "Matches and returns all users that registered using given email address"
msgid "Match and return all users that registered using given email address"
msgstr ""
#: ../modules/operserv/os_logsearch.cpp
@@ -5780,7 +5798,7 @@ msgid "Redefine the meanings of access levels"
msgstr ""
#: ../modules/nickserv/ns_recover.cpp
msgid "Regains control of your nick"
msgid "Regain control of your nick"
msgstr ""
#: ../modules/operserv/os_akill.cpp ../modules/operserv/os_sxline.cpp
@@ -5866,7 +5884,7 @@ msgid "Reject the requested vhost of a user"
msgstr ""
#: ../modules/chanserv/cs_suspend.cpp
msgid "Releases a suspended channel"
msgid "Release a suspended channel"
msgstr ""
#: ../modules/chanserv/cs_suspend.cpp
@@ -5885,6 +5903,10 @@ msgstr ""
msgid "Remove a nick from an account"
msgstr ""
#: ../modules/chanserv/cs_updown.cpp
msgid "Remove a selected nicks status from a channel"
msgstr ""
#: ../modules/chanserv/cs_unban.cpp
msgid "Remove all bans preventing a user from entering a channel"
msgstr ""
@@ -5918,10 +5940,6 @@ msgstr ""
msgid "Removes %s status from you or the specified nick on a channel"
msgstr ""
#: ../modules/chanserv/cs_updown.cpp
msgid "Removes a selected nicks status from a channel"
msgstr ""
#: ../modules/chanserv/cs_updown.cpp
msgid "Removes a selected nicks status modes on a channel. If nick is omitted then your status is removed. If channel is omitted then your channel status is removed on every channel you are in."
msgstr ""
@@ -6003,11 +6021,11 @@ msgid "Retain topic when channel is not in use"
msgstr ""
#: ../modules/hostserv/hs_request.cpp
msgid "Retrieves the vhost requests"
msgid "Retrieve the vhost requests"
msgstr ""
#: ../modules/chanserv/cs_getkey.cpp
msgid "Returns the key of the given channel"
msgid "Return the key of the given channel"
msgstr ""
#: ../modules/chanserv/cs_getkey.cpp
@@ -6018,6 +6036,10 @@ msgstr ""
msgid "Returns the matching accounts that used given email."
msgstr ""
#: ../modules/nickserv/ns_logout.cpp
msgid "Reverse the effect of the IDENTIFY command"
msgstr ""
#: ../modules/botserv/bs_kick.cpp
msgid "Reverses kicker"
msgstr ""
@@ -6026,10 +6048,6 @@ msgstr ""
msgid "Reverses the effect of the IDENTIFY command, i.e. make you not recognized as the real owner of the nick anymore. Note, however, that you won't be asked to reidentify yourself."
msgstr ""
#: ../modules/nickserv/ns_logout.cpp
msgid "Reverses the effect of the IDENTIFY command"
msgstr ""
#: ../modules/operserv/os_noop.cpp
msgid "SET server"
msgstr ""
@@ -6062,7 +6080,7 @@ msgid "Save databases and restart services"
msgstr ""
#: ../modules/operserv/os_logsearch.cpp
msgid "Searches logs for a matching pattern"
msgid "Search logs for a matching pattern"
msgstr ""
#: ../modules/operserv/os_logsearch.cpp
@@ -6117,6 +6135,10 @@ msgstr ""
msgid "See the %s command (%sACCESS) for information on giving a subset of these privileges to other channel users."
msgstr ""
#: ../modules/memoserv/ms_rsend.cpp
msgid "Send a memo and requests a read receipt"
msgstr ""
#: ../modules/memoserv/ms_send.cpp
msgid "Send a memo to a nick or channel"
msgstr ""
@@ -6137,6 +6159,10 @@ msgstr ""
msgid "Send a message to all users on a server"
msgstr ""
#: ../modules/nickserv/ns_resetpass.cpp
msgid "Send an email to recover access to an account"
msgstr ""
#: ../modules/memoserv/ms_list.cpp
msgid "Sender"
msgstr ""
@@ -6145,10 +6171,6 @@ msgstr ""
msgid "Sends a confirmation code to the nickname's email address with instructions on how to reset their password. email must be the email address associated with the account."
msgstr ""
#: ../modules/memoserv/ms_rsend.cpp
msgid "Sends a memo and requests a read receipt"
msgstr ""
#: ../modules/chanserv/cs_log.cpp
msgid "Sends a memo to the channel when someone uses the chanserv/xop command on #anope."
msgstr ""
@@ -6466,6 +6488,18 @@ msgstr ""
msgid "Set various global services options"
msgstr ""
#: ../modules/nickserv/ns_set_op.cpp
msgid "Set whether services should set channel status modes on you automatically."
msgstr ""
#: ../modules/nickserv/ns_set_op.cpp
msgid "Set whether you can be added to a channel access list."
msgstr ""
#: ../modules/nickserv/ns_cert.cpp
msgid "Set whether you should automatically be logged in when you connect using a known SSL certificate."
msgstr ""
#: ../modules/nickserv/ns_set.cpp
msgid "Set your nickname password"
msgstr ""
@@ -6602,10 +6636,6 @@ msgstr ""
msgid "Sets voice status on all users in the channel."
msgstr ""
#: ../modules/nickserv/ns_set_op.cpp
msgid "Sets whether services should set channel status modes on you automatically."
msgstr ""
#: ../modules/chanserv/cs_set.cpp
msgid "Sets whether the given channel will expire. Setting this to ON prevents the channel from expiring."
msgstr ""
@@ -6632,10 +6662,6 @@ msgstr ""
msgid "Sets whether you can be added to a channel access list."
msgstr ""
#: ../modules/nickserv/ns_cert.cpp
msgid "Sets whether you should automatically be logged in when you connect using a known SSL certificate."
msgstr ""
#: ../modules/nickserv/ns_cert.cpp
#, c-format
msgid "Sets whether you should automatically be logged in when you connect using a known SSL certificate. You can configure your SSL certificate using the %s command."
@@ -6798,6 +6824,10 @@ msgstr ""
msgid "Suspension expires"
msgstr ""
#: ../modules/hostserv/hs_group.cpp
msgid "Sync the vhost for all nicks in an account"
msgstr ""
#: ../modules/chanserv/cs_sync.cpp
msgid "Sync users channel modes"
msgstr ""
@@ -6806,10 +6836,6 @@ msgstr ""
msgid "Syncs all modes set on users on the channel with the modes they should have based on their access."
msgstr ""
#: ../modules/hostserv/hs_group.cpp
msgid "Syncs the vhost for all nicks in an account"
msgstr ""
#: ../src/command.cpp
msgid "Syntax"
msgstr ""
@@ -6889,6 +6915,10 @@ msgstr ""
msgid "TAKE {vhost | entry-num}"
msgstr ""
#: ../modules/chanserv/cs_seen.cpp
msgid "Tell you about the last time a user was seen"
msgstr ""
#: ../modules/nickserv/ns_identify.cpp
#, c-format
msgid "Tells %s that you are really the owner of this nick. Many commands require you to authenticate yourself with this command before you use them. The password should be the same one you sent with the REGISTER command."
@@ -6896,28 +6926,18 @@ msgstr ""
#: ../modules/chanserv/cs_invite.cpp
#, c-format
msgid ""
"Tells %s to invite you or an optionally specified nick into the given channel.\n"
"\n"
"By default, limited to AOPs or those with level 5 access and above on the channel."
msgid "Tells %s to invite you or an optionally specified nick into the given channel."
msgstr ""
#: ../modules/chanserv/cs_unban.cpp
#, c-format
msgid ""
"Tells %s to remove all bans preventing you or the given user from entering the given channel. If no channel is given, all bans affecting you in channels you have access in are removed.\n"
"\n"
"By default, limited to AOPs or those with level 5 access and above on the channel."
msgid "Tells %s to remove all bans preventing you or the given user from entering the given channel. If no channel is given, all bans affecting you in channels you have access in are removed."
msgstr ""
#: ../modules/operserv/os_jupe.cpp
msgid "Tells services to jupiter a server -- that is, to create a fake \"server\" connected to services which prevents the real server of that name from connecting. The jupe may be removed using a standard SQUIT. If a reason is given, it is placed in the server information field; otherwise, the server information field will contain the text \"Juped by <nick>\", showing the nickname of the person who jupitered the server."
msgstr ""
#: ../modules/chanserv/cs_seen.cpp
msgid "Tells you about the last time a user was seen"
msgstr ""
#: ../modules/operserv/os_shutdown.cpp
msgid "Terminate services WITHOUT saving"
msgstr ""
@@ -7234,6 +7254,11 @@ msgstr ""
msgid "The registration confirmation code you specified for %s is incorrect."
msgstr ""
#: ../modules/nickserv/ns_register.cpp
#, c-format
msgid "The registration of %s can only be confirmed by an administrator."
msgstr ""
#: ../modules/nickserv/ns_info.cpp
#, c-format
msgid "The services access status of %s will now be hidden from %s INFO displays."
@@ -7654,7 +7679,7 @@ msgid "Unable to remove module %s."
msgstr ""
#: ../modules/botserv/bs_assign.cpp
msgid "Unassigns a bot from a channel"
msgid "Unassign a bot from a channel"
msgstr ""
#: ../modules/botserv/bs_assign.cpp
@@ -7746,15 +7771,15 @@ msgid "Unsuspends a nickname which allows it to be used again."
msgstr ""
#: ../modules/chanserv/cs_updown.cpp
msgid "Updates a selected nicks status modes on a channel. If nick is omitted then your status is updated. If channel is omitted then your channel status is updated on every channel you are in."
msgstr ""
#: ../modules/chanserv/cs_updown.cpp
msgid "Updates a selected nicks status on a channel"
msgid "Update a selected nicks status on a channel"
msgstr ""
#: ../modules/nickserv/ns_update.cpp
msgid "Updates your current status, i.e. it checks for new memos"
msgid "Update your current status, i.e. it checks for new memos"
msgstr ""
#: ../modules/chanserv/cs_updown.cpp
msgid "Updates a selected nicks status modes on a channel. If nick is omitted then your status is updated. If channel is omitted then your channel status is updated on every channel you are in."
msgstr ""
#: ../modules/nickserv/ns_update.cpp
@@ -7903,7 +7928,7 @@ msgid "VIEW [vhost-mask | entry-num | list]"
msgstr ""
#: ../modules/hostserv/hs_request.cpp
msgid "Validates a previously requested vhost using DNS"
msgid "Validate a previously requested vhost using DNS"
msgstr ""
#: ../modules/hostserv/hs_request.cpp
@@ -7990,6 +8015,10 @@ msgstr ""
msgid "Word"
msgstr ""
#: ../modules/chanserv/cs_xop.cpp
msgid "XOP"
msgstr ""
#: ../modules/nickserv/ns_group.cpp
#, c-format
msgid "You are already a member of the account of %s."
+2001 -13
View File
File diff suppressed because it is too large Load Diff
+2000 -12
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -24,7 +24,6 @@ find ../ \
-print0 | sort -z | xargs -0 -I {} \
xgettext \
--language=C++ \
--sort-output \
--default-domain=Anope \
--join-existing \
--output=anope.pot \
+7 -1
View File
@@ -50,7 +50,7 @@ macro(inline_cmake TARGET FILE)
set(CODE "${CODE}\n${CLEAN_LINE}")
endif()
elseif(LINE MATCHES "^/// BEGIN CMAKE$")
message(STATUS "Executing inline CMake code for ${TARGET}")
message(DEBUG "Executing inline CMake code for ${TARGET}")
set(IN_CODE ON)
endif()
endforeach()
@@ -77,6 +77,12 @@ macro(build_module SRC MODULE_SRC)
PREFIX ""
SUFFIX ""
)
list(LENGTH MODULE_SRC MODULE_SRC_COUNT)
if(MODULE_SRC_COUNT LESS_EQUAL 1)
set_target_properties(${SO} PROPERTIES
UNITY_BUILD OFF
)
endif()
add_dependencies(${SO} ${PROGRAM_NAME})
if(HAVE_LOCALIZATION)
add_dependencies(${SO} module_language)
+2 -2
View File
@@ -20,7 +20,7 @@ class CommandBSAssign final
public:
CommandBSAssign(Module *creator) : Command(creator, "botserv/assign", 2, 2)
{
this->SetDesc(_("Assigns a bot to a channel"));
this->SetDesc(_("Assign a bot to a channel"));
this->SetSyntax(_("\037channel\037 \037nick\037"));
}
@@ -101,7 +101,7 @@ class CommandBSUnassign final
public:
CommandBSUnassign(Module *creator) : Command(creator, "botserv/unassign", 1, 1)
{
this->SetDesc(_("Unassigns a bot from a channel"));
this->SetDesc(_("Unassign a bot from a channel"));
this->SetSyntax(_("\037channel\037"));
}
+1 -1
View File
@@ -416,7 +416,7 @@ private:
public:
CommandBSBadwords(Module *creator) : Command(creator, "botserv/badwords", 2, 3)
{
this->SetDesc(_("Maintains the bad words list"));
this->SetDesc(_("Maintain the bad words list"));
this->SetSyntax(_("\037channel\037 ADD \037word\037 [\037SINGLE\037 | \037START\037 | \037END\037]"));
this->SetSyntax(_("\037channel\037 DEL {\037word\037 | \037entry-num\037 | \037list\037}"));
this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]"));
+1 -1
View File
@@ -264,7 +264,7 @@ private:
public:
CommandBSBot(Module *creator) : Command(creator, "botserv/bot", 1, 6)
{
this->SetDesc(_("Maintains network bot list"));
this->SetDesc(_("Maintain network bot list"));
this->SetSyntax(_("\002ADD \037nick\037 \037user\037 \037host\037 \037real\037\002"));
this->SetSyntax(_("\002CHANGE \037oldnick\037 \037newnick\037 [\037user\037 [\037host\037 [\037real\037]]]\002"));
this->SetSyntax(_("\002DEL \037nick\037\002"));
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandBSBotList final
public:
CommandBSBotList(Module *creator) : Command(creator, "botserv/botlist", 0, 1)
{
this->SetDesc(_("Lists available bots"));
this->SetDesc(_("List available bots"));
this->SetSyntax("[OPERONLY] [UNUSED] [VANITY]");
}
+2 -2
View File
@@ -20,7 +20,7 @@ class CommandBSSay final
public:
CommandBSSay(Module *creator) : Command(creator, "botserv/say", 2, 2)
{
this->SetDesc(_("Makes the bot say the specified text on the specified channel"));
this->SetDesc(_("Make the bot say the specified text on the specified channel"));
this->SetSyntax(_("\037channel\037 \037text\037"));
}
@@ -88,7 +88,7 @@ class CommandBSAct final
public:
CommandBSAct(Module *creator) : Command(creator, "botserv/act", 2, 2)
{
this->SetDesc(_("Makes the bot do the equivalent of a \"/me\" command"));
this->SetDesc(_("Make the bot do the equivalent of a \"/me\" command"));
this->SetSyntax(_("\037channel\037 \037text\037"));
}
+14 -13
View File
@@ -129,7 +129,7 @@ class CommandBSKick final
public:
CommandBSKick(Module *creator) : Command(creator, "botserv/kick", 0)
{
this->SetDesc(_("Configures kickers"));
this->SetDesc(_("Configure kickers"));
this->SetSyntax(_("\037option\037 \037channel\037 {\037ON|OFF\037} [\037settings\037]"));
}
@@ -258,7 +258,7 @@ class CommandBSKickAMSG final
public:
CommandBSKickAMSG(Module *creator) : CommandBSKickBase(creator, "botserv/kick/amsg", 2, 3)
{
this->SetDesc(_("Configures AMSG kicker"));
this->SetDesc(_("Configure AMSG kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
@@ -298,7 +298,7 @@ class CommandBSKickBadwords final
public:
CommandBSKickBadwords(Module *creator) : CommandBSKickBase(creator, "botserv/kick/badwords", 2, 3)
{
this->SetDesc(_("Configures badwords kicker"));
this->SetDesc(_("Configure badwords kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
@@ -342,7 +342,7 @@ class CommandBSKickBolds final
public:
CommandBSKickBolds(Module *creator) : CommandBSKickBase(creator, "botserv/kick/bolds", 2, 3)
{
this->SetDesc(_("Configures bolds kicker"));
this->SetDesc(_("Configure bolds kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
@@ -379,7 +379,7 @@ class CommandBSKickCaps final
public:
CommandBSKickCaps(Module *creator) : CommandBSKickBase(creator, "botserv/kick/caps", 2, 5)
{
this->SetDesc(_("Configures caps kicker"));
this->SetDesc(_("Configure caps kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037min\037 [\037percent\037]]]\002"));
}
@@ -475,7 +475,7 @@ class CommandBSKickColors final
public:
CommandBSKickColors(Module *creator) : CommandBSKickBase(creator, "botserv/kick/colors", 2, 3)
{
this->SetDesc(_("Configures color kicker"));
this->SetDesc(_("Configure color kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
@@ -512,7 +512,7 @@ class CommandBSKickFlood final
public:
CommandBSKickFlood(Module *creator) : CommandBSKickBase(creator, "botserv/kick/flood", 2, 5)
{
this->SetDesc(_("Configures flood kicker"));
this->SetDesc(_("Configure flood kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037ln\037 [\037secs\037]]]\002"));
}
@@ -602,7 +602,7 @@ class CommandBSKickItalics final
public:
CommandBSKickItalics(Module *creator) : CommandBSKickBase(creator, "botserv/kick/italics", 2, 3)
{
this->SetDesc(_("Configures italics kicker"));
this->SetDesc(_("Configure italics kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
@@ -639,7 +639,7 @@ class CommandBSKickRepeat final
public:
CommandBSKickRepeat(Module *creator) : CommandBSKickBase(creator, "botserv/kick/repeat", 2, 4)
{
this->SetDesc(_("Configures repeat kicker"));
this->SetDesc(_("Configure repeat kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037num\037]]\002"));
}
@@ -750,7 +750,7 @@ class CommandBSKickReverses final
public:
CommandBSKickReverses(Module *creator) : CommandBSKickBase(creator, "botserv/kick/reverses", 2, 3)
{
this->SetDesc(_("Configures reverses kicker"));
this->SetDesc(_("Configure reverses kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
@@ -787,7 +787,7 @@ class CommandBSKickUnderlines final
public:
CommandBSKickUnderlines(Module *creator) : CommandBSKickBase(creator, "botserv/kick/underlines", 2, 3)
{
this->SetDesc(_("Configures underlines kicker"));
this->SetDesc(_("Configure underlines kicker"));
this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]"));
}
@@ -1030,11 +1030,11 @@ class BanDataPurger final
{
public:
BanDataPurger(Module *o)
: Timer(o, 300, true)
: Timer(o, 300)
{
}
void Tick() override
bool Tick() override
{
Log(LOG_DEBUG) << "bs_main: Running bandata purger";
@@ -1048,6 +1048,7 @@ public:
c->Shrink<BanData>("bandata");
}
}
return true;
}
};
+4 -3
View File
@@ -20,7 +20,7 @@ class CommandBSSet final
public:
CommandBSSet(Module *creator) : Command(creator, "botserv/set", 3, 3)
{
this->SetDesc(_("Configures bot options"));
this->SetDesc(_("Configure bot options"));
this->SetSyntax(_("\037option\037 \037(channel | bot)\037 \037settings\037"));
}
@@ -92,17 +92,18 @@ public:
{
}
void Tick() override
bool Tick() override
{
Channel *c = Channel::Find(chname);
if (c)
c->RemoveMode(NULL, "BAN", mask);
return false;
}
};
CommandBSSetBanExpire(Module *creator, const Anope::string &sname = "botserv/set/banexpire") : Command(creator, sname, 2, 2)
{
this->SetDesc(_("Configures the time bot bans expire in"));
this->SetDesc(_("Configure the time bot bans expire in"));
this->SetSyntax(_("\037channel\037 \037time\037"));
}
+4 -2
View File
@@ -82,10 +82,10 @@ public:
/** Called when the delay is up
* @param The current time
*/
void Tick() override
bool Tick() override
{
if (!c)
return;
return false; // Dead channel.
/* In the event we don't part */
c->RemoveMode(NULL, "SECRET");
@@ -101,6 +101,8 @@ public:
/* If someone has rejoined this channel in the meantime, don't part the bot */
else if (c->users.size() <= 1)
c->ci->bi->Part(c);
return false;
}
};
+8 -3
View File
@@ -92,6 +92,13 @@ public:
{
return new AccessChanAccess(this);
}
void GetAccess(CommandSource& source, const Privilege *p, Anope::map<Anope::string> &access) override
{
auto it = defaultLevels.find(p->name);
if (it != defaultLevels.end())
access[_("Level")] = LevelToString(source, it->second);
}
};
AccessAccessProvider *AccessAccessProvider::me;
@@ -956,10 +963,8 @@ public:
{
defaultLevels.clear();
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
for (const auto &[_, priv] : conf.GetBlocks("privilege"))
{
const auto &priv = conf.GetBlock("privilege", i);
const Anope::string &pname = priv.Get<const Anope::string>("name");
Privilege *p = PrivilegeManager::FindPrivilege(pname);
+16 -7
View File
@@ -28,6 +28,8 @@ private:
Anope::string mode;
public:
bool ticked = false;
TempBan(time_t seconds, Channel *c, const Anope::string &banmask, const Anope::string &mod)
: Timer(me, seconds)
, channel(c->name)
@@ -51,11 +53,17 @@ public:
&& bmask == this->mask;
}
void Tick() override
bool Tick() override
{
// We need to do this to prevent the remove-on-unban logic from double
// deleting the timer.
ticked = true;
Channel *c = Channel::Find(this->channel);
if (c)
c->RemoveMode(NULL, mode, this->mask);
return false;
}
};
@@ -65,7 +73,7 @@ class CommandCSBan final
public:
CommandCSBan(Module *creator) : Command(creator, "chanserv/ban", 2, 4)
{
this->SetDesc(_("Bans a given nick or mask on a channel"));
this->SetDesc(_("Ban a given nick or mask on a channel"));
this->SetSyntax(_("\037channel\037 [+\037expiry\037] {\037nick\037 | \037mask\037} [\037reason\037]"));
}
@@ -264,11 +272,12 @@ public:
source.Reply(_(
"Bans a given nick or mask on a channel. An optional expiry may "
"be given to cause services to remove the ban after a set amount "
"of time."
"\n\n"
"By default, limited to AOPs or those with level 5 access "
"and above on the channel. Channel founders may ban masks."
"of time. Channel founders may ban masks."
));
source.Reply(" ");
AccessProvider::SendAccess(source, "BAN");
return true;
}
};
@@ -290,7 +299,7 @@ public:
{
for (const auto *tempban : tempbans)
{
if (tempban->Matches(c, cmode, param))
if (!tempban->ticked && tempban->Matches(c, cmode, param))
{
delete tempban;
break;
+1 -5
View File
@@ -299,11 +299,7 @@ public:
{
Anope::map<Anope::string> tags;
if (timestamp)
{
char timebuf[32];
strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S.000Z", gmtime(&message->when));
tags["time"] = timebuf;
}
tags["time"] = Anope::FormatISO8601(message->when, 0);
if (u->ShouldPrivmsg())
IRCD->SendContextPrivmsg(c->ci->WhoSends(), u, c, message->message, tags);
+2 -2
View File
@@ -41,7 +41,7 @@ class CommandCSStats final
public:
CommandCSStats(Module *creator) : Command (creator, "chanserv/stats", 0, 2)
{
this->SetDesc(_("Displays your Channel Stats"));
this->SetDesc(_("Display your Channel Stats"));
this->SetSyntax(_("[\037channel\037] [\037nick\037]"));
}
@@ -54,7 +54,7 @@ class CommandCSGStats final
public:
CommandCSGStats(Module *creator) : Command (creator, "chanserv/gstats", 0, 2)
{
this->SetDesc(_("Displays your Global Stats"));
this->SetDesc(_("Display your Global Stats"));
this->SetSyntax(_("\037nick\037"));
}
+4 -4
View File
@@ -40,7 +40,7 @@ class CommandCSTop final
public:
CommandCSTop(Module *creator) : Command (creator, "chanserv/top", 0, 2)
{
this->SetDesc(_("Displays the top 3 users of a channel"));
this->SetDesc(_("Display the top 3 users of a channel"));
this->SetSyntax(_("\037channel\037"));
}
@@ -53,7 +53,7 @@ class CommandCSTop10 final
public:
CommandCSTop10(Module *creator) : Command (creator, "chanserv/top10", 0, 2)
{
this->SetDesc(_("Displays the top 10 users of a channel"));
this->SetDesc(_("Display the top 10 users of a channel"));
this->SetSyntax(_("\037channel\037"));
}
@@ -66,7 +66,7 @@ class CommandCSGTop final
public:
CommandCSGTop(Module *creator) : Command (creator, "chanserv/gtop", 0, 1)
{
this->SetDesc(_("Displays the top 3 users of the network"));
this->SetDesc(_("Display the top 3 users of the network"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params);
@@ -78,7 +78,7 @@ class CommandCSGTop10 final
public:
CommandCSGTop10(Module *creator) : Command (creator, "chanserv/gtop10", 0, 1)
{
this->SetDesc(_("Displays the top 10 users of the network"));
this->SetDesc(_("Display the top 10 users of the network"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params);
+53 -14
View File
@@ -14,7 +14,15 @@
#include "module.h"
#define FLAGS_MIGRATED_1 _("\002%s\002 has been migrated to the %s access system.")
#define FLAGS_MIGRATED_N N_("\002%u\002 entry has been migrated to the %s access system.", "\002%u\002 entries have been migrated to the %s access system.")
#define FLAGS_NOT_MIGRATABLE_1 _("\002%s\002 can not be migrated to the %s access system because they have no migratable privileges.")
#define FLAGS_NOT_MIGRATABLE_N N_("\002%u\002 entry can not be migrated to the %s access system because they have no migratable privileges.", "\002%u\002 entries can not be migrated to the %s access system because they have no migratable privileges.")
#define FLAGS_NOT_MIGRATED_1 _("\002%s\002 can not be migrated to the %s access system because they have privileges that you do not.")
#define FLAGS_NOT_MIGRATED_N N_("\002%u\002 entry can not be migrated to the %s access system because they have privileges that you do not.", "\002%u\002 entries can not be migrated to the %s access system because they have privileges that you do not.")
static std::map<Anope::string, char> defaultFlags;
static Anope::map<Anope::string> migrationRequires;
class FlagsChanAccess final
: public ChanAccess
@@ -76,6 +84,13 @@ public:
{
return new FlagsChanAccess(this);
}
void GetAccess(CommandSource& source, const Privilege *p, Anope::map<Anope::string> &access) override
{
auto it = defaultFlags.find(p->name);
if (it != defaultFlags.end())
access[_("Flag")] = Anope::ToString(it->second);
}
};
FlagsAccessProvider *FlagsAccessProvider::ap;
@@ -303,8 +318,8 @@ class CommandCSFlags final
return;
auto *access = anope_dynamic_static_cast<FlagsChanAccess *>(provider->Create());
access->SetMask(mask, ci);
access->creator = source.GetNick();
access->description = current ? current->description : description;
access->creator = source.GetNick();
access->description = current && description.empty() ? current->description : description;
access->last_seen = current ? current->last_seen : 0;
access->created = Anope::CurTime;
access->flags = current_flags;
@@ -411,10 +426,9 @@ class CommandCSFlags final
void DoMigrate(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{
auto override = false;
const auto source_access = source.AccessFor(ci);
unsigned migrated = 0, notmigrated = 0;
Anope::string migratedmask, notmigratedmask;
unsigned migrated = 0, notmigratable = 0, notmigrated = 0;
Anope::string migratedmask, notmigratablemask, notmigratedmask;
const auto &entry = params.size() > 2 ? params[2] : "*";
for (auto idx = ci->GetAccessCount(); idx > 0; --idx)
{
@@ -428,34 +442,52 @@ class CommandCSFlags final
std::set<char> newflags;
for (auto &[priv, flag] : defaultFlags)
{
if (access->HasPriv(priv))
if (!access->HasPriv(priv))
continue; // Source doesn't have this flag.
// Check that the source has access to set this entry.
const auto source_access = source.AccessFor(ci);
if (!override && !source_access.HasPriv(priv) && !source_access.founder)
{
if (!source.HasPriv("chanserv/access/modify"))
{
notmigrated++;
notmigratedmask = access->Mask();
Log(LOG_DEBUG) << source.GetNick() << " does not have the access to migrate " << access->Mask() << " to flags";
continue; // No privs
}
override = true;
}
auto req = migrationRequires.find(priv);
if (req != migrationRequires.end() && !access->HasPriv(req->second))
{
Log(LOG_DEBUG) << access->Mask() << " has " << priv << " but not " << req->second << " so it will be lost on migration to flags";
continue; // Required flag missing.
}
newflags.insert(flag);
}
if (newflags.empty())
{
notmigratable++;
notmigratablemask = access->Mask();
Log(LOG_DEBUG) << access->Mask() << " has " << access->AccessSerialize() << " that can not be migrated to flags";
continue; // No privs that are migratable
}
migrated++;
migratedmask = access->Mask();
auto *newaccess = anope_dynamic_static_cast<FlagsChanAccess *>(FlagsAccessProvider::ap->Create());
newaccess->SetMask(access->Mask(), ci);
newaccess->created = access->created;
newaccess->creator = access->creator;
newaccess->description = access->description;
newaccess->created = access->created;
newaccess->flags = newflags;
newaccess->last_seen = access->last_seen;
ci->EraseAccess(idx - 1);
FOREACH_MOD(OnAccessDel, (ci, source, access, true));
@@ -468,18 +500,23 @@ class CommandCSFlags final
if (migrated == 1)
{
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to migrate " << migratedmask;
source.Reply(CHAN_ACCESS_MIGRATED_1, migratedmask.c_str(), source.command.nobreak().c_str());
source.Reply(FLAGS_MIGRATED_1, migratedmask.c_str(), source.command.nobreak().c_str());
}
else if (migrated > 1)
{
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to migrate " << migrated << " access entries";
source.Reply(migrated, CHAN_ACCESS_MIGRATED_N, migrated, source.command.nobreak().c_str());
source.Reply(migrated, FLAGS_MIGRATED_N, migrated, source.command.nobreak().c_str());
}
if (notmigratable == 1)
source.Reply(FLAGS_NOT_MIGRATABLE_1, notmigratablemask.c_str(), source.command.nobreak().c_str());
else if (notmigratable > 1)
source.Reply(notmigratable, FLAGS_NOT_MIGRATABLE_N, notmigratable, source.command.nobreak().c_str());
if (notmigrated == 1)
source.Reply(CHAN_ACCESS_NOT_MIGRATED_1, notmigratedmask.c_str(), source.command.nobreak().c_str());
source.Reply(FLAGS_NOT_MIGRATED_1, notmigratedmask.c_str(), source.command.nobreak().c_str());
else if (notmigrated > 1)
source.Reply(migrated, CHAN_ACCESS_NOT_MIGRATED_N, notmigrated, source.command.nobreak().c_str());
source.Reply(notmigrated, FLAGS_NOT_MIGRATED_N, notmigrated, source.command.nobreak().c_str());
}
void DoClear(CommandSource &source, ChannelInfo *ci)
@@ -624,10 +661,8 @@ public:
{
defaultFlags.clear();
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
for (const auto &[_, priv] : conf.GetBlocks("privilege"))
{
const auto &priv = conf.GetBlock("privilege", i);
const Anope::string &pname = priv.Get<const Anope::string>("name");
Privilege *p = PrivilegeManager::FindPrivilege(pname);
@@ -638,6 +673,10 @@ public:
if (value.empty())
continue;
const auto &migration_requires = priv.Get<const Anope::string>("flag_migration_requires");
if (!migration_requires.empty())
migrationRequires[p->name] = migration_requires;
defaultFlags[p->name] = value[0];
}
}
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandCSGetKey final
public:
CommandCSGetKey(Module *creator) : Command(creator, "chanserv/getkey", 1, 1)
{
this->SetDesc(_("Returns the key of the given channel"));
this->SetDesc(_("Return the key of the given channel"));
this->SetSyntax(_("\037channel\037"));
}
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandCSInfo final
public:
CommandCSInfo(Module *creator) : Command(creator, "chanserv/info", 1, 2)
{
this->SetDesc(_("Lists information about the specified registered channel"));
this->SetDesc(_("List information about the specified registered channel"));
this->SetSyntax(_("\037channel\037"));
this->AllowUnregistered(true);
}
+5 -4
View File
@@ -20,7 +20,7 @@ class CommandCSInvite final
public:
CommandCSInvite(Module *creator) : Command(creator, "chanserv/invite", 1, 3)
{
this->SetDesc(_("Invites you or an optionally specified nick into a channel"));
this->SetDesc(_("Invite you or an optionally specified nick into a channel"));
this->SetSyntax(_("\037channel\037 [\037nick\037]"));
}
@@ -95,11 +95,12 @@ public:
source.Reply(_(
"Tells %s to invite you or an optionally specified "
"nick into the given channel."
"\n\n"
"By default, limited to AOPs or those with level 5 access and above "
"on the channel."
),
source.service->nick.c_str());
source.Reply(" ");
AccessProvider::SendAccess(source, "INVITE");
return true;
}
};
+6 -7
View File
@@ -20,7 +20,7 @@ class CommandCSKick final
public:
CommandCSKick(Module *creator) : Command(creator, "chanserv/kick", 2, 3)
{
this->SetDesc(_("Kicks a specified nick from a channel"));
this->SetDesc(_("Kick a specified nick from a channel"));
this->SetSyntax(_("\037channel\037 \037nick\037 [\037reason\037]"));
this->SetSyntax(_("\037channel\037 \037mask\037 [\037reason\037]"));
}
@@ -134,12 +134,11 @@ public:
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_(
"Kicks a specified nick from a channel."
"\n\n"
"By default, limited to AOPs or those with level 5 access "
"and above on the channel. Channel founders can also specify masks."
));
source.Reply(_("Kicks a specified nick from a channel. Channel founders can also specify masks."));
source.Reply(" ");
AccessProvider::SendAccess(source, "KICK");
return true;
}
};
+1 -1
View File
@@ -21,7 +21,7 @@ class CommandCSList final
public:
CommandCSList(Module *creator) : Command(creator, "chanserv/list", 1, 2)
{
this->SetDesc(_("Lists all registered channels matching the given pattern"));
this->SetDesc(_("List all registered channels matching the given pattern"));
this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE]"));
}
+2 -4
View File
@@ -118,7 +118,7 @@ class CommandCSLog final
public:
CommandCSLog(Module *creator) : Command(creator, "chanserv/log", 1, 4)
{
this->SetDesc(_("Configures channel logging settings"));
this->SetDesc(_("Configure channel logging settings"));
this->SetSyntax(_("\037channel\037"));
this->SetSyntax(_("\037channel\037 \037command\037 \037method\037 [\037status\037]"));
}
@@ -331,10 +331,8 @@ public:
const auto &block = conf.GetModule(this);
defaults.clear();
for (int i = 0; i < block.CountBlock("default"); ++i)
for (const auto &[_, def] : block.GetBlocks("default"))
{
const auto &def = block.GetBlock("default", i);
LogDefault ld;
ld.service = def.Get<const Anope::string>("service");
+1 -3
View File
@@ -999,10 +999,8 @@ public:
{
modes.clear();
for (int i = 0; i < conf.CountBlock("command"); ++i)
for (const auto &[_, block] : conf.GetBlocks("command"))
{
const auto &block = conf.GetBlock("command", i);
const Anope::string &cname = block.Get<const Anope::string>("name"),
&cmd = block.Get<const Anope::string>("command");
+1 -1
View File
@@ -242,7 +242,7 @@ class CommandSeen final
public:
CommandSeen(Module *creator) : Command(creator, "chanserv/seen", 1, 2)
{
this->SetDesc(_("Tells you about the last time a user was seen"));
this->SetDesc(_("Tell you about the last time a user was seen"));
this->SetSyntax(_("\037nick\037"));
this->AllowUnregistered(true);
}
+2 -2
View File
@@ -268,9 +268,9 @@ public:
void OnReload(Configuration::Conf &conf) override
{
command_data.clear();
for (int i = 0; i < conf.CountBlock("command"); ++i)
for (const auto &[_, block] : conf.GetBlocks("command"))
{
const auto &block = conf.GetBlock("command", i);
if (block.Get<const Anope::string>("command") != "chanserv/set/misc")
continue;
+1 -1
View File
@@ -165,7 +165,7 @@ class CommandCSUnSuspend final
public:
CommandCSUnSuspend(Module *creator) : Command(creator, "chanserv/unsuspend", 1, 1)
{
this->SetDesc(_("Releases a suspended channel"));
this->SetDesc(_("Release a suspended channel"));
this->SetSyntax(_("\037channel\037"));
}
+4 -3
View File
@@ -128,11 +128,12 @@ public:
"user from entering the given channel. If no channel is "
"given, all bans affecting you in channels you have access "
"in are removed."
"\n\n"
"By default, limited to AOPs or those with level 5 access and above "
"on the channel."
),
source.service->nick.c_str());
source.Reply(" ");
AccessProvider::SendAccess(source, "UNBAN");
return true;
}
};
+2 -2
View File
@@ -48,7 +48,7 @@ class CommandCSUp final
public:
CommandCSUp(Module *creator) : Command(creator, "chanserv/up", 0, 2)
{
this->SetDesc(_("Updates a selected nicks status on a channel"));
this->SetDesc(_("Update a selected nicks status on a channel"));
this->SetSyntax(_("[\037channel\037 [\037nick\037]]"));
}
@@ -152,7 +152,7 @@ class CommandCSDown final
public:
CommandCSDown(Module *creator) : Command(creator, "chanserv/down", 0, 2)
{
this->SetDesc(_("Removes a selected nicks status from a channel"));
this->SetDesc(_("Remove a selected nicks status from a channel"));
this->SetSyntax(_("[\037channel\037 [\037nick\037]]"));
}
+15 -4
View File
@@ -100,6 +100,19 @@ public:
{
return new XOPChanAccess(this);
}
void GetAccess(CommandSource& source, const Privilege *p, Anope::map<Anope::string> &access) override
{
for (const auto& xop : order)
{
const auto &privs = permissions[xop];
if (std::find(privs.begin(), privs.end(), p->name) != privs.end())
{
access[_("XOP")] = xop;
return;
}
}
}
};
class CommandCSXOP final
@@ -675,9 +688,8 @@ public:
order.clear();
permissions.clear();
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
for (const auto &[_, block] : conf.GetBlocks("privilege"))
{
const auto &block = conf.GetBlock("privilege", i);
const Anope::string &pname = block.Get<const Anope::string>("name");
Privilege *p = PrivilegeManager::FindPrivilege(pname);
@@ -691,9 +703,8 @@ public:
permissions[xop].push_back(pname);
}
for (int i = 0; i < conf.CountBlock("command"); ++i)
for (const auto &[_, block] : conf.GetBlocks("command"))
{
const auto &block = conf.GetBlock("command", i);
const Anope::string &cname = block.Get<const Anope::string>("name"),
&cserv = block.Get<const Anope::string>("command");
if (cname.empty() || cserv != "chanserv/xop")
+4 -2
View File
@@ -353,14 +353,16 @@ class MChanstats final
"(nick_, '', 'total'), (nick_, '', 'monthly'),"
"(nick_, '', 'weekly'), (nick_, '', 'daily');"
"END IF;"
"SET @echan = chan_;"
"SET @enick = nick_;"
"SET @update_query = CONCAT('UPDATE `" + prefix + "chanstats` SET line=line+', line_, ',"
"letters=letters+', letters_, ' , words=words+', words_, ', actions=actions+', actions_, ', "
"smileys_happy=smileys_happy+', sm_h_, ', smileys_sad=smileys_sad+', sm_s_, ', "
"smileys_other=smileys_other+', sm_o_, ', kicks=kicks+', kicks_, ', kicked=kicked+', kicked_, ', "
"modes=modes+', modes_, ', topics=topics+', topics_, ', ', time_ , '=', time_, '+', line_ ,' "
"WHERE (nick='''' OR nick=''', nick_, ''') AND (chan='''' OR chan=''', chan_, ''')');"
"WHERE (nick='''' OR nick=?) AND (chan='''' OR chan=?)');"
"PREPARE update_query FROM @update_query;"
"EXECUTE update_query;"
"EXECUTE update_query using @enick, @echan;"
"DEALLOCATE PREPARE update_query;"
"END";
this->RunQuery(query);
+181 -24
View File
@@ -12,6 +12,7 @@
//
// SPDX-License-Identifier: GPL-2.0-only
#include <algorithm>
#include "module.h"
#include "modules/botserv/badwords.h"
@@ -21,6 +22,7 @@
#include "modules/chanserv/mode.h"
#include "modules/hostserv/request.h"
#include "modules/info.h"
#include "modules/nickserv/ajoin.h"
#include "modules/nickserv/cert.h"
#include "modules/operserv/forbid.h"
#include "modules/operserv/news.h"
@@ -73,10 +75,10 @@ public:
}
// Retrieves the remaining data in the row.
Anope::string GetRemaining()
Anope::string GetRemaining(bool allow_empty = false)
{
auto remaining = stream.GetRemaining();
if (remaining.empty())
if (remaining.empty() && !allow_empty)
error++;
return remaining;
}
@@ -120,14 +122,49 @@ struct ModeLockData final
}
};
struct FounderSuccessorCandidate
{
// Flags ranked from founder down, for successor candidate ranking
static const Anope::string FLAG_PRIORITY;
NickCore* nc;
size_t priority;
time_t mtime;
FounderSuccessorCandidate()
: nc(nullptr)
, priority(99) // arbitrary; for log readability
, mtime(std::numeric_limits<std::time_t>::max())
{
}
FounderSuccessorCandidate(NickCore *c, const Anope::string &flags, time_t m)
: nc(c)
, priority(FLAG_PRIORITY.find_first_of(flags))
, mtime(m)
{
}
bool operator<(const FounderSuccessorCandidate& other)
{
return std::tie(priority, mtime) < std::tie(other.priority, other.mtime);
}
FounderSuccessorCandidate& operator=(const FounderSuccessorCandidate& other) = default;
};
const Anope::string FounderSuccessorCandidate::FLAG_PRIORITY = "FSRsaOoHh";
struct ChannelData final
{
Anope::unordered_map<ChanServ::AutoKick *> akicks;
Anope::string bot;
FounderSuccessorCandidate founder_candidate;
Anope::string info_adder;
Anope::string info_message;
time_t info_ts = 0;
std::vector<ModeLockData> mlocks;
FounderSuccessorCandidate successor_candidate;
Anope::string suspend_by;
Anope::string suspend_reason;
time_t suspend_ts = 0;
@@ -135,6 +172,7 @@ struct ChannelData final
struct UserData final
{
Anope::map<Anope::string> ajoins;
Anope::string info_adder;
Anope::string info_message;
time_t info_ts = 0;
@@ -236,21 +274,40 @@ private:
{ "XL", &DBAtheme::HandleXL },
};
void ApplyAccess(Anope::string &in, char flag, Anope::string &out, std::initializer_list<const char*> privs)
static void RemoveAll(Anope::string& in, const Anope::string& unwanted)
{
for (const auto *priv : privs)
auto it = std::remove_if(in.begin(), in.end(), [&](char c){
return unwanted.find_first_of(c) != unwanted.npos;
});
in.erase(it, in.end());
}
static bool RemoveFirstOccurrence(Anope::string& in, char c)
{
auto pos = in.find(c);
if (pos != Anope::string::npos)
{
auto pos = in.find(flag);
if (pos != Anope::string::npos)
in.erase(pos, 1);
return true;
}
return false;
}
bool ApplyAccess(Anope::string &in, char flag, Anope::string &out, std::initializer_list<const char*> privs)
{
const bool flag_found = RemoveFirstOccurrence(in, flag);
if (flag_found)
{
for (const auto *priv : privs)
{
auto privchar = flags.find(priv);
if (privchar != flags.end())
{
out.push_back(privchar->second);
in.erase(pos, 1);
}
}
}
return flag_found;
}
void ApplyFlags(Extensible *ext, Anope::string &flags, char flag, const char *extname, bool extend = true)
@@ -609,16 +666,17 @@ private:
return false;
}
auto *data = chandata.Require(ci);
auto *nc = NickCore::Find(mask);
if (flags.find('b') != Anope::string::npos)
{
if (ChanServ::akick_service)
if (!ChanServ::akick_service)
{
Log(this) << "Unable to import channel akick for " << ci->name << " as cs_akick is not loaded";
return true;
}
auto *data = chandata.Require(ci);
if (nc)
data->akicks[mask] = ChanServ::akick_service->AddAKick(ci, setter, nc, "", modifiedtime, modifiedtime);
else
@@ -638,7 +696,6 @@ private:
ApplyAccess(flags, 'a', accessflags, { "AUTOPROTECT", "PROTECT", "PROTECTME" });
ApplyAccess(flags, 'e', accessflags, { "GETKEY", "NOKICK", "UNBANME" });
ApplyAccess(flags, 'f', accessflags, { "ACCESS_CHANGE" });
ApplyAccess(flags, 'F', accessflags, { "FOUNDER" });
ApplyAccess(flags, 'H', accessflags, { "AUTOHALFOP" });
ApplyAccess(flags, 'h', accessflags, { "HALFOP", "HALFOPME" });
ApplyAccess(flags, 'i', accessflags, { "INVITE" });
@@ -662,6 +719,35 @@ private:
ci->AddAccess(access);
}
// Atheme allows multiple founders and picks a successor based on rank if one is not explicitly assigned.
bool is_founder_candidate = RemoveFirstOccurrence(flags, 'F');
RemoveAll(flags, "SR");
FounderSuccessorCandidate current_candidate(nc, originalflags, modifiedtime);
if (nc && current_candidate < data->successor_candidate)
{
if (is_founder_candidate && current_candidate < data->founder_candidate)
{
Log(LOG_DEBUG) << ci->name << ": Demoting founder candidate ("
<< ( data->founder_candidate.nc ? data->founder_candidate.nc->display : "NONE" )
<< ", " << data->founder_candidate.priority
<< ") to successor; replacing with (" << current_candidate.nc->display
<< ", " << current_candidate.priority << ")";
data->successor_candidate = data->founder_candidate;
data->founder_candidate = current_candidate;
}
else
{
Log(LOG_DEBUG) << ci->name << ": Replacing successor candidate ("
<< ( data->successor_candidate.nc ? data->successor_candidate.nc->display : "NONE" )
<< ", " << data->successor_candidate.priority
<< ") with (" << current_candidate.nc->display
<< ", " << current_candidate.priority << ")";
data->successor_candidate = current_candidate;
}
}
if (flags != "+")
Log(this) << "Unable to convert channel access flags " << flags << " for " << mask << " on " << ci->name;
@@ -788,7 +874,7 @@ private:
return true;
}
auto *xl = new XLine(user + "@" + host, setby, settime + duration, reason);
auto *xl = new XLine(user + "@" + host, setby, duration ? settime + duration : 0, reason);
xl->id = id;
sglinemgr->AddXLine(xl);
return true;
@@ -879,6 +965,7 @@ private:
ci->last_used = used;
// No equivalent: elnv
RemoveFirstOccurrence(flags, 'v'); // verbose, com
ApplyFlags(ci, flags, 'h', "CS_NO_EXPIRE");
ApplyFlags(ci, flags, 'k', "KEEPTOPIC");
ApplyFlags(ci, flags, 'o', "NOAUTOOP");
@@ -985,6 +1072,10 @@ private:
if (akick != data->akicks.end())
akick->second->reason = value;
}
else if (key == "expires")
{
Log(this) << "Unable to set access expiration for " << mask << " on " << ci->name << ": unimplemented";
}
else
Log(this) << "Unknown channel access metadata for " << mask << " on " << ci->name << ": " << key << " = " << value;
@@ -1146,10 +1237,7 @@ private:
// MDU <display> <key> <value>
auto display = row.Get();
auto key = row.Get();
auto value = row.GetRemaining();
if (!row)
return row.LogError(this);
auto value = row.GetRemaining(true);
auto *nc = NickCore::Find(display);
if (!nc)
@@ -1160,7 +1248,17 @@ private:
auto *data = userdata.Require(nc);
if (key == "private:autojoin")
return true; // TODO
{
commasepstream autojoins(value, true);
for (Anope::string autojoin; autojoins.GetToken(autojoin); )
{
spacesepstream entry(autojoin);
Anope::string cname, ckey;
if (entry.GetToken(cname))
entry.GetToken(ckey);
data->ajoins[cname] = ckey;
}
}
else if (key == "private:doenforce")
data->protect = true;
else if (key == "private:enforcetime")
@@ -1189,6 +1287,12 @@ private:
data->info_adder = value;
else if (key == "private:mark:timestamp")
data->info_ts = Anope::Convert<time_t>(value, 0);
else if (key == "private:sendpass:sender")
return HandleIgnoreMetadata(nc->display, key, value);
else if (key == "private:sendpass:timestamp")
return HandleIgnoreMetadata(nc->display, key, value);
else if (key == "private:setpass:key")
return HandleIgnoreMetadata(nc->display, key, value);
else if (key == "private:swhois")
return HandleIgnoreMetadata(nc->display, key, value);
else if (key == "private:usercloak")
@@ -1410,6 +1514,7 @@ private:
ApplyPassword(nc, flags, pass);
// No equivalent: bglmNQrS
RemoveFirstOccurrence(flags, 'b'); // nick b flag is ephemeral, ignore
ApplyFlags(nc, flags, 'E', "PROTECT");
ApplyFlags(nc, flags, 'e', "MEMO_MAIL");
ApplyFlags(nc, flags, 'n', "NEVEROP");
@@ -1499,7 +1604,7 @@ private:
return true;
}
auto *xl = new XLine(nick, setby, settime + duration, reason);
auto *xl = new XLine(nick, setby, duration ? settime + duration : 0, reason);
xl->id = id;
sqlinemgr->AddXLine(xl);
return true;
@@ -1561,7 +1666,7 @@ private:
return true;
}
auto *xl = new XLine(real, setby, settime + duration, reason);
auto *xl = new XLine(real, setby, duration ? settime + duration : 0, reason);
xl->id = id;
snlinemgr->AddXLine(xl);
return true;
@@ -1584,9 +1689,8 @@ public:
const auto &modconf = conf.GetModule(this);
csmiscdata.clear();
for (auto idx = 0; idx < modconf.CountBlock("cs_set_misc"); ++idx)
for (const auto &[_, data] : modconf.GetBlocks("cs_set_misc"))
{
const auto &data = modconf.GetBlock("cs_set_misc", idx);
const auto &anope = data.Get<const Anope::string>("anope");
const auto &atheme = data.Get<const Anope::string>("atheme");
if (!anope.empty() && !atheme.empty())
@@ -1594,9 +1698,8 @@ public:
}
nsmiscdata.clear();
for (auto idx = 0; idx < modconf.CountBlock("ns_set_misc"); ++idx)
for (const auto &[_, data] : modconf.GetBlocks("ns_set_misc"))
{
const auto &data = modconf.GetBlock("ns_set_misc", idx);
const auto &anope = data.Get<const Anope::string>("anope");
const auto &atheme = data.Get<const Anope::string>("atheme");
if (!anope.empty() && !atheme.empty())
@@ -1604,9 +1707,8 @@ public:
}
flags.clear();
for (int i = 0; i < Config->CountBlock("privilege"); ++i)
for (const auto &[_, priv] : conf.GetBlocks("privilege"))
{
const auto &priv = Config->GetBlock("privilege", i);
const Anope::string &name = priv.Get<const Anope::string>("name");
const Anope::string &value = priv.Get<const Anope::string>("flag");
if (!name.empty() && !value.empty())
@@ -1684,6 +1786,12 @@ public:
si.when = data->suspend_ts;
ci->Extend("CS_SUSPENDED", si);
}
if (data->founder_candidate.nc)
ci->SetFounder(data->founder_candidate.nc);
if (data->successor_candidate.nc)
ci->SetSuccessor(data->successor_candidate.nc);
}
for (const auto &[_, nc] : *NickCoreList)
@@ -1692,6 +1800,55 @@ public:
if (!data)
continue;
if (!data->ajoins.empty())
{
auto *channels = nc->Require<AJoinList>(NICKSERV_AJOIN_LIST_EXT);
if (channels)
{
for (const auto& ajoin : data->ajoins)
{
auto &channel = ajoin.first, &key = ajoin.second;
if (!key.empty())
{
Channel *c = Channel::Find(channel);
Anope::string k;
if (c && c->GetParam("KEY", k) && key != k)
{
Log(this) << "Skipping ajoin with incorrect key for channel " << channel
<< ", user " << nc->display;
continue;
}
}
if (!IRCD->IsChannelValid(channel))
{
Log(this) << "Invalid ajoin channel " << channel << " for " << nc->display;
}
else
{
const auto it = std::find_if((*channels)->cbegin(), (*channels)->cend(), [&](const AJoinEntry* a){
return a->channel == channel;
});
if (it != (*channels)->cend())
{
Log(this) << "Skipping duplicate ajoin channel" << channel << " for " << nc->display;
continue;
}
auto* entry = new AJoinEntry(nc);
entry->owner = nc;
entry->channel = channel;
entry->key = key;
(*channels)->push_back(entry); // ignore ajoinmax for non-disruptive migration
}
}
}
else
{
Log(this) << "Unable to convert autojoins for " << nc->display << " as ns_ajoin is not loaded";
}
}
if (!data->info_message.empty())
{
auto *oil = nc->Require<OperInfoList>("operinfo");
+5 -1
View File
@@ -12,10 +12,14 @@
//
// SPDX-License-Identifier: GPL-2.0-only
/// BEGIN CMAKE
/// target_link_libraries(${SO} PRIVATE "vendored_yyjson")
/// END CMAKE
#include <filesystem>
namespace fs = std::filesystem;
#include "yyjson/yyjson.c"
#include "yyjson/yyjson.h"
#include "module.h"
+6 -5
View File
@@ -534,8 +534,9 @@ public:
}
/* Times out after a few seconds */
void Tick() override
bool Tick() override
{
return false;
}
void Reply(Packet *p) override
@@ -718,7 +719,7 @@ public:
MyManager(Module *creator)
: Manager(creator)
, Timer(300, true)
, Timer(300)
, serial(Anope::CurTime)
, cur_id(Anope::RandomNumber())
{
@@ -1011,7 +1012,7 @@ public:
return serial;
}
void Tick() override
bool Tick() override
{
Log(LOG_DEBUG_2) << "Resolver: Purging DNS cache";
@@ -1025,6 +1026,7 @@ public:
if (req.created + static_cast<time_t>(req.ttl) < Anope::CurTime)
this->cache.erase(it);
}
return true;
}
private:
@@ -1093,9 +1095,8 @@ public:
refresh = block.Get<int>("refresh", "3600");
std::vector<std::pair<Anope::string, short> > notify;
for (int i = 0; i < block.CountBlock("notify"); ++i)
for (const auto &[_, n] : block.GetBlocks("notify"))
{
const auto &n = block.GetBlock("notify", i);
auto nip = n.Get<Anope::string>("ip");
auto nport = n.Get<short>("port");
+3 -6
View File
@@ -126,9 +126,8 @@ public:
this->add_to_akill = block.Get<bool>("add_to_akill", "yes");
this->blacklists.clear();
for (int i = 0; i < block.CountBlock("blacklist"); ++i)
for (const auto &[_, bl] : block.GetBlocks("blacklist"))
{
const auto &bl = block.GetBlock("blacklist", i);
Blacklist blacklist;
blacklist.name = bl.Get<Anope::string>("name");
@@ -137,9 +136,8 @@ public:
blacklist.bantime = bl.Get<time_t>("time", "4h");
blacklist.reason = bl.Get<Anope::string>("reason");
for (int j = 0; j < bl.CountBlock("reply"); ++j)
for (const auto &[_, reply] : block.GetBlocks("reply"))
{
const auto &reply = bl.GetBlock("reply", j);
Blacklist::Reply r;
r.code = reply.Get<int>("code");
@@ -153,9 +151,8 @@ public:
}
this->exempts.clear();
for (int i = 0; i < block.CountBlock("exempt"); ++i)
for (const auto &[_, bl] : block.GetBlocks("exempt"))
{
const auto &bl = block.GetBlock("exempt", i);
this->exempts.insert(bl.Get<Anope::string>("ip"));
}
}
+8 -1
View File
@@ -12,10 +12,17 @@
//
// SPDX-License-Identifier: GPL-2.0-only
/// BEGIN CMAKE
/// target_link_libraries(${SO} PRIVATE "vendored_bcrypt")
/// END CMAKE
#include <climits>
#include <random>
#include "bcrypt/crypt_blowfish.c"
extern "C"
{
#include "bcrypt/crypt_blowfish.h"
}
#include "module.h"
#include "modules/encryption.h"
+8 -1
View File
@@ -12,10 +12,17 @@
//
// SPDX-License-Identifier: GPL-2.0-only
/// BEGIN CMAKE
/// target_link_libraries(${SO} PRIVATE "vendored_md5")
/// END CMAKE
#include "module.h"
#include "modules/encryption.h"
#include "md5/md5.c"
extern "C"
{
#include "md5/md5.h"
}
class MD5Context final
: public Encryption::Context
+5 -1
View File
@@ -12,10 +12,14 @@
//
// SPDX-License-Identifier: GPL-2.0-only
/// BEGIN CMAKE
/// target_link_libraries(${SO} PRIVATE "vendored_sha1")
/// END CMAKE
#include "module.h"
#include "modules/encryption.h"
#include "sha1/sha1.c"
#include "sha1/sha1.h"
class SHA1Context final
: public Encryption::Context
+5 -1
View File
@@ -12,10 +12,14 @@
//
// SPDX-License-Identifier: GPL-2.0-only
/// BEGIN CMAKE
/// target_link_libraries(${SO} PRIVATE "vendored_sha2")
/// END CMAKE
#include <climits>
#include <random>
#include "sha2/sha2.c"
#include "sha2/sha2.h"
#include "module.h"
#include "modules/encryption.h"
+76 -4
View File
@@ -405,6 +405,80 @@ public:
QueueRequest(mod);
}
Anope::string EscapeDN(const Anope::string &str) const override
{
if (str.empty())
return str;
Anope::string newstr;
newstr.str().reserve(str.length());
for (size_t idx = 0; idx < str.length(); ++idx)
{
const char chr = str[idx];
if (chr == '\0')
{
newstr.append("\\00");
}
else if (chr == '"' || chr == '+' || chr == ',' || chr == ';' ||
chr == '<' || chr == '=' || chr == '>' || chr == '\\')
{
newstr.push_back('\\');
newstr.push_back(chr);
}
else if (idx == 0 && (chr == '#' || chr == ' '))
{
newstr.push_back('\\');
newstr.push_back(chr);
}
else if (idx == str.length() - 1 && chr == ' ')
{
newstr.push_back('\\');
newstr.push_back(chr);
}
else
{
newstr.push_back(chr);
}
}
return newstr;
}
Anope::string EscapeSF(const Anope::string &str) const override
{
if (str.empty())
return str;
Anope::string newstr;
newstr.str().reserve(str.length());
for (size_t idx = 0; idx < str.length(); ++idx)
{
const char chr = str[idx];
switch (chr)
{
case '\0':
newstr.append("\\00");
break;
case '(':
newstr.append("\\28");
break;
case ')':
newstr.append("\\29");
break;
case '*':
newstr.append("\\2A");
break;
case '\\':
newstr.append("\\5C");
break;
default:
newstr.push_back(chr);
break;
}
}
return newstr;
}
private:
void BuildReply(int res, LDAPRequest *req)
{
@@ -560,7 +634,7 @@ public:
{
const Anope::string &cname = it->first;
LDAPService *s = it->second;
int i;
size_t i;
++it;
@@ -580,10 +654,8 @@ public:
}
}
for (int i = 0; i < conf.CountBlock("ldap"); ++i)
for (const auto &[_, ldap] : conf.GetBlocks("ldap"))
{
const auto &ldap = conf.GetBlock("ldap", i);
const Anope::string &connname = ldap.Get<const Anope::string>("name", "ldap/main");
if (this->LDAPServices.find(connname) == this->LDAPServices.end())
+2 -3
View File
@@ -281,7 +281,7 @@ public:
{
const Anope::string &cname = it->first;
MySQLService *s = it->second;
int i;
size_t i;
++it;
@@ -298,9 +298,8 @@ public:
}
}
for (int i = 0; i < config.CountBlock("mysql"); ++i)
for (const auto &[_, block] : config.GetBlocks("mysql"))
{
const auto &block = config.GetBlock("mysql", i);
const Anope::string &connname = block.Get<const Anope::string>("name", "mysql/main");
if (this->MySQLServices.find(connname) == this->MySQLServices.end())
+2 -3
View File
@@ -129,7 +129,7 @@ public:
{
const Anope::string &cname = it->first;
SQLiteService *s = it->second;
int i, num;
size_t i, num;
++it;
for (i = 0, num = config.CountBlock("sqlite"); i < num; ++i)
@@ -145,9 +145,8 @@ public:
}
}
for (int i = 0; i < config.CountBlock("sqlite"); ++i)
for (const auto &[_, block] : config.GetBlocks("sqlite"))
{
const auto &block = config.GetBlock("sqlite", i);
Anope::string connname = block.Get<const Anope::string>("name", "sqlite/main");
if (this->SQLiteServices.find(connname) == this->SQLiteServices.end())
+1 -3
View File
@@ -331,10 +331,8 @@ public:
throw ConfigException("Unable to find http reference, is httpd loaded?");
xmlrpcinterface.tokens.clear();
for (int i = 0; i < modconf.CountBlock("token"); ++i)
for (const auto &[_, block] : modconf.GetBlocks("token"))
{
const auto &block = modconf.GetBlock("token", i);
RPC::Token token;
token.token = block.Get<const Anope::string>("token");
if (!token.token.empty())
+1 -1
View File
@@ -130,7 +130,7 @@ public:
CommandGLQueue(Module *creator)
: Command(creator, "global/queue", 1, 2)
{
this->SetDesc(_("Manages your pending message queue."));
this->SetDesc(_("Manage your pending message queue."));
this->SetSyntax(_("ADD \037message\037"));
this->SetSyntax(_("DEL \037entry-num\037"));
this->SetSyntax("LIST");
+6 -1
View File
@@ -156,7 +156,12 @@ public:
if (server)
this->ServerGlobal(sender, server, false, line);
else
this->ServerGlobal(sender, Servers::GetUplink(), true, line);
{
auto* uplink = Servers::GetUplink();
if (!uplink)
return false;
this->ServerGlobal(sender, uplink, true, line);
}
return true;
}
+1 -1
View File
@@ -33,7 +33,7 @@ class CommandHelp final
public:
CommandHelp(Module *creator) : Command(creator, "generic/help", 0)
{
this->SetDesc(_("Displays this list and give information about commands"));
this->SetDesc(_("Display this list and give information about commands"));
this->AllowUnregistered(true);
}
+1 -1
View File
@@ -60,7 +60,7 @@ class CommandHSDelAll final
public:
CommandHSDelAll(Module *creator) : Command(creator, "hostserv/delall", 1, 1)
{
this->SetDesc(_("Deletes the vhost for all nicks in an account"));
this->SetDesc(_("Delete the vhost for all nicks in an account"));
this->SetSyntax(_("\037nick\037"));
}
+1 -1
View File
@@ -42,7 +42,7 @@ public:
CommandHSGroup(Module *creator) : Command(creator, "hostserv/group", 0, 0)
{
this->SetDesc(_("Syncs the vhost for all nicks in an account"));
this->SetDesc(_("Sync the vhost for all nicks in an account"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandHSList final
public:
CommandHSList(Module *creator) : Command(creator, "hostserv/list", 0, 1)
{
this->SetDesc(_("Displays one or more vhost entries"));
this->SetDesc(_("Display one or more vhost entries"));
this->SetSyntax(_("[\037key\037|\037#X-Y\037]"));
}
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandHSOff final
public:
CommandHSOff(Module *creator) : Command(creator, "hostserv/off", 0, 0)
{
this->SetDesc(_("Deactivates your assigned vhost"));
this->SetDesc(_("Deactivate your assigned vhost"));
this->RequireUser(true);
}
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandHSOn final
public:
CommandHSOn(Module *creator) : Command(creator, "hostserv/on", 0, 0)
{
this->SetDesc(_("Activates your assigned vhost"));
this->SetDesc(_("Activate your assigned vhost"));
this->RequireUser(true);
}
+86 -21
View File
@@ -27,6 +27,29 @@ namespace
Anope::string validation_record;
}
struct SharedData final
{
// How long after a requested vhost is activated does a user have to wait before they can request a new vhost.
time_t activationcooldown = 0;
// How long after a requested vhost is rejected does a user have to wait before they can request a new vhost.
time_t rejectioncooldown = 0;
// How long should users have to wait between attempts at DNS validation.
time_t validationcooldown = 0;
// Extensible that stores the time a user had a vhost activated/rejected.
SerializableExtensibleItem<time_t> requestcooldown;
// The name of the DNS record used for validation.
Anope::string validationrecord;
SharedData(Module *mod)
: requestcooldown(mod, "HS_REQUEST_COOLDOWN")
{
}
};
struct HostRequestImpl final
: HostServ::HostRequest
, Serializable
@@ -105,6 +128,7 @@ private:
Command *command;
Reference<NickAlias> nickalias;
CommandSource source;
SharedData &data;
void HandleError(HostRequestImpl *hr)
{
@@ -119,11 +143,12 @@ private:
}
public:
DNSHostResolver(Command *cmd, HostServ::HostRequest *hr, NickAlias *na, const CommandSource &src)
DNSHostResolver(Command *cmd, HostServ::HostRequest *hr, NickAlias *na, const CommandSource &src, SharedData &sd)
: Request(dnsmanager, cmd->module, hr->host, DNS::QUERY_TXT, false)
, command(cmd)
, nickalias(na)
, source(src)
, data(sd)
{
hr->last_validation = Anope::CurTime;
Log(LOG_DEBUG) << "Checking " << hr->host << " for " << hr->validation_token;
@@ -171,6 +196,8 @@ public:
source.Reply(_("VHost for %s has been validated using DNS."), na->nick.c_str());
Log(LOG_COMMAND, source, command) << "for " << na->nick << " for vhost " << hr->Mask();
data.requestcooldown.Set(na, Anope::CurTime + data.activationcooldown);
na->Shrink<HostRequestImpl>(HOSTSERV_HOST_REQUEST_EXT);
return; // We're done.
@@ -183,8 +210,13 @@ public:
class CommandHSRequest final
: public Command
{
private:
SharedData &data;
public:
CommandHSRequest(Module *creator) : Command(creator, "hostserv/request", 1, 1)
CommandHSRequest(Module *creator, SharedData &sd)
: Command(creator, "hostserv/request", 1, 1)
, data(sd)
{
this->SetDesc(_("Request a vhost for your nick"));
this->SetSyntax(_("vhost"));
@@ -263,12 +295,25 @@ public:
return;
}
time_t send_delay = Config->GetModule("memoserv").Get<time_t>("senddelay");
if (Config->GetModule(this->owner).Get<bool>("memooper") && send_delay > 0 && u && u->lastmemosend + send_delay > Anope::CurTime)
time_t waituntil = 0;
{
auto waitperiod = (u->lastmemosend + send_delay) - Anope::CurTime;
// Check whether the user is on a request cooldown.
const auto *last_req = data.requestcooldown.Get(na);
if (last_req)
waituntil = *last_req;
}
if (Config->GetModule(this->owner).Get<bool>("memooper"))
{
// Check whether the user can send a memo to opers yet.
const auto send_delay = Config->GetModule("memoserv").Get<time_t>("senddelay");
if (send_delay > 0 && u && u->lastmemosend)
waituntil = std::max(waituntil, u->lastmemosend + send_delay);
}
if (waituntil && waituntil > Anope::CurTime)
{
const auto waitperiod = waituntil - Anope::CurTime;
source.Reply(_("Please wait %s before requesting a new vhost."), Anope::Duration(waitperiod, source.GetAccount()).c_str());
u->lastmemosend = Anope::CurTime;
return;
}
@@ -319,8 +364,13 @@ public:
class CommandHSActivate final
: public Command
{
private:
SharedData &data;
public:
CommandHSActivate(Module *creator) : Command(creator, "hostserv/activate", 1, 1)
CommandHSActivate(Module *creator, SharedData &sd)
: Command(creator, "hostserv/activate", 1, 1)
, data(sd)
{
this->SetDesc(_("Approve the requested vhost of a user"));
this->SetSyntax(_("\037nick\037"));
@@ -348,6 +398,8 @@ public:
source.Reply(_("VHost for %s has been activated."), na->nick.c_str());
Log(LOG_COMMAND, source, this) << "for " << na->nick << " for vhost " << (!req->ident.empty() ? req->ident + "@" : "") << req->host;
data.requestcooldown.Set(na, Anope::CurTime + data.activationcooldown);
na->Shrink<HostRequestImpl>(HOSTSERV_HOST_REQUEST_EXT);
}
else
@@ -369,8 +421,13 @@ public:
class CommandHSReject final
: public Command
{
private:
SharedData &data;
public:
CommandHSReject(Module *creator) : Command(creator, "hostserv/reject", 1, 2)
CommandHSReject(Module *creator, SharedData &sd)
: Command(creator, "hostserv/reject", 1, 2)
, data(sd)
{
this->SetDesc(_("Reject the requested vhost of a user"));
this->SetSyntax(_("\037nick\037 [\037reason\037]"));
@@ -391,6 +448,7 @@ public:
auto *req = HostRequestImpl::Get(na);
if (req)
{
data.requestcooldown.Set(na, Anope::CurTime + data.rejectioncooldown);
na->Shrink<HostRequestImpl>(HOSTSERV_HOST_REQUEST_EXT);
if (Config->GetModule(this->owner).Get<bool>("memouser") && MemoServ::service)
@@ -429,7 +487,7 @@ class CommandHSWaiting final
public:
CommandHSWaiting(Module *creator) : Command(creator, "hostserv/waiting", 0, 0)
{
this->SetDesc(_("Retrieves the vhost requests"));
this->SetDesc(_("Retrieve the vhost requests"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
@@ -481,13 +539,15 @@ public:
class CommandHSValidate final
: public Command
{
public:
time_t cooldown;
private:
SharedData &data;
CommandHSValidate(Module *creator)
public:
CommandHSValidate(Module *creator, SharedData &sd)
: Command(creator, "hostserv/validate", 0)
, data(sd)
{
this->SetDesc(_("Validates a previously requested vhost using DNS"));
this->SetDesc(_("Validate a previously requested vhost using DNS"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
@@ -512,7 +572,7 @@ public:
return;
}
auto next_validation = req->last_validation + cooldown;
auto next_validation = req->last_validation + data.validationcooldown;
if (req->last_validation && next_validation > Anope::CurTime)
{
source.Reply(_("You must wait for %s before trying DNS validation again."),
@@ -526,7 +586,7 @@ public:
if (!dnsmanager)
throw SocketException("DNS is not available");
res = new DNSHostResolver(this, req, na, source);
res = new DNSHostResolver(this, req, na, source, data);
dnsmanager->Process(res);
}
catch (const SocketException &ex)
@@ -553,8 +613,10 @@ public:
class HSRequest final
: public Module
{
private:
SharedData data;
CommandHSRequest commandhsrequest;
CommandHSActivate commandhsactive;
CommandHSActivate commandhsactivate;
CommandHSReject commandhsreject;
CommandHSWaiting commandhswaiting;
CommandHSValidate commandhsvalidate;
@@ -564,11 +626,12 @@ class HSRequest final
public:
HSRequest(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, VENDOR)
, commandhsrequest(this)
, commandhsactive(this)
, commandhsreject(this)
, data(this)
, commandhsrequest(this, data)
, commandhsactivate(this, data)
, commandhsreject(this, data)
, commandhswaiting(this)
, commandhsvalidate(this)
, commandhsvalidate(this, data)
, hostrequest(this, HOSTSERV_HOST_REQUEST_EXT)
{
if (!IRCD || !IRCD->CanSetVHost)
@@ -578,7 +641,9 @@ public:
void OnReload(Configuration::Conf &conf) override
{
const auto &block = conf.GetModule(this);
commandhsvalidate.cooldown = block.Get<time_t>("validationcooldown", "5m");
data.activationcooldown = block.Get<time_t>("activationcooldown", "24h");
data.rejectioncooldown = block.Get<time_t>("rejectioncooldown", "24h");
data.validationcooldown = block.Get<time_t>("validationcooldown", "5m");
validation_record = block.Get<const Anope::string>("validationrecord", "anope-dns-validation");
}
};
+4 -6
View File
@@ -298,12 +298,12 @@ public:
MyHTTPProvider(Module *c, const Anope::string &n, const Anope::string &i, const unsigned short p, const int t, bool s)
: Socket(-1, i.find(':') == Anope::string::npos ? AF_INET : AF_INET6)
, HTTP::Provider(c, n, i, p, s)
, Timer(c, 10, true)
, Timer(c, 10)
, timeout(t)
{
}
void Tick() override
bool Tick() override
{
while (!this->clients.empty())
{
@@ -314,6 +314,7 @@ public:
delete c;
this->clients.pop_front();
}
return true;
}
ClientSocket *OnAccept(int fd, const sockaddrs &addr) override
@@ -371,11 +372,8 @@ public:
const auto &conf = config.GetModule(this);
std::set<Anope::string> existing;
for (int i = 0; i < conf.CountBlock("httpd"); ++i)
for (const auto &[_, block] : conf.GetBlocks("httpd"))
{
const auto &block = conf.GetBlock("httpd", i);
const Anope::string &hname = block.Get<const Anope::string>("name", "httpd/main");
existing.insert(hname);
+3 -3
View File
@@ -92,8 +92,8 @@ public:
if (ii->admin_bind)
{
auto sf = Anope::Template(search_filter, {
{ "account", ii->req->GetAccount() },
{ "object_class", object_class },
{ "account", ii->lprov->EscapeSF(ii->req->GetAccount()) },
{ "object_class", object_class },
});
try
{
@@ -310,7 +310,7 @@ public:
attributes[3].name = this->password_attribute;
attributes[3].values.push_back(pass);
Anope::string new_dn = username_attribute + "=" + na->nick + "," + basedn;
Anope::string new_dn = username_attribute + "=" + this->ldap->EscapeDN(na->nick) + "," + basedn;
this->ldap->Add(&this->orinterface, new_dn, attributes);
}
+2 -2
View File
@@ -125,13 +125,13 @@ public:
if (!this->binddn.empty())
{
auto bdn = Anope::Template(this->binddn, {
{ "account", u->Account()->display },
{ "account", this->ldap->EscapeDN(u->Account()->display) },
});
this->ldap->Bind(NULL, bdn, this->password.c_str());
}
auto af = Anope::Template(this->filter, {
{ "account", u->Account()->display },
{ "account", this->ldap->EscapeSF(u->Account()->display) },
});
this->ldap->Search(new IdentifyInterface(this, u), this->basedn, af);
}
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandMSCheck final
public:
CommandMSCheck(Module *creator) : Command(creator, "memoserv/check", 1, 1)
{
this->SetDesc(_("Checks if last memo to a nick was read"));
this->SetDesc(_("Check if last memo to a nick was read"));
this->SetSyntax(_("\037nick\037"));
}
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandMSInfo final
public:
CommandMSInfo(Module *creator) : Command(creator, "memoserv/info", 0, 1)
{
this->SetDesc(_("Displays information about your memos"));
this->SetDesc(_("Display information about your memos"));
this->SetSyntax(_("[\037nick\037 | \037channel\037]"));
}
+1 -1
View File
@@ -21,7 +21,7 @@ class CommandMSRSend final
public:
CommandMSRSend(Module *creator) : Command(creator, "memoserv/rsend", 2, 2)
{
this->SetDesc(_("Sends a memo and requests a read receipt"));
this->SetDesc(_("Send a memo and requests a read receipt"));
this->SetSyntax(_("{\037nick\037 | \037channel\037} \037memo-text\037"));
}
+8 -5
View File
@@ -61,16 +61,17 @@ public:
return na;
}
void Tick() override
bool Tick() override
{
if (!u || !na || !NickServ::service)
return;
return false;
/* If they identified or don't exist anymore, don't kill them. */
if (u->Account() == na->nc || u->timestamp > ts)
return;
return false;
NickServ::service->Collide(u, na);
return false;
}
};
@@ -90,10 +91,11 @@ public:
n->Extend<bool>("HELD");
}
void Tick() override
bool Tick() override
{
if (na)
na->Shrink<bool>("HELD");
return false;
}
};
@@ -133,8 +135,9 @@ public:
NickServReleases.erase(this->nick);
}
void Tick() override
bool Tick() override
{
return false;
}
};
+7 -32
View File
@@ -13,34 +13,15 @@
// SPDX-License-Identifier: GPL-2.0-only
#include "module.h"
#include "modules/nickserv/ajoin.h"
struct AJoinEntry;
struct AJoinList final
: Serialize::Checker<std::vector<AJoinEntry *> >
struct AJoinListImpl final : public AJoinList
{
AJoinList(Extensible *) : Serialize::Checker<std::vector<AJoinEntry *> >("AJoinEntry") { }
~AJoinList();
};
struct AJoinEntry final
: Serializable
{
Serialize::Reference<NickCore> owner;
Anope::string channel;
Anope::string key;
AJoinEntry(Extensible *) : Serializable("AJoinEntry") { }
~AJoinEntry() override
AJoinListImpl(Extensible * e) : AJoinList(e) { }
~AJoinListImpl()
{
auto *channels = owner->GetExt<AJoinList>("ajoinlist");
if (channels)
{
auto it = std::find((*channels)->begin(), (*channels)->end(), this);
if (it != (*channels)->end())
(*channels)->erase(it);
}
for (const auto *ajoin : *(*this))
delete ajoin;
}
};
@@ -93,12 +74,6 @@ struct AJoinEntryType final
}
};
AJoinList::~AJoinList()
{
for (const auto *ajoin : *(*this))
delete ajoin;
}
class CommandNSAJoin final
: public Command
{
@@ -321,7 +296,7 @@ class NSAJoin final
: public Module
{
CommandNSAJoin commandnsajoin;
ExtensibleItem<AJoinList> ajoinlist;
ExtensibleItem<AJoinListImpl> ajoinlist;
AJoinEntryType ajoinentry_type;
public:
+4 -4
View File
@@ -164,12 +164,12 @@ public:
if (newit != this->certs.end())
{
// The cert we're upgrading to already exists.
delete *newit;
this->certs.erase(newit);
delete *oldit;
this->certs.erase(oldit);
return;
}
auto *cert = *newit;
auto *cert = *oldit;
cert->fingerprint = newentry;
certmap[newentry] = cert;
FOREACH_MOD(OnNickAddCert, (this->nc, cert));
@@ -548,7 +548,7 @@ public:
CommandNSSetAutologin(Module *creator, const Anope::string &sname = "nickserv/set/autologin", size_t min = 1)
: Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Sets whether you should automatically be logged in when you connect using a known SSL certificate."));
this->SetDesc(_("Set whether you should automatically be logged in when you connect using a known SSL certificate."));
this->SetSyntax("{ON | OFF}");
}
+1 -1
View File
@@ -205,7 +205,7 @@ public:
CommandNSGetEmail(Module *creator)
: Command(creator, "nickserv/getemail", 1, 1)
{
this->SetDesc(_("Matches and returns all users that registered using given email address"));
this->SetDesc(_("Match and return all users that registered using given email address"));
this->SetSyntax(_("\037email\037"));
}
+4 -3
View File
@@ -145,8 +145,9 @@ public:
}
NickAlias *target, *na = NickAlias::Find(source.GetNick());
time_t reg_delay = Config->GetModule("nickserv").Get<time_t>("regdelay");
auto maxaliases = Config->GetModule(this->owner).Get<unsigned>("maxaliases");
auto &modconf = Config->GetModule(this->owner);
time_t reg_delay = modconf.Get<time_t>("delay", Config->GetModule("nickserv").Get<time_t>("regdelay", "5m"));
auto maxaliases = modconf.Get<unsigned>("maxaliases");
if (!(target = NickAlias::Find(nick)))
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
else if (user && Anope::CurTime < user->lastnickreg + reg_delay)
@@ -305,7 +306,7 @@ class CommandNSGList final
public:
CommandNSGList(Module *creator) : Command(creator, "nickserv/glist", 0, 1)
{
this->SetDesc(_("Lists all nicknames in your account"));
this->SetDesc(_("List all nicknames in your account"));
this->SetSyntax(_("[\037nickname\037]"), [](auto &source) { return source.IsServicesOper(); });
}
+1 -1
View File
@@ -20,7 +20,7 @@ class CommandNSInfo final
public:
CommandNSInfo(Module *creator) : Command(creator, "nickserv/info", 0, 2)
{
this->SetDesc(_("Displays information about a given nickname"));
this->SetDesc(_("Display information about a given nickname"));
this->SetSyntax(_("[\037nickname\037]"));
this->AllowUnregistered(true);
}
+1 -1
View File
@@ -21,7 +21,7 @@ class CommandNSLogout final
public:
CommandNSLogout(Module *creator) : Command(creator, "nickserv/logout", 0, 2)
{
this->SetDesc(_("Reverses the effect of the IDENTIFY command"));
this->SetDesc(_("Reverse the effect of the IDENTIFY command"));
this->SetSyntax(_("[\037nickname\037 [REVALIDATE]]"), [](auto &source) { return source.IsServicesOper(); });
}
+1 -1
View File
@@ -154,7 +154,7 @@ class CommandNSRecover final
public:
CommandNSRecover(Module *creator) : Command(creator, "nickserv/recover", 1, 2)
{
this->SetDesc(_("Regains control of your nick"));
this->SetDesc(_("Regain control of your nick"));
this->SetSyntax(_("\037nickname\037 [\037password\037]"));
this->AllowUnregistered(true);
}
+17 -7
View File
@@ -66,7 +66,7 @@ public:
}
time_t nickregdelay = Config->GetModule(this->owner).Get<time_t>("nickregdelay");
time_t reg_delay = Config->GetModule("nickserv").Get<time_t>("regdelay");
time_t reg_delay = Config->GetModule("nickserv").Get<time_t>("regdelay", "15m");
if (u && !u->HasMode("OPER") && nickregdelay && Anope::CurTime - u->timestamp < nickregdelay)
{
auto waitperiod = (u->timestamp + nickregdelay) - Anope::CurTime;
@@ -275,18 +275,28 @@ public:
return;
}
auto *passcode = nc->GetExt<Anope::string>("passcode");
if (!passcode)
if (!nc->HasExt("UNCONFIRMED"))
{
source.Reply(_("There is no registration confirmation pending for %s."),
na->nick.c_str());
return;
}
if (!code.empty() && !code.equals_cs(*passcode))
if (!code.empty())
{
source.Reply(_("The registration confirmation code you specified for %s is incorrect."),
na->nick.c_str());
return;
auto *passcode = nc->GetExt<Anope::string>("passcode");
if (passcode && !code.equals_cs(*passcode))
{
source.Reply(_("The registration confirmation code you specified for %s is incorrect."),
na->nick.c_str());
return;
}
else if (!passcode)
{
source.Reply(_("The registration of %s can only be confirmed by an administrator."),
na->nick.c_str());
return;
}
}
nc->Shrink<Anope::string>("passcode");
+1 -1
View File
@@ -22,7 +22,7 @@ class CommandNSResetPass final
public:
CommandNSResetPass(Module *creator) : Command(creator, "nickserv/resetpass", 2, 2)
{
this->SetDesc(_("Helps you reset lost passwords"));
this->SetDesc(_("Send an email to recover access to an account"));
this->SetSyntax(_("\037nickname\037 \037email\037"));
this->AllowUnregistered(true);
}
+3 -2
View File
@@ -29,7 +29,7 @@ public:
SASLService(Module *o)
: SASL::Service(o)
, Timer(o, 60, true)
, Timer(o, 60)
{
}
@@ -221,7 +221,7 @@ public:
this->SendMessage(session, "M", buf.empty() ? "" : buf.substr(1));
}
void Tick() override
bool Tick() override
{
for (auto it = badpasswords.begin(); it != badpasswords.end(); )
{
@@ -240,6 +240,7 @@ public:
sessions.erase(uid);
}
}
return true;
}
};
+5 -5
View File
@@ -21,7 +21,7 @@ public:
CommandNSSetKeepModes(Module *creator, const Anope::string &sname = "nickserv/set/keepmodes", size_t min = 1)
: Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Enable or disable keep modes"));
this->SetDesc(_("Configure keeping user modes set across connections"));
this->SetSyntax("{ON | OFF}");
}
@@ -72,9 +72,9 @@ public:
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_(
"Enables or disables keepmodes for your nick. If keep "
"modes is enabled, services will remember your usermodes "
"and attempt to re-set them the next time you authenticate."
"Configures keeping user modes set across connections. If this is "
"enabled, your last user modes will be remembered and will be "
"re-set the next time you identify."
));
return true;
}
@@ -102,7 +102,7 @@ public:
source.Reply(" ");
source.Reply(_(
"Enables or disables keepmodes for the given nick. If keep "
"modes is enabled, services will remember users' usermodes "
"modes is enabled, services will remember users' user modes "
"and attempt to re-set them the next time they authenticate."
));
return true;
+1 -1
View File
@@ -21,7 +21,7 @@ public:
CommandNSSetLayout(Module *creator, const Anope::string &sname = "nickserv/set/layout", size_t min = 1)
: Command(creator, sname, min, min + 1)
{
this->SetDesc(_("Configures the layout used for services messages"));
this->SetDesc(_("Configure the layout used for services messages"));
this->SetSyntax("{FIXED | FLEXIBLE | MONOSPACE}");
}

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