mirror of
https://github.com/anope/anope.git
synced 2026-06-17 06:44:46 +02:00
Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0bb51f6551 | |||
| 28ce7bccb6 | |||
| a70ef47359 | |||
| 90ac540960 | |||
| 909a77efb9 | |||
| 59c8867e64 | |||
| 08d47a5dad | |||
| 41403c7e36 | |||
| b8ef28509c | |||
| cf6e56130a | |||
| a3f6ffd2c7 | |||
| b9554f8539 | |||
| 84dc0f3cc8 | |||
| 75f764e353 | |||
| 302c4f334e | |||
| 5148b349b7 | |||
| bbe31a6a38 | |||
| 8cb310c72e | |||
| 4a1ad182d4 | |||
| 75a893b18d | |||
| 753db88ae9 | |||
| 9f6f0b445b | |||
| dfa0bf5e5d | |||
| cc35c22d2a | |||
| 1dafc96521 | |||
| 5d1dd21887 | |||
| 8b6c6fdd81 | |||
| 1a5d49b7f6 | |||
| 0b3e55ed8f | |||
| 7a09cebcfb | |||
| da5c68f274 | |||
| 9782c1f94b | |||
| ee6b022f4d | |||
| 85b0e9d02f | |||
| da799bd6f1 | |||
| 4dada51e08 | |||
| 1275fd01a7 | |||
| 5b8018eb80 | |||
| b2026fe739 | |||
| 3390d82ebe | |||
| 4762e306f9 | |||
| fd759f7bd3 | |||
| 003ddde09d | |||
| c021d7134e | |||
| a792088a62 | |||
| 03e2ebe2d2 | |||
| 0238f0a9e3 | |||
| c2dfb9a447 | |||
| bd8435a061 | |||
| 2cd67c9f36 | |||
| 45ab094d63 | |||
| 54389f474b | |||
| ac2b38b1b6 | |||
| df551bee03 | |||
| 59bb9d3d06 | |||
| 3b2d798e76 | |||
| ff6d6bdb3c | |||
| 411b3ce65a | |||
| ad19603818 | |||
| 535ff9b839 | |||
| 51916a50d2 | |||
| 42e58952cc | |||
| ba9f4e93c2 | |||
| 679a313ae2 | |||
| 390975e6c4 | |||
| d631885495 | |||
| 8e337c6592 | |||
| 9d89d8233d | |||
| 6f27418381 | |||
| 1932081c27 | |||
| f73159159f | |||
| eccb338cdd | |||
| 4021c0bb68 | |||
| 7dfb40cb58 | |||
| 0fbd3095c4 | |||
| 6d426ec386 | |||
| 1b33a51695 | |||
| 168a1173ed | |||
| 59c777d4ff | |||
| 43f88524e2 | |||
| 04de41ad7f | |||
| dd13846cad | |||
| 6864bc6171 | |||
| 003cb55409 | |||
| d15b8ee949 | |||
| 70de2b7de2 | |||
| e5c5689985 | |||
| 928d4260dc | |||
| 5e8561a7f1 | |||
| 4dd3075ddf | |||
| dbef7a7c64 | |||
| cd0f00a819 | |||
| b2d40d4189 | |||
| e6e812c43c | |||
| 2dbd41d244 | |||
| 02aeb254ee | |||
| 1245b43ade | |||
| 5a3f9f3f87 | |||
| 2c6f4d7c27 | |||
| 64f8449bf4 | |||
| 0e1f6b403b | |||
| 206192abdc | |||
| 32d3ddc0e4 | |||
| 4410e5ccce | |||
| d5f2232140 | |||
| 6d754b7d73 | |||
| 4d2870fa45 | |||
| 5948c2ea53 | |||
| ace7d99797 | |||
| 52595b90fa | |||
| b39f002d1b | |||
| 5df95d9f86 | |||
| a56d9a4096 | |||
| ce7bb15c18 | |||
| 6873630f2e | |||
| 44a4d62654 | |||
| 97389cd105 | |||
| 80c0adf7c8 | |||
| 6a539277b9 |
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
if: "!contains(github.event.head_commit.message, '[skip alpine ci]')"
|
||||
@@ -13,7 +14,7 @@ jobs:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
CXXFLAGS: -Werror
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
name: Ubuntu CI
|
||||
on:
|
||||
- pull_request
|
||||
- push
|
||||
pull_request:
|
||||
push:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
if: "!contains(github.event.head_commit.message, '[skip ubuntu ci]')"
|
||||
@@ -10,7 +13,7 @@ jobs:
|
||||
CXX: ${{ matrix.compiler }}
|
||||
CXXFLAGS: -Werror
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
- published
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
build:
|
||||
if: "!contains(github.event.head_commit.message, '[skip windows ci]')"
|
||||
@@ -16,7 +17,7 @@ jobs:
|
||||
CONAN_USER_HOME: ${{ github.workspace }}/win/build
|
||||
CONAN_USER_HOME_SHORT: None
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Setup NSIS
|
||||
run: |-
|
||||
|
||||
@@ -14,5 +14,6 @@ modules/ssl_openssl.cpp
|
||||
modules/stats
|
||||
modules/xmlrpc.cpp
|
||||
run/
|
||||
*.diff
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
+4
-2
@@ -107,6 +107,7 @@ include(CheckFunctionExists)
|
||||
include(CheckTypeSize)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(FindPkgConfig)
|
||||
|
||||
# If extra include directories were specified, tell cmake about them.
|
||||
if(EXTRA_INCLUDE)
|
||||
@@ -121,7 +122,7 @@ endif()
|
||||
# setup conan
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/conanbuildinfo.cmake")
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/conanbuildinfo.cmake")
|
||||
conan_basic_setup()
|
||||
conan_basic_setup(TARGETS)
|
||||
endif()
|
||||
|
||||
# Find gettext
|
||||
@@ -159,7 +160,8 @@ if(MSVC)
|
||||
# Otherwise, we're not using Visual Studio
|
||||
else()
|
||||
# Set the compile flags to have all warnings on (including shadowed variables)
|
||||
set(CXXFLAGS "${CXXFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wextra -Wformat=2 -Wmissing-format-attribute -Wpedantic -Wno-format-nonliteral -Wno-format-zero-length -Wno-unused-parameter ${CMAKE_CXX_FLAGS}")
|
||||
set(CXXFLAGS "${CXXFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wextra -Wformat=2 -Wmissing-format-attribute -Wpedantic")
|
||||
set(CXXFLAGS "${CXXFLAGS} -Wno-format-nonliteral -Wno-format-y2k -Wno-format-zero-length -Wno-date-time -Wno-unused-parameter ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
# If CMake has found that the given system requires a special library for dl* calls, include it with the linker flags
|
||||
|
||||
BIN
Binary file not shown.
+26
-84
@@ -1,87 +1,3 @@
|
||||
###############################################################################
|
||||
# calculate_libraries(<source filename> <output variable for linker flags> <output variable for extra depends>)
|
||||
#
|
||||
# This macro is used in most of the module (sub)directories to calculate the
|
||||
# library dependencies for the given source file.
|
||||
###############################################################################
|
||||
macro(calculate_libraries SRC SRC_LDFLAGS EXTRA_DEPENDS)
|
||||
# Set up a temporary LDFLAGS for this file
|
||||
set(THIS_LDFLAGS "${LDFLAGS}")
|
||||
# Reset extra dependencies
|
||||
set(EXTRA_DEPENDENCIES)
|
||||
# Reset library paths
|
||||
set(LIBRARY_PATHS)
|
||||
# Reset libraries
|
||||
set(LIBRARIES)
|
||||
# Check to see if there are any lines matching: /* RequiredLibraries: [something] */
|
||||
if(WIN32)
|
||||
file(STRINGS ${SRC} REQUIRED_LIBRARIES REGEX "/\\*[ \t]*RequiredWindowsLibraries:[ \t]*.*[ \t]*\\*/")
|
||||
else()
|
||||
file(STRINGS ${SRC} REQUIRED_LIBRARIES REGEX "/\\*[ \t]*RequiredLibraries:[ \t]*.*[ \t]*\\*/")
|
||||
endif()
|
||||
# Iterate through those lines
|
||||
foreach(REQUIRED_LIBRARY ${REQUIRED_LIBRARIES})
|
||||
# Strip off the /* RequiredLibraries: and */ from the line
|
||||
string(REGEX REPLACE "/\\*[ \t]*Required.*Libraries:[ \t]*([^ \t]*)[ \t]*\\*/" "\\1" REQUIRED_LIBRARY ${REQUIRED_LIBRARY})
|
||||
# Replace all commas with semicolons
|
||||
string(REGEX REPLACE "," ";" REQUIRED_LIBRARY ${REQUIRED_LIBRARY})
|
||||
# Iterate through the libraries given
|
||||
foreach(LIBRARY ${REQUIRED_LIBRARY})
|
||||
# If the library has multiple names extract the alternate.
|
||||
unset(LIBRARY_ALT)
|
||||
if (${LIBRARY} MATCHES "^.+\\|.+$")
|
||||
string(REGEX REPLACE ".+\\|(.*)" "\\1" LIBRARY_ALT ${LIBRARY})
|
||||
string(REGEX REPLACE "(.+)\\|.*" "\\1" LIBRARY ${LIBRARY})
|
||||
endif()
|
||||
# Locate the library to see if it exists
|
||||
if(DEFAULT_LIBRARY_DIRS OR DEFINED $ENV{VCINSTALLDIR})
|
||||
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${DEFAULT_LIBRARY_DIRS} $ENV{VCINSTALLDIR}/lib ${EXTRA_INCLUDE} ${EXTRA_LIBS})
|
||||
else()
|
||||
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${EXTRA_INCLUDE} ${EXTRA_LIBS} NO_DEFAULT_PATH)
|
||||
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${EXTRA_INCLUDE} ${EXTRA_LIBS})
|
||||
endif()
|
||||
# If the library was found, we will add it to the linker flags
|
||||
if(FOUND_${LIBRARY}_LIBRARY)
|
||||
if(MSVC)
|
||||
# For Visual Studio, instead of editing the linker flags, we'll add the library to a separate list of extra dependencies
|
||||
list(APPEND EXTRA_DEPENDENCIES "${FOUND_${LIBRARY}_LIBRARY}")
|
||||
else()
|
||||
# Get the path only of the library, to add it to library paths.
|
||||
get_filename_component(LIBRARY_PATH ${FOUND_${LIBRARY}_LIBRARY} PATH)
|
||||
list(APPEND LIBRARY_PATHS "${LIBRARY_PATH}")
|
||||
# Extract the library short name, add it to the library path
|
||||
get_filename_component(LIBRARY_NAME ${FOUND_${LIBRARY}_LIBRARY} NAME_WE)
|
||||
string(REGEX REPLACE "^lib" "" LIBRARY_NAME ${LIBRARY_NAME})
|
||||
list(APPEND LIBRARIES ${LIBRARY_NAME})
|
||||
endif()
|
||||
else()
|
||||
# In the case of the library not being found, we fatally error so CMake stops trying to generate
|
||||
message(FATAL_ERROR "${SRC} needs library ${LIBRARY} but we were unable to locate that library! Check that the library is within the search path of your OS.")
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
# Remove duplicates from the library paths
|
||||
if(LIBRARY_PATHS)
|
||||
list(REMOVE_DUPLICATES LIBRARY_PATHS)
|
||||
endif()
|
||||
# Remove diplicates from the libraries
|
||||
if(LIBRARIES)
|
||||
list(REMOVE_DUPLICATES LIBRARIES)
|
||||
endif()
|
||||
# Iterate through library paths and add them to the linker flags
|
||||
foreach(LIBRARY_PATH ${LIBRARY_PATHS})
|
||||
if(NOT "${LIBRARY_PATH}" IN_LIST DEFAULT_LIBRARY_DIRS)
|
||||
set(THIS_LDFLAGS "${THIS_LDFLAGS} -L${LIBRARY_PATH}")
|
||||
endif()
|
||||
endforeach()
|
||||
# Iterate through libraries and add them to the linker flags
|
||||
foreach(LIBRARY ${LIBRARIES})
|
||||
list(APPEND EXTRA_DEPENDENCIES "${LIBRARY}")
|
||||
endforeach()
|
||||
set(${SRC_LDFLAGS} "${THIS_LDFLAGS}")
|
||||
set(${EXTRA_DEPENDS} "${EXTRA_DEPENDENCIES}")
|
||||
endmacro()
|
||||
|
||||
###############################################################################
|
||||
# add_to_cpack_ignored_files(<item> [TRUE])
|
||||
#
|
||||
@@ -104,3 +20,29 @@ macro(add_to_cpack_ignored_files ITEM)
|
||||
set(ENV{CPACK_IGNORED_FILES} "${REAL_ITEM}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
###############################################################################
|
||||
# inline_cmake(TARGET FILE)
|
||||
#
|
||||
# A macro to execute inline CMake instructions from within a module source.
|
||||
###############################################################################
|
||||
macro(inline_cmake TARGET FILE)
|
||||
file(STRINGS ${FILE} SRC)
|
||||
set(CODE "")
|
||||
set(IN_CODE OFF)
|
||||
foreach(LINE IN LISTS SRC)
|
||||
if(IN_CODE)
|
||||
string(REGEX REPLACE "/// " "" CLEAN_LINE ${LINE})
|
||||
if(CLEAN_LINE MATCHES "^END CMAKE$")
|
||||
cmake_language(EVAL CODE "${CODE}")
|
||||
set(CODE "")
|
||||
set(IN_CODE OFF)
|
||||
else()
|
||||
set(CODE "${CODE}\n${CLEAN_LINE}")
|
||||
endif()
|
||||
elseif(LINE MATCHES "^/// BEGIN CMAKE$")
|
||||
message(STATUS "Executing inline CMake code for ${TARGET}")
|
||||
set(IN_CODE ON)
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
+19
-72
@@ -83,8 +83,9 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
* The "services.host" define is used in multiple different locations throughout
|
||||
* the configuration for the server name and pseudoclient hostnames. You should
|
||||
* change the value to the hostname you wish to use for your services server.
|
||||
*/
|
||||
define
|
||||
{
|
||||
@@ -126,8 +127,9 @@ define
|
||||
* and serverinfo configuration would look like:
|
||||
*
|
||||
* # This goes in inspircd.conf, *NOT* your Anope config!
|
||||
* <module name="account">
|
||||
* <module name="hidechans">
|
||||
* <module name="services_account">
|
||||
* <module name="services">
|
||||
* <module name="spanningtree">
|
||||
* <bind address="127.0.0.1" port="7000" type="servers">
|
||||
* <link name="services.example.com"
|
||||
@@ -135,7 +137,7 @@ define
|
||||
* port="7000"
|
||||
* sendpass="mypassword"
|
||||
* recvpass="mypassword">
|
||||
* <uline server="services.example.com" silent="yes">
|
||||
* <services server="services.example.com" silent="yes">
|
||||
*
|
||||
* An example configuration for UnrealIRCd that is compatible with the below uplink
|
||||
* and serverinfo configuration would look like:
|
||||
@@ -508,7 +510,7 @@ options
|
||||
*
|
||||
* Removing .UTF-8 will instead use the default encoding for the language, e.g. iso-8859-1 for western European languages.
|
||||
*/
|
||||
languages = "de_DE.UTF-8 el_GR.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 it_IT.UTF-8 nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 tr_TR.UTF-8"
|
||||
languages = "de_DE.UTF-8 el_GR.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 it_IT.UTF-8 nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 ro_RO.UTF-8 tr_TR.UTF-8"
|
||||
|
||||
/*
|
||||
* Default language that non- and newly-registered nicks will receive messages in.
|
||||
@@ -747,6 +749,7 @@ log
|
||||
* nickserv/drop/display - Allows dropping display nicks when preservedisplay is enabled
|
||||
* nickserv/drop/override - Allows dropping nicks without using a confirmation code
|
||||
* nickserv/recover - Can recover other users nicks
|
||||
* nickserv/resend - Can resend confirmation codes via email
|
||||
* operserv/config - Can modify services's configuration
|
||||
* operserv/oper/modify - Can add and remove operators with at most the same privileges
|
||||
* protected - Can not be kicked from channels by services
|
||||
@@ -811,7 +814,7 @@ opertype
|
||||
inherits = "Helper, Another Helper"
|
||||
|
||||
/* What commands (see above) this opertype may use */
|
||||
commands = "chanserv/list chanserv/suspend chanserv/topic memoserv/staff nickserv/list nickserv/suspend operserv/mode operserv/chankill operserv/akill operserv/session operserv/modinfo operserv/sqline operserv/oper operserv/kick operserv/ignore operserv/snline"
|
||||
commands = "chanserv/list chanserv/suspend chanserv/topic memoserv/staff nickserv/list nickserv/resend nickserv/suspend operserv/mode operserv/chankill operserv/akill operserv/session operserv/modinfo operserv/sqline operserv/oper operserv/kick operserv/ignore operserv/snline"
|
||||
|
||||
/* What privs (see above) this opertype has */
|
||||
privs = "chanserv/auspex chanserv/no-register-limit memoserv/* nickserv/auspex nickserv/confirm/*"
|
||||
@@ -1063,91 +1066,38 @@ mail
|
||||
* have will not be stored!
|
||||
*/
|
||||
|
||||
/*
|
||||
* [DEPRECATED] db_old
|
||||
*
|
||||
* This is the old binary database format from late Anope 1.7.x, Anope 1.8.x, and
|
||||
* early Anope 1.9.x. This module only loads these databases, and will NOT save them.
|
||||
* You should only use this to upgrade old databases to a newer database format by loading
|
||||
* other database modules in addition to this one, which will be used when saving databases.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_old"
|
||||
|
||||
/*
|
||||
* This is the encryption type used by the databases. This must be set correctly or
|
||||
* your passwords will not work. Valid options are: md5, oldmd5, sha1, and plain.
|
||||
* You must also be sure to load the correct encryption module below in the Encryption
|
||||
* Modules section so that your passwords work.
|
||||
*/
|
||||
#hash = "md5"
|
||||
}
|
||||
|
||||
/*
|
||||
* db_atheme
|
||||
*
|
||||
* This allows importing databases from Atheme. You should load another database module as
|
||||
* well as this as it can only read Atheme databases not write them.
|
||||
* This allows importing databases from Atheme. You should load another database
|
||||
* module like db_json as well as this as it can only read Atheme databases not
|
||||
* write them.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_atheme"
|
||||
|
||||
/*
|
||||
* The database name db_atheme should use.
|
||||
* The file that db_atheme will import your main database from.
|
||||
*/
|
||||
database = "atheme.db"
|
||||
}
|
||||
|
||||
/*
|
||||
* db_flatfile
|
||||
* [DEPRECATED] db_flatfile
|
||||
*
|
||||
* Stores your database in a custom flatfile format.
|
||||
*
|
||||
* This was the recommended database module in 2.0 but it is now recommended
|
||||
* that you use db_json instead. You can migrate your db_flatfile database to
|
||||
* db_json by loading db_flatfile BEFORE db_json, sending SIGUSR1 to force a
|
||||
* database write, and then unloading db_flatfile.
|
||||
* This allows importing databases from the custom flat file format used between
|
||||
* Anope 1.9.6 and 2.1.17. You should load another database module like db_json
|
||||
* as well as this as it can only read db_flatfile databases not write them.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_flatfile"
|
||||
|
||||
/*
|
||||
* The database name db_flatfile should use
|
||||
* The file that db_flatfile will import your main database from.
|
||||
*/
|
||||
database = "anope.db"
|
||||
|
||||
/*
|
||||
* Sets the number of days backups of databases are kept. If you don't give it,
|
||||
* or if you set it to 0, Anope won't backup the databases.
|
||||
*
|
||||
* This directive is optional, but recommended.
|
||||
*/
|
||||
keepbackups = 7
|
||||
|
||||
/*
|
||||
* Allows Anope to continue file write operations (i.e. database saving)
|
||||
* even if the original file cannot be backed up. Enabling this option may
|
||||
* allow Anope to continue operation under conditions where it might
|
||||
* otherwise fail, such as a nearly-full disk.
|
||||
*
|
||||
* NOTE: Enabling this option can cause irrecoverable data loss under some
|
||||
* conditions, so make CERTAIN you know what you're doing when you enable it!
|
||||
*
|
||||
* This directive is optional, and you are discouraged against enabling it.
|
||||
*/
|
||||
#nobackupokay = yes
|
||||
|
||||
/*
|
||||
* If enabled, services will fork a child process to save databases.
|
||||
*
|
||||
* This is only useful with very large databases, with hundreds
|
||||
* of thousands of objects, that have a noticeable delay from
|
||||
* writing databases.
|
||||
*/
|
||||
fork = no
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1371,7 +1321,7 @@ module
|
||||
#module { name = "enc_posix" }
|
||||
|
||||
/*
|
||||
* [DEPRECATED] enc_md5, enc_none, enc_old, enc_sha1, enc_sha256
|
||||
* [DEPRECATED] enc_md5, enc_none, enc_sha1, enc_sha256
|
||||
*
|
||||
* Provides verify-only support for passwords encrypted using encryption methods
|
||||
* from older versions of Anope. These methods are no longer considered secure
|
||||
@@ -1381,8 +1331,6 @@ module
|
||||
* enc_md5: Verifies passwords encrypted with the MD5 algorithm
|
||||
* enc_none: Verifies passwords that are not encrypted
|
||||
* enc_sha1: Verifies passwords encrypted with the SHA1 algorithm
|
||||
* enc_old: Verifies passwords encrypted with the broken MD5 algorithm used
|
||||
* before 1.7.17.
|
||||
* enc_sha256: Verifies passwords encrypted with the SHA256 algorithm using a
|
||||
* custom initialisation vector as a salt.
|
||||
*
|
||||
@@ -1391,7 +1339,6 @@ module
|
||||
*/
|
||||
#module { name = "enc_md5" }
|
||||
#module { name = "enc_none" }
|
||||
#module { name = "enc_old" }
|
||||
#module { name = "enc_sha1" }
|
||||
#module { name = "enc_sha256" }
|
||||
|
||||
|
||||
@@ -296,11 +296,9 @@ command { service = "BotServ"; name = "KICK ITALICS"; command = "botserv/kick/it
|
||||
command { service = "BotServ"; name = "KICK REPEAT"; command = "botserv/kick/repeat"; }
|
||||
command { service = "BotServ"; name = "KICK REVERSES"; command = "botserv/kick/reverses"; }
|
||||
command { service = "BotServ"; name = "KICK UNDERLINES"; command = "botserv/kick/underlines"; }
|
||||
|
||||
command { service = "BotServ"; name = "SET DONTKICKOPS"; command = "botserv/set/dontkickops"; }
|
||||
command { service = "BotServ"; name = "SET DONTKICKVOICES"; command = "botserv/set/dontkickvoices"; }
|
||||
|
||||
|
||||
/*
|
||||
* bs_set
|
||||
*
|
||||
@@ -341,7 +339,6 @@ privilege
|
||||
xop = "AOP"
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fantasy
|
||||
*
|
||||
@@ -387,7 +384,7 @@ fantasy { name = "ENFORCE"; command = "chanserv/enforce"; }
|
||||
fantasy { name = "ENTRYMSG"; command = "chanserv/entrymsg"; }
|
||||
fantasy { name = "FLAGS"; command = "chanserv/flags"; }
|
||||
fantasy { name = "HALFOP"; command = "chanserv/modes"; }
|
||||
fantasy { name = "HELP"; command = "generic/help"; prepend_channel = no; }
|
||||
fantasy { name = "HELP"; command = "generic/help"; prepend_channel = no; require_privilege = no; }
|
||||
fantasy { name = "HOP"; command = "chanserv/xop"; }
|
||||
fantasy { name = "INFO"; command = "chanserv/info"; prepend_channel = no; }
|
||||
fantasy { name = "INVITE"; command = "chanserv/invite"; }
|
||||
|
||||
@@ -990,8 +990,20 @@ module
|
||||
{
|
||||
name = "cs_entrymsg"
|
||||
|
||||
/* The maximum number of entrymsgs allowed per channel. If not set, defaults to 5. */
|
||||
/*
|
||||
* The maximum number of entry messages allowed per channel.
|
||||
*
|
||||
* Defaults to 5
|
||||
*/
|
||||
maxentries = 5
|
||||
|
||||
/*
|
||||
* Whether to include an IRCv3 time tag for the original add time on entry
|
||||
* messages.
|
||||
*
|
||||
* Defaults to yes.
|
||||
*/
|
||||
#timestamp = no
|
||||
}
|
||||
command { service = "ChanServ"; name = "ENTRYMSG"; command = "chanserv/entrymsg"; group = "chanserv/management"; }
|
||||
|
||||
@@ -1067,10 +1079,8 @@ module
|
||||
listmax = 50
|
||||
}
|
||||
command { service = "ChanServ"; name = "LIST"; command = "chanserv/list"; }
|
||||
|
||||
command { service = "ChanServ"; name = "SET PRIVATE"; command = "chanserv/set/private"; }
|
||||
|
||||
|
||||
/*
|
||||
* cs_log
|
||||
*
|
||||
@@ -1156,7 +1166,6 @@ command { service = "ChanServ"; name = "DEHALFOP"; command = "chanserv/modes"; g
|
||||
command { service = "ChanServ"; name = "VOICE"; command = "chanserv/modes"; group = "chanserv/status"; set = "VOICE" }
|
||||
command { service = "ChanServ"; name = "DEVOICE"; command = "chanserv/modes"; group = "chanserv/status"; unset = "VOICE" }
|
||||
|
||||
|
||||
/*
|
||||
* cs_register
|
||||
*
|
||||
|
||||
@@ -168,7 +168,13 @@ command { service = "HostServ"; name = "ON"; command = "hostserv/on"; }
|
||||
/*
|
||||
* hs_request
|
||||
*
|
||||
* Provides the commands hostserv/request, hostserv/activate, hostserv/reject, and hostserv/waiting.
|
||||
* Provides the commands:
|
||||
* hostserv/request - Requests a vhost.
|
||||
* hostserv/activate - Approves a requested vhost.
|
||||
* hostserv/reject - Rejects a requested vhost.
|
||||
* hostserv/waiting - Lists pending vhost requests.
|
||||
* hostserv/validate - Allows self-service approval of vhosts using DNS
|
||||
* validation (requires the dns module).
|
||||
*
|
||||
* Used to manage vhosts requested by users.
|
||||
*/
|
||||
@@ -186,11 +192,24 @@ module
|
||||
* If set, Anope will send a memo to all services staff when a new vhost is requested.
|
||||
*/
|
||||
#memooper = yes
|
||||
|
||||
/*
|
||||
* If DNS validation is enabled, how long should users have to wait between
|
||||
* attempts at DNS validation. Defaults to 5 minutes.
|
||||
*/
|
||||
#validationcooldown = 5m
|
||||
|
||||
/*
|
||||
* If DNS validation is enabled, the TXT record to look for when determining
|
||||
* if the requester controls the domain. Defaults to anope-dns-validation.
|
||||
*/
|
||||
#validationrecord = "anope-dns-validation"
|
||||
}
|
||||
command { service = "HostServ"; name = "REQUEST"; command = "hostserv/request"; }
|
||||
command { service = "HostServ"; name = "ACTIVATE"; command = "hostserv/activate"; permission = "hostserv/set"; }
|
||||
command { service = "HostServ"; name = "REJECT"; command = "hostserv/reject"; permission = "hostserv/set"; }
|
||||
command { service = "HostServ"; name = "WAITING"; command = "hostserv/waiting"; permission = "hostserv/set"; }
|
||||
#command { service = "HostServ"; name = "VALIDATE"; command = "hostserv/validate"; }
|
||||
|
||||
/*
|
||||
* hs_set
|
||||
|
||||
@@ -41,7 +41,6 @@ module { name = "help" }
|
||||
*/
|
||||
timeout = 5
|
||||
|
||||
|
||||
/* Only edit below if you are expecting to use os_dns or otherwise answer DNS queries. */
|
||||
|
||||
/*
|
||||
@@ -54,7 +53,6 @@ module { name = "help" }
|
||||
ip = "0.0.0.0"
|
||||
port = 53
|
||||
|
||||
|
||||
/*
|
||||
* SOA record information.
|
||||
*/
|
||||
|
||||
+95
-26
@@ -399,7 +399,12 @@ command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/
|
||||
/*
|
||||
* ns_group
|
||||
*
|
||||
* Provides the commands nickserv/group, nickserv/glist, and nickserv/ungroup.
|
||||
* Provides the commands:
|
||||
* nickserv/group
|
||||
* nickserv/ungroup
|
||||
* nickserv/glist
|
||||
* nickserv/saset/display
|
||||
* nickserv/set/display
|
||||
*
|
||||
* Used for controlling grouped nicknames.
|
||||
*/
|
||||
@@ -426,6 +431,12 @@ module
|
||||
command { service = "NickServ"; name = "GLIST"; command = "nickserv/glist"; }
|
||||
command { service = "NickServ"; name = "GROUP"; command = "nickserv/group"; }
|
||||
command { service = "NickServ"; name = "UNGROUP"; command = "nickserv/ungroup"; }
|
||||
command { service = "NickServ"; name = "SET DISPLAY"; command = "nickserv/set/display"; }
|
||||
command { service = "NickServ"; name = "SASET DISPLAY"; command = "nickserv/saset/display"; permission = "nickserv/saset/display"; }
|
||||
|
||||
# For compatibility with Atheme.
|
||||
command { service = "NickServ"; name = "SET ACCOUNTNAME"; command = "nickserv/set/display"; hide = yes; }
|
||||
command { service = "NickServ"; name = "SASET ACCOUNTNAME"; command = "nickserv/saset/display"; permission = "nickserv/saset/display"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_identify
|
||||
@@ -460,7 +471,6 @@ command { service = "NickServ"; name = "INFO"; command = "nickserv/info"; }
|
||||
command { service = "NickServ"; name = "SET HIDE"; command = "nickserv/set/hide"; }
|
||||
command { service = "NickServ"; name = "SASET HIDE"; command = "nickserv/saset/hide"; permission = "nickserv/saset/hide"; }
|
||||
|
||||
|
||||
/*
|
||||
* ns_list
|
||||
*
|
||||
@@ -479,11 +489,9 @@ module
|
||||
listmax = 50
|
||||
}
|
||||
command { service = "NickServ"; name = "LIST"; command = "nickserv/list"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET PRIVATE"; command = "nickserv/set/private"; }
|
||||
command { service = "NickServ"; name = "SASET PRIVATE"; command = "nickserv/saset/private"; permission = "nickserv/saset/private"; }
|
||||
|
||||
|
||||
/*
|
||||
* ns_logout
|
||||
*
|
||||
@@ -539,7 +547,7 @@ module
|
||||
* "mail" to require confirmation with a code provided via email.
|
||||
* "none" to automatically confirm (this is the default).
|
||||
*/
|
||||
registration = "none"
|
||||
registration = "code"
|
||||
|
||||
/*
|
||||
* The minimum length of time between consecutive uses of NickServ's RESEND command.
|
||||
@@ -554,7 +562,7 @@ module
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
nickregdelay = 15s
|
||||
#nickregdelay = 1m
|
||||
|
||||
/*
|
||||
* The length of time a user using an unconfirmed account has
|
||||
@@ -586,6 +594,9 @@ module
|
||||
command { service = "NickServ"; name = "CONFIRM RESETPASS"; command = "nickserv/confirm/resetpass"; }
|
||||
command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpass"; }
|
||||
|
||||
# For compatibility with Anope 2.0.
|
||||
command { service = "NickServ"; name = "GETPASS"; command = "nickserv/resetpass"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_sasl
|
||||
*
|
||||
@@ -605,17 +616,46 @@ module
|
||||
* The nick of the client which operates as the SASL agent.
|
||||
*/
|
||||
#agent = "NickServ"
|
||||
|
||||
/*
|
||||
* Sets the number of invalid SASL authentication attempts before services
|
||||
* removes a partially-connected user from the network. If not defined then
|
||||
* the value specified in options:badpasslimit will be used instead.
|
||||
*/
|
||||
#badpasslimit = 1
|
||||
|
||||
/*
|
||||
* Sets the time after which invalid SASL authentication attempts are
|
||||
* forgotten about. If a user does not fail to authenticate in this amount
|
||||
* of time, the incorrect password count will reset to zero. If not defined
|
||||
* then the value specified in options:badpasstimeout will be used instead.
|
||||
*/
|
||||
#badpasstimeout = 15m
|
||||
}
|
||||
|
||||
/*
|
||||
* ns_sasl_anonymous, ns_sasl_external, ns_sasl_plain
|
||||
*
|
||||
* Provides support for the following SASL mechanisms:
|
||||
*
|
||||
* ns_sasl_anonymous: Adds the ANONYMOUS mechanism which allows logging out of
|
||||
* an account. See RFC 4505 for more details.
|
||||
* ns_sasl_external: Adds the EXTERNAL mechanism which allows logging into an
|
||||
account using a TLS client certificate. See RFC 4422 for
|
||||
for more details.
|
||||
* ns_sasl_plain: Adds the PLAIN mechanism which allows logging in to an
|
||||
account using a plain text username and password. See RFC
|
||||
4422 for more details.
|
||||
*/
|
||||
module { name = "ns_sasl_anonymous" }
|
||||
module { name = "ns_sasl_external" }
|
||||
module { name = "ns_sasl_plain" }
|
||||
|
||||
/*
|
||||
* ns_set
|
||||
*
|
||||
* Provides the commands:
|
||||
* nickserv/set, nickserv/saset - Dummy help wrappers for the SET and SASET commands.
|
||||
* nickserv/set/autoop, nickserv/saset/autoop - Determines whether or not modes are automatically set users when joining a channel.
|
||||
* nickserv/set/display, nickserv/saset/display - Used for setting a users display name.
|
||||
* nickserv/set/keepmodes, nickserv/saset/keepmodes - Configure whether or not services should retain a user's modes across sessions.
|
||||
* nickserv/set/neverop, nickserv/saset/neverop - Used to configure whether a user can be added to access lists
|
||||
* nickserv/saset/noexpire - Used for configuring noexpire, which prevents nicks from expiring.
|
||||
* nickserv/set/password, nickserv/saset/password - Used for changing a users password.
|
||||
*/
|
||||
@@ -624,18 +664,9 @@ module { name = "ns_set" }
|
||||
command { service = "NickServ"; name = "SET"; command = "nickserv/set"; }
|
||||
command { service = "NickServ"; name = "SASET"; command = "nickserv/saset"; permission = "nickserv/saset/"; group = "nickserv/admin"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET AUTOOP"; command = "nickserv/set/autoop"; }
|
||||
command { service = "NickServ"; name = "SASET AUTOOP"; command = "nickserv/saset/autoop"; permission = "nickserv/saset/autoop"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET DISPLAY"; command = "nickserv/set/display"; }
|
||||
command { service = "NickServ"; name = "SASET DISPLAY"; command = "nickserv/saset/display"; permission = "nickserv/saset/display"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; }
|
||||
command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; permission = "nickserv/saset/password"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET NEVEROP"; command = "nickserv/set/neverop"; }
|
||||
command { service = "NickServ"; name = "SASET NEVEROP"; command = "nickserv/saset/neverop"; permission = "nickserv/saset/neverop"; }
|
||||
|
||||
command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; permission = "nickserv/saset/noexpire"; }
|
||||
|
||||
/*
|
||||
@@ -670,6 +701,17 @@ module { name = "ns_set_language" }
|
||||
command { service = "NickServ"; name = "SET LANGUAGE"; command = "nickserv/set/language"; }
|
||||
command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/saset/language"; permission = "nickserv/saset/language"; }
|
||||
|
||||
/*
|
||||
* ns_set_layout
|
||||
*
|
||||
* Provides the command nickserv/set/layout and nickserv/saset/layout.
|
||||
*
|
||||
* Allows configuring the layout that services uses.
|
||||
*/
|
||||
module { name = "ns_set_layout" }
|
||||
command { service = "NickServ"; name = "SET LAYOUT"; command = "nickserv/set/layout"; }
|
||||
command { service = "NickServ"; name = "SASET LAYOUT"; command = "nickserv/saset/layout"; permission = "nickserv/saset/layout"; }
|
||||
|
||||
/*
|
||||
* ns_set_message
|
||||
*
|
||||
@@ -696,29 +738,56 @@ command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/sas
|
||||
module { name = "ns_set_misc" }
|
||||
command { service = "NickServ"; name = "SET URL"; command = "nickserv/set/misc"; misc_description = _("Associate a URL with your account"); }
|
||||
command { service = "NickServ"; name = "SASET URL"; command = "nickserv/saset/misc"; misc_description = _("Associate a URL with this account"); permission = "nickserv/saset/url"; group = "nickserv/admin"; }
|
||||
#command { service = "NickServ"; name = "SET DISCORD"; command = "nickserv/set/misc"; misc_description = _("Associate a Discord account with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET DISCORD"; command = "nickserv/saset/misc"; misc_description = _("Associate a Discord account with this account"); permission = "nickserv/saset/discord"; group = "nickserv/admin"; }
|
||||
#command { service = "NickServ"; name = "SET MASTODON"; command = "nickserv/set/misc"; misc_description = _("Associate a Mastodon account with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET MASTODON"; command = "nickserv/saset/misc"; misc_description = _("Associate a Mastodon account with this account"); permission = "nickserv/saset/mastodon"; group = "nickserv/admin"; }
|
||||
#command { service = "NickServ"; name = "SET TIMEZONE"; command = "nickserv/set/misc"; misc_description = _("Associate a time zone with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET TIMEZONE"; command = "nickserv/saset/misc"; misc_description = _("Associate a time zone with this account"); permission = "nickserv/saset/timezone"; group = "nickserv/admin"; }
|
||||
#command { service = "NickServ"; name = "SET LOCATION"; command = "nickserv/set/misc"; misc_description = _("Associate a location with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET LOCATION"; command = "nickserv/saset/misc"; misc_description = _("Associate a location with this account"); permission = "nickserv/saset/location"; group = "nickserv/admin"; }
|
||||
|
||||
/*
|
||||
* ns_set_op
|
||||
*
|
||||
* Provides the commands:
|
||||
* nickserv/set/autoop, nickserv/saset/autoop - Allows configuring whether status modes are automatically granted when joining a channel.
|
||||
* nickserv/set/neverop, nickserv/saset/neverop - Allows configuring whether a user can be added to access lists.
|
||||
*/
|
||||
module { name = "ns_set_op" }
|
||||
|
||||
command { service = "NickServ"; name = "SET AUTOOP"; command = "nickserv/set/autoop"; }
|
||||
command { service = "NickServ"; name = "SASET AUTOOP"; command = "nickserv/saset/autoop"; permission = "nickserv/saset/autoop"; }
|
||||
|
||||
command { service = "NickServ"; name = "SET NEVEROP"; command = "nickserv/set/neverop"; }
|
||||
command { service = "NickServ"; name = "SASET NEVEROP"; command = "nickserv/saset/neverop"; permission = "nickserv/saset/neverop"; }
|
||||
|
||||
# For compatibility with DALnet Services.
|
||||
command { service = "NickServ"; name = "SET NOOP"; command = "nickserv/set/neverop"; hide = yes; }
|
||||
command { service = "NickServ"; name = "SASET NOOP"; command = "nickserv/saset/neverop"; permission = "nickserv/saset/neverop"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_set_protect
|
||||
*
|
||||
* Provides the commands nickserv/set/protect and kickserv/saset/protect.
|
||||
* Provides the commands nickserv/set/protect and nickserv/saset/protect.
|
||||
*
|
||||
* Used for configuring nickname protection.
|
||||
*/
|
||||
module { name = "ns_set_protect" }
|
||||
|
||||
command { service = "NickServ"; name = "SET PROTECT"; command = "nickserv/set/protect"; }
|
||||
command { service = "NickServ"; name = "SASET PROTECT"; command = "nickserv/saset/protect"; permission = "nickserv/saset/kill"; }
|
||||
command { service = "NickServ"; name = "SASET PROTECT"; command = "nickserv/saset/protect"; permission = "nickserv/saset/protect"; }
|
||||
|
||||
# For compatibility with Anope 2.0.
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/protect"; hide = yes; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/protect"; permission = "nickserv/saset/protect"; hide = yes; }
|
||||
|
||||
/*
|
||||
* ns_set_timezone
|
||||
*
|
||||
* Provides the command nickserv/set/timezone and nickserv/saset/timezone.
|
||||
*
|
||||
* Allows configuring the timezone that services uses.
|
||||
*/
|
||||
module { name = "ns_set_timezone" }
|
||||
command { service = "NickServ"; name = "SET TIMEZONE"; command = "nickserv/set/timezone"; }
|
||||
command { service = "NickServ"; name = "SASET TIMEZONE"; command = "nickserv/saset/timezone"; permission = "nickserv/saset/timezone"; }
|
||||
|
||||
/*
|
||||
* ns_suspend
|
||||
*
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# Anope Change Log
|
||||
|
||||
## Anope 2.1.19 (2025-11-01)
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* `pkg-config` is now required to find dependencies for the following modules on UNIX systems:
|
||||
- enc_argon2
|
||||
- ldap
|
||||
- mysql
|
||||
- regex_pcre2
|
||||
- regex_tre
|
||||
|
||||
* Support for InspIRCd v3 has been dropped ahead of it going EOL in two months. Please migrate to InspIRCd v4 to keep using Anope 2.1 with InspIRCd.
|
||||
|
||||
### Changes
|
||||
|
||||
* Added a Romanian translation (contributed by @KidProtect on GitHub).
|
||||
|
||||
* Added support for associating a timezone with an account to allow users to receive timestamps in their local timezone.
|
||||
|
||||
```
|
||||
/NICKSERV SET TIMEZONE Europe/London
|
||||
-NickServ- Timezone changed to Europe/Berlin.
|
||||
|
||||
/NICKSERV INFO test
|
||||
-NickServ- Account registered: Thu 09 Oct 2025 15:22:45 CEST (45 seconds ago)
|
||||
```
|
||||
|
||||
NOTE: This requires a compiler with C++20 timezone support.
|
||||
|
||||
* Added support for IRCv3 message tags when using Solanum git.
|
||||
|
||||
* Added support for language-specific time formats.
|
||||
|
||||
```
|
||||
/NICKSERV SET LANGUAGE tr_TR.UTF-8
|
||||
-NickServ- Dil Türkçe olarak değiştirildi.
|
||||
|
||||
/NICKSERV INFO test
|
||||
-NickServ- Hesap kaydedildi: Prş 09 Eki 2025 15:22:45 (6 dakika, 16 saniye önce)
|
||||
```
|
||||
|
||||
* Channel entry messages are now tagged with an IRCv3 time tag for the time they were created on supporting IRCds. This defaults to on but can be disabled using `{cs_entrymsg}:timestamp`.
|
||||
|
||||
* Reordered the information in the `nickserv/info` command output to show the registration dates before the seen information.
|
||||
|
||||
* Updated the Turkish translation (contributed by @CaPaCuL on GitHub).
|
||||
|
||||
* Updated the vendored libraries.
|
||||
+1
-1
@@ -7,7 +7,7 @@ if(WIN32)
|
||||
# Add README.txt to list of files for CPack to ignore
|
||||
add_to_cpack_ignored_files("README.txt$" TRUE)
|
||||
endif()
|
||||
set(DOCS Changes Changes.conf DEFCON FAQ INSTALL LANGUAGE MODULES ${CMAKE_CURRENT_BINARY_DIR}/README.txt WIN32.txt)
|
||||
set(DOCS CHANGES.md DEFCON FAQ INSTALL LANGUAGE MODULES ${CMAKE_CURRENT_BINARY_DIR}/README.txt WIN32.txt)
|
||||
install(FILES ${DOCS}
|
||||
DESTINATION ${DOC_DIR}
|
||||
)
|
||||
|
||||
+2
-7
@@ -10,14 +10,9 @@ Anope Multi Language Support
|
||||
|
||||
To build Anope with gettext support, gettext and its development libraries must be installed on the system.
|
||||
|
||||
On Debian install the locales-all package.
|
||||
On Debian-based systems install the locales-all package.
|
||||
|
||||
On Ubuntu run locale-gen for each language you want to enable.
|
||||
For example:
|
||||
locale-gen es_ES.UTF-8
|
||||
|
||||
Then execute:
|
||||
dpkg-reconfigure locales
|
||||
On RHEL-based systems run `yum list glibc-langpack-*` and install the languages you want to enable.
|
||||
|
||||
If you have already built Anope you will need to delete the build directory and rebuild from scratch.
|
||||
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@ Table of Contents
|
||||
|
||||
Anope currently works with:
|
||||
|
||||
* InspIRCd 3 or later
|
||||
* InspIRCd 4 or later
|
||||
* ircd-hybrid 8.2.34 or later
|
||||
* ircd-ratbox 3 or later
|
||||
* ngIRCd 19.2 or later
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
Anope Version 2.1.18
|
||||
--------------------
|
||||
Added a check that a non-deprecated database module is loaded.
|
||||
Added support for flexible and monospace layouts to make text easier to read on clients that use a variable-width font.
|
||||
Added support for logging about deprecated modules on boot.
|
||||
Added support for per-IRCd hints when a link fails.
|
||||
Added support for self-service validation of vhosts using DNS TXT records.
|
||||
Added support for separate bad password limits for pre-connection SASL authentication.
|
||||
Added support for SRV and TXT records to the dns module.
|
||||
Added the --nodb option to disable database and encrytption module checks.
|
||||
Added the nickname registration date to the nickserv/glist output.
|
||||
Changed db_flatfile to be import-only (migrate to db_json).
|
||||
Changed the default registration confirmation type to code validation.
|
||||
Changed the fantasy !help command to not require the FANTASY privilege by default.
|
||||
Changed various length measurement code to be UTF-8 aware.
|
||||
Disabled the nickname registration delay by default.
|
||||
Fixed reporting the MySQL version that the mysql module was built against.
|
||||
Improved the layout of the nickserv/info command.
|
||||
Modularised the ns_sasl module to make it easier to pick SASL mechanisms.
|
||||
Moved duration rounding logic from Anope::Expires to Anope::Duration.
|
||||
Removed support for importing old databases from 1.8.
|
||||
Removed support for verifying "old MD5" passwords from 1.7.
|
||||
Reworked how memory is allocated when formatting messages.
|
||||
|
||||
Anope Version 2.1.17
|
||||
--------------------
|
||||
Allowed opers to resend passwords for users in nickserv/resend.
|
||||
Fixed HostServ using a different valid username character set to the protocol module.
|
||||
Fixed losing the channel and nickname registration time when upgrading from an earlier 2.1 release.
|
||||
Improved the messages sent when a user is forced off a protected nickname.
|
||||
Simplified copying modules to the runtime directory on Windows.
|
||||
|
||||
Anope Version 2.1.16
|
||||
--------------------
|
||||
Added support for on-IRC code confirmation.
|
||||
@@ -1,3 +1,30 @@
|
||||
Anope Version 2.1.18
|
||||
--------------------
|
||||
Added the hostserv/validate command.
|
||||
Added the nickserv/saset/layout command.
|
||||
Added the nickserv/set/layout command.
|
||||
Added the ns_sasl_anonymous module.
|
||||
Added the ns_sasl_external module.
|
||||
Added the ns_sasl_plain module.
|
||||
Added the ns_set_layout module.
|
||||
Added the ns_set_op module.
|
||||
Added {hs_request}:validationcooldown (defaults to 5 minutes).
|
||||
Added {hs_request}:validationrecord (defaults to "anope-dns-validation").
|
||||
Added {ns_sasl}:badpasslimit (defaults to options:badpasslimit).
|
||||
Added {ns_sasl}:badpasstimeout (defaults to options:badpasstimeout).
|
||||
Moved nickserv/set/autoop and nickserv/saset/autoop to the ns_set_op module.
|
||||
Moved nickserv/set/display and nickserv/saset/display to the ns_set_group module.
|
||||
Moved nickserv/set/neverop and nickserv/saset/neverop to the ns_set_op module.
|
||||
Removed the db_old module.
|
||||
Removed the enc_old module.
|
||||
Removed {db_flatfile}:fork (module is now import-only).
|
||||
Removed {db_flatfile}:keepbackups (module is now import-only).
|
||||
Removed {db_flatfile}:nobackupokay (module is now import-only).
|
||||
|
||||
Anope Version 2.1.17
|
||||
--------------------
|
||||
Added the nickserv/resend oper privilege.
|
||||
|
||||
Anope Version 2.1.16
|
||||
--------------------
|
||||
Added fantasy:require_privilege (defaults to yes).
|
||||
+5
-6
@@ -48,11 +48,10 @@ private:
|
||||
public:
|
||||
Anope::string nick;
|
||||
Anope::string last_quit;
|
||||
Anope::string last_realname;
|
||||
/* Last usermask this nick was seen on, eg user@host */
|
||||
Anope::string last_usermask;
|
||||
/* Last uncloaked usermask, requires nickserv/auspex to see */
|
||||
Anope::string last_realhost;
|
||||
/* Last cloaked user@host this nick was seen using. */
|
||||
Anope::string last_userhost;
|
||||
/* Last real user@host this nick was seen using. */
|
||||
Anope::string last_userhost_real;
|
||||
time_t registered = Anope::CurTime;
|
||||
time_t last_seen = Anope::CurTime;
|
||||
|
||||
@@ -185,7 +184,7 @@ public:
|
||||
/** Checks whether this account is a services oper or not.
|
||||
* @return True if this account is a services oper, false otherwise.
|
||||
*/
|
||||
virtual bool IsServicesOper() const;
|
||||
bool IsServicesOper() const;
|
||||
|
||||
/** Retrieves the account id for this user */
|
||||
uint64_t GetId();
|
||||
|
||||
+8
-78
@@ -15,6 +15,9 @@
|
||||
|
||||
#include "hashcomp.h"
|
||||
|
||||
#define UTF_CPP_CPLUSPLUS 201703L
|
||||
#include "utfcpp/unchecked.h"
|
||||
|
||||
namespace Anope
|
||||
{
|
||||
/**
|
||||
@@ -52,6 +55,7 @@ namespace Anope
|
||||
string(const char *_str, size_type n) : _string(_str, n) { }
|
||||
string(const std::string &_str) : _string(_str) { }
|
||||
string(const ci::string &_str) : _string(_str.c_str()) { }
|
||||
string(const std::string_view &_sv) : _string(_sv.begin(), _sv.end()) { }
|
||||
string(const string &_str, size_type pos, size_type n = npos) : _string(_str._string, pos, n) { }
|
||||
template <class InputIterator> string(InputIterator first, InputIterator last) : _string(first, last) { }
|
||||
string(const string &) = default;
|
||||
@@ -129,6 +133,7 @@ namespace Anope
|
||||
* Returns the string's length.
|
||||
*/
|
||||
inline size_type length() const { return this->_string.length(); }
|
||||
inline size_type utf8length() const { return utf8::unchecked::distance(str().begin(), str().end()); }
|
||||
|
||||
/**
|
||||
* Returns the size of the currently allocated storage space in the string object.
|
||||
@@ -383,7 +388,7 @@ namespace Anope
|
||||
|
||||
/** Other command line options.
|
||||
*/
|
||||
extern CoreExport bool ReadOnly, NoFork, NoThird, NoPID, NoExpire, ProtocolDebug;
|
||||
extern CoreExport bool ReadOnly, NoFork, NoThird, NoDB, NoPID, NoExpire, ProtocolDebug;
|
||||
|
||||
/** The root of the Anope installation. Usually ~/anope
|
||||
*/
|
||||
@@ -463,33 +468,12 @@ namespace Anope
|
||||
extern CoreExport void Unhex(const string &src, string &dest);
|
||||
extern CoreExport void Unhex(const string &src, char *dest, size_t sz);
|
||||
|
||||
/** Base 64 encode a string
|
||||
* @param src The string to encode
|
||||
* @param target Where the encoded string is placed
|
||||
*/
|
||||
extern CoreExport void B64Encode(const string &src, string &target);
|
||||
|
||||
/** Base 64 decode a string
|
||||
* @param src The base64 encoded string
|
||||
* @param target The plain text result
|
||||
*/
|
||||
extern CoreExport void B64Decode(const string &src, string &target);
|
||||
|
||||
/** Encrypts what is in 'src' to 'dest'
|
||||
* @param src The source string to encrypt
|
||||
* @param dest The destination where the encrypted string is placed
|
||||
*/
|
||||
extern CoreExport bool Encrypt(const Anope::string &src, Anope::string &dest);
|
||||
|
||||
/** Returns a sequence of data formatted as the format argument specifies.
|
||||
** After the format parameter, the function expects at least as many
|
||||
** additional arguments as specified in format.
|
||||
* @param fmt Format of the Message
|
||||
* @param ... any number of parameters
|
||||
* @return a Anope::string
|
||||
*/
|
||||
extern CoreExport string printf(const char *fmt, ...) ATTR_FORMAT(1, 2);
|
||||
|
||||
/** Return the last error code
|
||||
* @return The error code
|
||||
*/
|
||||
@@ -513,9 +497,10 @@ namespace Anope
|
||||
/** Retrieves a human readable string representing the time in seconds
|
||||
* @param seconds The time on seconds, eg 60
|
||||
* @param nc The account to use language settings for to translate this string, if applicable
|
||||
* @param round Whether to round the duration to produce a shorter output.
|
||||
* @return A human readable string, eg "1 minute"
|
||||
*/
|
||||
extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = NULL);
|
||||
extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = nullptr, bool round = false);
|
||||
|
||||
/** Generates a human readable string of type "expires in ..."
|
||||
* @param expires time in seconds
|
||||
@@ -531,12 +516,6 @@ namespace Anope
|
||||
*/
|
||||
extern CoreExport Anope::string strftime(time_t t, const NickCore *nc = NULL, bool short_output = false);
|
||||
|
||||
/** Normalize buffer, stripping control characters and colors
|
||||
* @param A string to be parsed for control and color codes
|
||||
* @return A string stripped of control and color codes
|
||||
*/
|
||||
extern CoreExport Anope::string NormalizeBuffer(const Anope::string &);
|
||||
|
||||
/** Parses a raw message from the uplink and calls its command handler.
|
||||
* @param message Raw message from the uplink
|
||||
*/
|
||||
@@ -572,57 +551,8 @@ namespace Anope
|
||||
/** Generate a random number. */
|
||||
extern CoreExport int RandomNumber();
|
||||
|
||||
/** Calculates the levenshtein distance between two strings.
|
||||
* @param s1 The first string.
|
||||
* @param s2 The second string.
|
||||
*/
|
||||
extern CoreExport size_t Distance(const Anope::string &s1, const Anope::string &s2);
|
||||
|
||||
/** Update the current time. */
|
||||
extern CoreExport void UpdateTime();
|
||||
|
||||
/** Expands a path fragment that is relative to the base directory.
|
||||
* @param base The base directory that it is relative to.
|
||||
* @param fragment The fragment to expand.
|
||||
*/
|
||||
extern CoreExport Anope::string Expand(const Anope::string &base, const Anope::string &fragment);
|
||||
|
||||
/** Expands a config path. */
|
||||
inline auto ExpandConfig(const Anope::string &path) { return Expand(ConfigDir, path); }
|
||||
|
||||
/** Expands a data path. */
|
||||
inline auto ExpandData(const Anope::string &path) { return Expand(DataDir, path); }
|
||||
|
||||
/** Expands a locale path. */
|
||||
inline auto ExpandLocale(const Anope::string &path) { return Expand(LocaleDir, path); }
|
||||
|
||||
/** Expands a log path. */
|
||||
inline auto ExpandLog(const Anope::string &path) { return Expand(LogDir, path); }
|
||||
|
||||
/** Expands a module path. */
|
||||
inline auto ExpandModule(const Anope::string &path) { return Expand(ModuleDir, path); }
|
||||
|
||||
/** Formats a CTCP message for sending to a client.
|
||||
* @param name The name of the CTCP.
|
||||
* @param body If present then the body of the CTCP.
|
||||
* @return A formatted CTCP ready to send to a client.
|
||||
*/
|
||||
extern CoreExport Anope::string FormatCTCP(const Anope::string &name, const Anope::string &body = "");
|
||||
|
||||
/** Parses a CTCP message received from a client.
|
||||
* @param text The raw message to parse.
|
||||
* @param name The location to store the name of the CTCP.
|
||||
* @param body The location to store body of the CTCP if one is present.
|
||||
* @return True if the message was a well formed CTCP; otherwise, false.
|
||||
*/
|
||||
extern CoreExport bool ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body);
|
||||
|
||||
/** Replaces template variables within a string with values from a map.
|
||||
* @param str The string to template from.
|
||||
* @param vars The variables to replace within the string.
|
||||
* @return The specified string with all variables replaced within it.
|
||||
*/
|
||||
extern CoreExport Anope::string Template(const Anope::string &str, const Anope::map<Anope::string> &vars);
|
||||
}
|
||||
|
||||
/** sepstream allows for splitting token separated lists.
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ public:
|
||||
* @param message The users' message
|
||||
* @params tags Message tags
|
||||
*/
|
||||
virtual void OnMessage(User *u, const Anope::string &message, const Anope::map<Anope::string> &tags);
|
||||
void OnMessage(User *u, const Anope::string &message, const Anope::map<Anope::string> &tags);
|
||||
|
||||
/** Link a command name to a command in services
|
||||
* @param cname The command name
|
||||
|
||||
+11
-5
@@ -35,6 +35,14 @@ namespace Language
|
||||
*/
|
||||
extern void InitLanguages();
|
||||
|
||||
/** Sets the locale to the specified language.
|
||||
* @param lang The language to translate to.
|
||||
*/
|
||||
extern CoreExport void SetLocale(const char* lang);
|
||||
|
||||
/** Sets the locale back to the default. */
|
||||
extern CoreExport void ResetLocale();
|
||||
|
||||
/** Translates a string to the default language.
|
||||
* @param string A string to translate
|
||||
* @return The translated string if found, else the original string.
|
||||
@@ -101,6 +109,9 @@ namespace Language
|
||||
|
||||
/* Commonly used language strings */
|
||||
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s\032%s\032%s\002")
|
||||
#define CONFIRM_REGISTER_ADMIN _("All new accounts must be confirmed by an administrator. Please wait for your registration to be confirmed.")
|
||||
#define CONFIRM_REGISTER_CODE _("All new accounts must be confirmed. To confirm your account, type \002%s\002.")
|
||||
#define CONFIRM_REGISTER_MAIL _("All new accounts must be confirmed. To confirm your account, follow the instructions that were emailed to you.")
|
||||
#define SERVICE_UNAVAILABLE _("Sorry, %s is temporarily unavailable.")
|
||||
#define MORE_INFO _("Type \002%s\002 for more information.")
|
||||
#define BAD_USERHOST_MASK _("Mask must be in the form \037user\037@\037host\037.")
|
||||
@@ -114,7 +125,6 @@ namespace Language
|
||||
"cannot contain the space or tab characters.")
|
||||
#define PASSWORD_TOO_SHORT _("Your password is too short. It must be longer than %u characters.")
|
||||
#define PASSWORD_TOO_LONG _("Your password is too long. It must be shorter than %u characters.")
|
||||
#define NICK_NOT_REGISTERED _("Your nick isn't registered.")
|
||||
#define NICK_X_NOT_REGISTERED _("Nick \002%s\002 isn't registered.")
|
||||
#define NICK_X_NOT_IN_USE _("Nick \002%s\002 isn't currently in use.")
|
||||
#define NICK_X_NOT_ON_CHAN _("\002%s\002 is not currently on channel %s.")
|
||||
@@ -127,10 +137,6 @@ namespace Language
|
||||
#define UNKNOWN _("<unknown>")
|
||||
#define NO_EXPIRE _("does not expire")
|
||||
#define LIST_INCORRECT_RANGE _("Incorrect range specified. The correct syntax is \002#\037from\037-\037to\037\002.")
|
||||
#define NICK_IS_SECURE _("This nickname is registered and protected. If it is your " \
|
||||
"nick, type \002%s\032\037password\037\002. Otherwise, " \
|
||||
"please choose a different nick.")
|
||||
#define FORCENICKCHANGE_NOW _("This nickname has been registered; you may not use it.")
|
||||
#define NICK_CANNOT_BE_REGISTERED _("Nickname \002%s\002 may not be registered.")
|
||||
#define NICK_ALREADY_REGISTERED _("Nickname \002%s\002 is already registered!")
|
||||
#define NICK_SET_DISPLAY_CHANGED _("The new display is now \002%s\002.")
|
||||
|
||||
@@ -57,35 +57,3 @@ public:
|
||||
*/
|
||||
virtual bool InvalidRange(const Anope::string &list);
|
||||
};
|
||||
|
||||
/** This class handles formatting LIST/VIEW replies.
|
||||
*/
|
||||
class CoreExport ListFormatter final
|
||||
{
|
||||
public:
|
||||
typedef std::map<Anope::string, Anope::string> ListEntry;
|
||||
private:
|
||||
NickCore *nc;
|
||||
std::vector<Anope::string> columns;
|
||||
std::vector<ListEntry> entries;
|
||||
public:
|
||||
ListFormatter(NickCore *nc);
|
||||
ListFormatter &AddColumn(const Anope::string &name);
|
||||
void AddEntry(const ListEntry &entry);
|
||||
bool IsEmpty() const;
|
||||
void Process(std::vector<Anope::string> &);
|
||||
};
|
||||
|
||||
/** This class handles formatting INFO replies
|
||||
*/
|
||||
class CoreExport InfoFormatter final
|
||||
{
|
||||
NickCore *nc;
|
||||
std::vector<std::pair<Anope::string, Anope::string> > replies;
|
||||
unsigned longest = 0;
|
||||
public:
|
||||
InfoFormatter(NickCore *nc);
|
||||
void Process(std::vector<Anope::string> &);
|
||||
Anope::string &operator[](const Anope::string &key);
|
||||
void AddOption(const Anope::string &opt);
|
||||
};
|
||||
|
||||
+15
-10
@@ -70,11 +70,6 @@ public:
|
||||
*/
|
||||
Mode(const Anope::string &mname, ModeClass mclass, char mc, ModeType type);
|
||||
virtual ~Mode() = default;
|
||||
|
||||
/** Can a user set this mode, used for mlock
|
||||
* @param u The user
|
||||
*/
|
||||
virtual bool CanSet(User *u) const;
|
||||
};
|
||||
|
||||
/** This class is a user mode, all user modes use this/inherit from this
|
||||
@@ -88,6 +83,12 @@ public:
|
||||
* @param mc The mode char
|
||||
*/
|
||||
UserMode(const Anope::string &name, char mc);
|
||||
|
||||
/** Can a user set this mode, used for mlock
|
||||
* @param source The user who is setting the mode.
|
||||
* @param target The user the mode is being set on.
|
||||
*/
|
||||
virtual bool CanSet(User *source, User *target) const { return true; }
|
||||
};
|
||||
|
||||
class CoreExport UserModeParam
|
||||
@@ -122,7 +123,11 @@ public:
|
||||
*/
|
||||
ChannelMode(const Anope::string &name, char mc);
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
/** Can a user set this mode, used for mlock
|
||||
* @param u The user who is setting the mode.
|
||||
* @param c The channel the mode is being set on.
|
||||
*/
|
||||
virtual bool CanSet(User *u, Channel *c) const;
|
||||
|
||||
virtual void Check() { }
|
||||
|
||||
@@ -270,7 +275,7 @@ class CoreExport UserModeOperOnly
|
||||
public:
|
||||
UserModeOperOnly(const Anope::string &mname, char um) : UserMode(mname, um) { }
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *source, User *target) const override;
|
||||
};
|
||||
|
||||
class CoreExport UserModeNoone
|
||||
@@ -279,7 +284,7 @@ class CoreExport UserModeNoone
|
||||
public:
|
||||
UserModeNoone(const Anope::string &mname, char um) : UserMode(mname, um) { }
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *source, User *target) const override;
|
||||
};
|
||||
|
||||
/** Channel mode +k (key)
|
||||
@@ -302,7 +307,7 @@ public:
|
||||
ChannelModeOperOnly(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
|
||||
|
||||
/* Opers only */
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *u, Channel *c) const override;
|
||||
};
|
||||
|
||||
/** This class is used for channel modes only servers may set
|
||||
@@ -313,7 +318,7 @@ class CoreExport ChannelModeNoone
|
||||
public:
|
||||
ChannelModeNoone(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
|
||||
|
||||
bool CanSet(User *u) const override;
|
||||
bool CanSet(User *u, Channel *c) const override;
|
||||
};
|
||||
|
||||
/** This is the mode manager
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "services.h"
|
||||
#include "socketengine.h"
|
||||
#include "sockets.h"
|
||||
#include "textproc.h"
|
||||
#include "threadengine.h"
|
||||
#include "timers.h"
|
||||
#include "uplink.h"
|
||||
|
||||
+7
-3
@@ -158,7 +158,9 @@ enum
|
||||
PSEUDOCLIENT = 1 << 5,
|
||||
/* Module provides IRCd protocol support */
|
||||
PROTOCOL = 1 << 6,
|
||||
MT_END = 1 << 7
|
||||
/* Module is deprecated */
|
||||
DEPRECATED = 1 << 7,
|
||||
MT_END = DEPRECATED,
|
||||
};
|
||||
typedef unsigned short ModType;
|
||||
|
||||
@@ -1046,9 +1048,10 @@ public:
|
||||
|
||||
/** Called to determine if a channel mode can be set by a user
|
||||
* @param u The user
|
||||
* @param c The channel
|
||||
* @param cm The mode
|
||||
*/
|
||||
virtual EventReturn OnCanSet(User *u, const ChannelMode *cm) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
|
||||
virtual EventReturn OnCanSet(User *u, Channel *c, const ChannelMode *cm) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
|
||||
|
||||
virtual EventReturn OnCheckDelete(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
|
||||
|
||||
@@ -1245,9 +1248,10 @@ public:
|
||||
|
||||
/** Find the first module of a certain type
|
||||
* @param type The module type
|
||||
* @param ignoredeprecated Whether to ignore deprecated modules.
|
||||
* @return The module
|
||||
*/
|
||||
static Module *FindFirstOf(ModType type);
|
||||
static Module *FindFirstOf(ModType type, bool ignoredeprecated = false);
|
||||
|
||||
/** Checks whether this version of Anope is at least major.minor.patch.build
|
||||
* Throws a ModuleException if not
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace DNS
|
||||
{
|
||||
/** Valid query types
|
||||
@@ -29,8 +31,12 @@ namespace DNS
|
||||
QUERY_SOA = 6,
|
||||
/* Reverse DNS lookup */
|
||||
QUERY_PTR = 12,
|
||||
/* TXT lookup */
|
||||
QUERY_TXT = 16,
|
||||
/* IPv6 AAAA lookup */
|
||||
QUERY_AAAA = 28,
|
||||
/** SRV lookup */
|
||||
QUERY_SRV = 33,
|
||||
/* Zone transfer */
|
||||
QUERY_AXFR = 252,
|
||||
/* A lookup for any record */
|
||||
@@ -88,11 +94,23 @@ namespace DNS
|
||||
};
|
||||
};
|
||||
|
||||
namespace Record
|
||||
{
|
||||
struct SRV final
|
||||
{
|
||||
uint16_t priority = UINT16_MAX;
|
||||
uint16_t weight = 0;
|
||||
uint16_t port = 0;
|
||||
Anope::string host;
|
||||
};
|
||||
}
|
||||
|
||||
struct ResourceRecord final
|
||||
: Question
|
||||
{
|
||||
unsigned int ttl = 0;
|
||||
Anope::string rdata;
|
||||
std::shared_ptr<void> rdataobj;
|
||||
time_t created;
|
||||
|
||||
ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), created(Anope::CurTime) { }
|
||||
|
||||
@@ -18,6 +18,8 @@ public:
|
||||
Anope::string ident;
|
||||
Anope::string host;
|
||||
time_t time = 0;
|
||||
Anope::string validation_token;
|
||||
time_t last_validation = 0;
|
||||
|
||||
virtual ~HostRequest() = default;
|
||||
};
|
||||
|
||||
@@ -151,7 +151,7 @@ struct SASL::Session
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return Anope::Format("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return "A user";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -228,9 +228,7 @@ public:
|
||||
if (header.compare(0, 7, "Bearer ", 7) != 0)
|
||||
return false; // No token provided.
|
||||
|
||||
Anope::string rawtoken;
|
||||
Anope::B64Decode(header.substr(7), rawtoken);
|
||||
|
||||
auto rawtoken = Anope::B64Decode(header.substr(7));
|
||||
for (const auto &token : tokens)
|
||||
{
|
||||
if (!CompareToken(token, rawtoken))
|
||||
|
||||
+9
-5
@@ -131,11 +131,15 @@ public:
|
||||
/* The maximum length of a username. */
|
||||
size_t MaxUser = 0;
|
||||
|
||||
|
||||
/* Retrieves the next free UID or SID */
|
||||
virtual Anope::string UID_Retrieve();
|
||||
virtual Anope::string SID_Retrieve();
|
||||
|
||||
/** Retrieves advice on what might be the problem when a link fails.
|
||||
* @param advice The location to store the advice.
|
||||
*/
|
||||
virtual void GetLinkAdvice(std::vector<Anope::string> &advice) { }
|
||||
|
||||
/** Extracts a timestamp from a string. */
|
||||
virtual time_t ExtractTimestamp(const Anope::string &str);
|
||||
|
||||
@@ -211,8 +215,8 @@ public:
|
||||
virtual void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) = 0;
|
||||
virtual void SendGlobalPrivmsg(BotInfo *bi, const Server *desc, const Anope::string &msg) = 0;
|
||||
|
||||
virtual void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
|
||||
virtual void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
|
||||
virtual void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
|
||||
virtual void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
|
||||
|
||||
virtual void SendQuit(User *u, const Anope::string &msg = "", const Anope::string &opermsg = "");
|
||||
virtual void SendPing(const Anope::string &servname, const Anope::string &who);
|
||||
@@ -276,9 +280,9 @@ public:
|
||||
virtual void SendServer(const Server *) = 0;
|
||||
virtual void SendSquit(Server *, const Anope::string &message);
|
||||
|
||||
virtual void SendNumericInternal(int numeric, const Anope::string &dest, const std::vector<Anope::string> ¶ms);
|
||||
virtual void SendNumericInternal(unsigned numeric, const Anope::string &dest, const std::vector<Anope::string> ¶ms);
|
||||
template <typename... Args>
|
||||
void SendNumeric(int numeric, const Anope::string &dest, Args &&...args)
|
||||
void SendNumeric(unsigned numeric, const Anope::string &dest, Args &&...args)
|
||||
{
|
||||
SendNumericInternal(numeric, dest, { Anope::ToString(args)... });
|
||||
}
|
||||
|
||||
@@ -11,6 +11,93 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ANOPE_FORMAT(LAST, FORMAT, BUFFER) \
|
||||
do { \
|
||||
va_list _valist; \
|
||||
va_start(_valist, LAST); \
|
||||
(BUFFER) = Anope::Format(_valist, (FORMAT)); \
|
||||
va_end(_valist); \
|
||||
} while (false);
|
||||
|
||||
namespace Anope
|
||||
{
|
||||
/** Encode a string as base-64.
|
||||
* @param str The string to encode as base-64 .
|
||||
*/
|
||||
extern CoreExport Anope::string B64Encode(const Anope::string &str);
|
||||
|
||||
/** Decode a string from base-64.
|
||||
* @param str The string to decode from base-64.
|
||||
*/
|
||||
extern CoreExport Anope::string B64Decode(const Anope::string &str);
|
||||
|
||||
/** Calculates the levenshtein distance between two strings.
|
||||
* @param s1 The first string.
|
||||
* @param s2 The second string.
|
||||
*/
|
||||
extern CoreExport size_t Distance(const Anope::string &s1, const Anope::string &s2);
|
||||
|
||||
/** Expands a path fragment that is relative to the base directory.
|
||||
* @param base The base directory that it is relative to.
|
||||
* @param fragment The fragment to expand.
|
||||
*/
|
||||
extern CoreExport Anope::string Expand(const Anope::string &base, const Anope::string &fragment);
|
||||
|
||||
/** Expands a config path. */
|
||||
inline auto ExpandConfig(const Anope::string &path) { return Expand(ConfigDir, path); }
|
||||
|
||||
/** Expands a data path. */
|
||||
inline auto ExpandData(const Anope::string &path) { return Expand(DataDir, path); }
|
||||
|
||||
/** Expands a locale path. */
|
||||
inline auto ExpandLocale(const Anope::string &path) { return Expand(LocaleDir, path); }
|
||||
|
||||
/** Expands a log path. */
|
||||
inline auto ExpandLog(const Anope::string &path) { return Expand(LogDir, path); }
|
||||
|
||||
/** Expands a module path. */
|
||||
inline auto ExpandModule(const Anope::string &path) { return Expand(ModuleDir, path); }
|
||||
|
||||
/** Formats a string using one or more values. This uses snprintf internally but with a flexible buffer.
|
||||
* @param fmt The message to format.
|
||||
*/
|
||||
extern CoreExport Anope::string Format(const char *fmt, ...) ATTR_FORMAT(1, 2);
|
||||
|
||||
/** Formats a string using a list of values. This uses snprintf internally but with a flexible buffer.
|
||||
* @param valist A list of values to format the message with.
|
||||
* @param fmt The message to format.
|
||||
*/
|
||||
extern CoreExport Anope::string Format(va_list &valist, const char *fmt) ATTR_FORMAT(2, 0);
|
||||
|
||||
/** Formats a CTCP message for sending to a client.
|
||||
* @param name The name of the CTCP.
|
||||
* @param body If present then the body of the CTCP.
|
||||
* @return A formatted CTCP ready to send to a client.
|
||||
*/
|
||||
extern CoreExport Anope::string FormatCTCP(const Anope::string &name, const Anope::string &body = "");
|
||||
|
||||
/** Parses a CTCP message received from a client.
|
||||
* @param text The raw message to parse.
|
||||
* @param name The location to store the name of the CTCP.
|
||||
* @param body The location to store body of the CTCP if one is present.
|
||||
* @return True if the message was a well formed CTCP; otherwise, false.
|
||||
*/
|
||||
extern CoreExport bool ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body);
|
||||
|
||||
/** Remove all formatting characters from a string.
|
||||
* @param text A string containing formatting characters.
|
||||
* @return A copy of \p text with all formatting characters removed.
|
||||
*/
|
||||
extern CoreExport Anope::string RemoveFormatting(const Anope::string &text);
|
||||
|
||||
/** Replaces template variables within a string with values from a map.
|
||||
* @param str The string to template from.
|
||||
* @param vars The variables to replace within the string.
|
||||
* @return The specified string with all variables replaced within it.
|
||||
*/
|
||||
extern CoreExport Anope::string Template(const Anope::string &str, const Anope::map<Anope::string> &vars);
|
||||
}
|
||||
|
||||
class CoreExport HelpWrapper final
|
||||
{
|
||||
private:
|
||||
@@ -22,6 +109,21 @@ public:
|
||||
void SendTo(CommandSource &source);
|
||||
};
|
||||
|
||||
class CoreExport InfoFormatter final
|
||||
{
|
||||
private:
|
||||
size_t longest = 0;
|
||||
NickCore *nc;
|
||||
std::vector<Anope::string> options;
|
||||
std::vector<std::pair<Anope::string, Anope::string>> replies;
|
||||
|
||||
public:
|
||||
InfoFormatter(NickCore *nc);
|
||||
Anope::string &operator[](const Anope::string &key);
|
||||
void AddOption(const Anope::string &opt);
|
||||
void SendTo(CommandSource &source);
|
||||
};
|
||||
|
||||
class CoreExport LineWrapper final
|
||||
{
|
||||
private:
|
||||
@@ -34,3 +136,26 @@ public:
|
||||
bool GetLine(Anope::string &out);
|
||||
};
|
||||
|
||||
class CoreExport ListFormatter final
|
||||
{
|
||||
public:
|
||||
using ListEntry = std::map<Anope::string, Anope::string>;
|
||||
using FlexibleFormatFn = std::function<Anope::string(ListEntry &)>;
|
||||
|
||||
private:
|
||||
std::vector<Anope::string> columns;
|
||||
std::vector<ListEntry> entries;
|
||||
FlexibleFormatFn flexiblerow;
|
||||
NickCore *nc;
|
||||
void SendFixed(CommandSource &source);
|
||||
void SendFlexible(CommandSource &source);
|
||||
|
||||
public:
|
||||
ListFormatter(NickCore *nc);
|
||||
ListFormatter &AddColumn(const Anope::string &name);
|
||||
void AddEntry(const ListEntry &entry);
|
||||
bool IsEmpty() const;
|
||||
void SendTo(CommandSource &source);
|
||||
void SetFlexible(const Anope::string &format);
|
||||
void SetFlexible(const FlexibleFormatFn &formatter);
|
||||
};
|
||||
|
||||
+1
-1
@@ -253,7 +253,7 @@ public:
|
||||
*/
|
||||
bool HasPriv(const Anope::string &privstr);
|
||||
|
||||
/** Update the last usermask stored for a user. */
|
||||
/** Update the last mask stored for a user. */
|
||||
void UpdateHost();
|
||||
|
||||
/** Update the away state for a user. */
|
||||
|
||||
+310
-56
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Anope\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-06-25 15:33+0100\n"
|
||||
"PO-Revision-Date: 2025-06-25 15:33+0100\n"
|
||||
"POT-Creation-Date: 2025-10-21 11:13+0100\n"
|
||||
"PO-Revision-Date: 2025-10-21 11:13+0100\n"
|
||||
"Last-Translator: Sadie Powell <sadie@witchery.services>\n"
|
||||
"Language-Team: English\n"
|
||||
"Language: en_US\n"
|
||||
@@ -342,6 +342,66 @@ msgstr ""
|
||||
msgid "[auto-memo] The memo you sent to %s has been viewed."
|
||||
msgstr ""
|
||||
|
||||
msgid "{host}: {session} sessions"
|
||||
msgstr ""
|
||||
|
||||
msgid "{mask}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{mask} -- created by {creator}; {expires}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{mask} -- created by {creator}; {expires} ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{mask} on {type} -- created by {creator}; expires in {expires}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{mask} on {type} -- created by {creator}; expires in {expires} ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name} ({description})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name} ({mask}) [{realname}]"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name} -- {users} user(s); +{modes}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name} -- {users} user(s); +{modes} ({topic})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name} = {level}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name} = {value}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{name}: {description}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{nick}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{nick} (last mask: {last_mask})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{nick} ({mask}) [{real_name}]"
|
||||
msgstr ""
|
||||
|
||||
msgid "{nick}: registered on {registered}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{nick}: registered on {registered}; expires in {expires}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{}{module_name}}:{name} = {value}"
|
||||
msgstr ""
|
||||
|
||||
msgid "[target] [password]"
|
||||
msgstr ""
|
||||
|
||||
@@ -585,6 +645,9 @@ msgstr ""
|
||||
msgid "nickname new-password"
|
||||
msgstr ""
|
||||
|
||||
msgid "nickname timezone"
|
||||
msgstr ""
|
||||
|
||||
msgid "nickname [code]"
|
||||
msgstr ""
|
||||
|
||||
@@ -597,7 +660,10 @@ msgstr ""
|
||||
msgid "nickname [+expiry] [reason]"
|
||||
msgstr ""
|
||||
|
||||
msgid "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
|
||||
msgid "nickname {EMAIL | STATUS | MASK | QUIT} {ON | OFF}"
|
||||
msgstr ""
|
||||
|
||||
msgid "nickname {FIXED | FLEXIBLE | MONOSPACE}"
|
||||
msgstr ""
|
||||
|
||||
msgid "nickname {ON | delay | OFF}"
|
||||
@@ -645,6 +711,9 @@ msgstr ""
|
||||
msgid "server [reason]"
|
||||
msgstr ""
|
||||
|
||||
msgid "timezone"
|
||||
msgstr ""
|
||||
|
||||
msgid "type parameters"
|
||||
msgstr ""
|
||||
|
||||
@@ -688,9 +757,6 @@ msgstr ""
|
||||
msgid "%2d %-16s letters: %s, words: %s, lines: %s, smileys: %s, actions: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "%b %d %Y %H:%M:%S %Z"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%c is an unknown status mode."
|
||||
msgstr ""
|
||||
@@ -825,6 +891,10 @@ msgstr ""
|
||||
msgid "%s (%s) was last seen quitting (%s) %s ago (%s)."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s (ID: %zu)"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s (minimum %d/%d%%)"
|
||||
msgstr ""
|
||||
@@ -929,10 +999,6 @@ msgstr ""
|
||||
msgid "%s has no new memos."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s is %s"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "%s is a Services Operator of type %s."
|
||||
msgstr ""
|
||||
@@ -1263,9 +1329,6 @@ msgstr ""
|
||||
msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Account id"
|
||||
msgstr ""
|
||||
|
||||
msgid "Account registered"
|
||||
msgstr ""
|
||||
|
||||
@@ -1341,6 +1404,9 @@ msgstr ""
|
||||
msgid "Additionally, Services Operators with the nickserv/drop/override permission can replace code with OVERRIDE to drop without a confirmation code."
|
||||
msgstr ""
|
||||
|
||||
msgid "Additionally, Services Operators with the nickserv/resend permission can specify a nickname to resend a confirmation email for another account."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Additionally, if fantasy is enabled fantasy commands can be executed by prefixing the command name with one of the following characters: %s"
|
||||
msgstr ""
|
||||
@@ -1376,7 +1442,14 @@ msgstr ""
|
||||
msgid "All modes cleared on %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."
|
||||
msgid "All new accounts must be confirmed by an administrator. Please wait for your registration to be confirmed."
|
||||
msgstr ""
|
||||
|
||||
msgid "All new accounts must be confirmed. To confirm your account, follow the instructions that were emailed to you."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "All new accounts must be confirmed. To confirm your account, type %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "All of your memos have been deleted."
|
||||
@@ -1520,7 +1593,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"Allows Services Operators to manipulate the AKILL list. If a user matching an AKILL mask attempts to connect, services will issue a KILL for that user and, on supported server types, will instruct all servers to add a ban for the mask which the user matched.\n"
|
||||
"\n"
|
||||
"%sADD adds the given mask to the AKILL list for the given reason, which must be given. Mask should be in the format of nick!user@host#realname, though all that is required is user@host. If a real name is specified, the reason must be prepended with a :. expiry is specified as an integer followed by one of d (days), h (hours), or m (minutes). Combinations (such as 1h30m) are not permitted. If a unit specifier is not included, the default is days (so +30 by itself means 30 days). To add an AKILL which does not expire, use +0. If the usermask to be added starts with a +, an expiry time must be given, even if it is the same as the default. The current AKILL default expiry time can be found with the STATSAKILL command."
|
||||
"%sADD adds the given mask to the AKILL list for the given reason, which must be given. Mask should be in the format of nick!user@host#realname, though all that is required is user@host. If a real name is specified, the reason must be prepended with a :. expiry is specified as an integer followed by one of d (days), h (hours), or m (minutes). Combinations (such as 1h30m) are not permitted. If a unit specifier is not included, the default is days (so +30 by itself means 30 days). To add an AKILL which does not expire, use +0. If the mask to be added starts with a +, an expiry time must be given, even if it is the same as the default. The current AKILL default expiry time can be found with the STATSAKILL command."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
@@ -1631,11 +1704,11 @@ msgid "Allows you to kill a user from the network. Parameters are the same as fo
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Allows you to prevent certain pieces of information from being displayed when someone does a %sINFO on the nick. You can hide the email address (EMAIL), last seen user@host mask (USERMASK), the services access status (STATUS) and last quit message (QUIT). The second parameter specifies whether the information should be displayed (OFF) or hidden (ON)."
|
||||
msgid "Allows you to prevent certain pieces of information from being displayed when someone does a %sINFO on the nick. You can hide the email address (EMAIL), last seen user@host mask (MASK), the services access status (STATUS) and last quit message (QUIT). The second parameter specifies whether the information should be displayed (OFF) or hidden (ON)."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Allows you to prevent certain pieces of information from being displayed when someone does a %sINFO on your nick. You can hide your email address(EMAIL), last seen user@host mask (USERMASK), your services access status (STATUS) and last quit message (QUIT). The second parameter specifies whether the information should be displayed (OFF) or hidden (ON)."
|
||||
msgid "Allows you to prevent certain pieces of information from being displayed when someone does a %sINFO on your nick. You can hide your email address(EMAIL), last seen user@host mask (MASK), your services access status (STATUS) and last quit message (QUIT). The second parameter specifies whether the information should be displayed (OFF) or hidden (ON)."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
@@ -1688,7 +1761,7 @@ msgstr ""
|
||||
msgid "Associates the given email address with your nickname. This address will be displayed whenever someone requests information on the nickname with the INFO command."
|
||||
msgstr ""
|
||||
|
||||
msgid "Auto-op"
|
||||
msgid "Auto op"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
@@ -1724,6 +1797,10 @@ msgstr ""
|
||||
msgid "Available privileges for %s:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Available timezones in the %s region:"
|
||||
msgstr ""
|
||||
|
||||
msgid "BANS enforced by "
|
||||
msgstr ""
|
||||
|
||||
@@ -1910,9 +1987,6 @@ msgstr ""
|
||||
msgid "Bot won't kick for repeats anymore."
|
||||
msgstr ""
|
||||
|
||||
msgid "By"
|
||||
msgstr ""
|
||||
|
||||
msgid "CLEAR target"
|
||||
msgstr ""
|
||||
|
||||
@@ -2000,6 +2074,12 @@ msgstr ""
|
||||
msgid "Changes the successor of a channel. If the founder's nickname expires or is dropped while the channel is still registered, the successor will become the new founder of the channel. The successor's nickname must be a registered one. If there's no successor set, then the first nickname on the access list (with the highest access, if applicable) will become the new founder, but if the access list is empty, the channel will be dropped."
|
||||
msgstr ""
|
||||
|
||||
msgid "Changes the timezone services uses when sending messages to the given user (for example, when responding to a command they send). timezone should be chosen from an entry in one of the supported timezone regions:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Changes the timezone services uses when sending messages to you (for example, when responding to a command you send). timezone should be chosen from an entry in one of the supported timezone regions:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Changes when you will be notified about new memos (only for nicknames)"
|
||||
msgstr ""
|
||||
|
||||
@@ -2203,6 +2283,29 @@ msgstr ""
|
||||
msgid "Configures reverses kicker"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Configures the layout used by the account for services messages.\n"
|
||||
"\n"
|
||||
"When the layout is set to FIXED services will use tables and position text such that it looks good in a client that uses a fixed-width font.\n"
|
||||
"\n"
|
||||
"When the layout is set to FLEXIBLE services will use an alternate format for messages and avoid any positioning that might be broken by a variable-width font.\n"
|
||||
"\n"
|
||||
"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 ""
|
||||
|
||||
msgid "Configures the layout used for services messages"
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Configures the layout used for services messages.\n"
|
||||
"\n"
|
||||
"When the layout is set to FIXED services will use tables and position text such that it looks good in a client that uses a fixed-width font.\n"
|
||||
"\n"
|
||||
"When the layout is set to FLEXIBLE services will use an alternate format for messages and avoid any positioning that might be broken by a variable-width font.\n"
|
||||
"\n"
|
||||
"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 ""
|
||||
|
||||
msgid "Configures the time bot bans expire in"
|
||||
msgstr ""
|
||||
|
||||
@@ -2885,6 +2988,9 @@ msgstr ""
|
||||
msgid "Fingerprint %s is already in use."
|
||||
msgstr ""
|
||||
|
||||
msgid "Fixed layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Flags"
|
||||
msgstr ""
|
||||
|
||||
@@ -2896,6 +3002,9 @@ msgstr ""
|
||||
msgid "Flags list for %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Flexible layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Flood kicker"
|
||||
msgstr ""
|
||||
|
||||
@@ -3012,10 +3121,6 @@ msgstr ""
|
||||
msgid "Identify yourself with your password"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "If you do not change within %s, I will change your nick."
|
||||
msgstr ""
|
||||
|
||||
msgid "Ignore list has been cleared."
|
||||
msgstr ""
|
||||
|
||||
@@ -3039,6 +3144,10 @@ msgstr ""
|
||||
msgid "Information about channel %s:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Information about nick %s:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Invalid duration %s, using %d days."
|
||||
msgstr ""
|
||||
@@ -3133,6 +3242,9 @@ msgstr ""
|
||||
msgid "Language for %s changed to %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Last mask"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Last memo to %s has been cancelled."
|
||||
msgstr ""
|
||||
@@ -3143,7 +3255,7 @@ msgstr ""
|
||||
msgid "Last seen"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last seen address"
|
||||
msgid "Last seen mask"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last topic"
|
||||
@@ -3152,7 +3264,16 @@ msgstr ""
|
||||
msgid "Last used"
|
||||
msgstr ""
|
||||
|
||||
msgid "Last usermask"
|
||||
#, c-format
|
||||
msgid "Layout is now fixed for %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Layout is now flexible for %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Layout is now monospace for %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Level"
|
||||
@@ -3390,7 +3511,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"Maintains the AutoKick list for a channel. If a user on the AutoKick list attempts to join the channel, %s will ban that user from the channel, then kick the user.\n"
|
||||
"\n"
|
||||
"The %sADD command adds the given nick or usermask to the AutoKick list. If a reason is given with the command, that reason will be used when the user is kicked; if not, the default reason is \"User has been banned from the channel\". When akicking a registered nick the %s account will be added to the akick list instead of the mask. All users within that nickgroup will then be akicked. \n"
|
||||
"The %sADD command adds the given nick or mask to the AutoKick list. If a reason is given with the command, that reason will be used when the user is kicked; if not, the default reason is \"User has been banned from the channel\". When akicking a registered nick the %s account will be added to the akick list instead of the mask. All users within that nickgroup will then be akicked. \n"
|
||||
"\n"
|
||||
"The %sDEL command removes the given nick or mask from the AutoKick list. It does not, however, remove any bans placed by an AutoKick; those must be removed manually.\n"
|
||||
"\n"
|
||||
@@ -3414,7 +3535,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"Maintains the bad words list for a channel. The bad words list determines which words are to be kicked when the bad words kicker is enabled. For more information, type %sKICK%s.\n"
|
||||
"\n"
|
||||
"The ADD command adds the given word to the bad words list. If SINGLE is specified, a kick will be done only if a user says the entire word. If START is specified, a kick will be done if a user says a word that starts with word. If END is specified, a kick will be done if a user says a word that ends with word. If you don't specify anything, a kick will be issued every time word is said by a user.\n"
|
||||
"The ADD command adds the given word to the bad words list. If SINGLE is specified, a kick will be done only if a user says the entire word. If START is specified, a kick will be done if a user says a word that starts with word. If END is specified, a kick will be done if a user says a word that ends with word. If you don't specify anything, a kick will be issued every time word is said by a user. This will be shown in the LIST output as ANY.\n"
|
||||
"\n"
|
||||
"The DEL command removes the given word from the bad words list. If a list of entry numbers is given, those entries are deleted. (See the example for LIST below.)\n"
|
||||
"\n"
|
||||
@@ -3643,10 +3764,17 @@ msgstr ""
|
||||
msgid "Module: %s [%s] [%s]"
|
||||
msgstr ""
|
||||
|
||||
msgid "Monospace layout"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Multiple languages matched %s. Please be more specific."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Multiple timezones matched %s. Please be more specific."
|
||||
msgstr ""
|
||||
|
||||
msgid "NOTICE: In order to register a channel, you must have first registered your nickname."
|
||||
msgstr ""
|
||||
|
||||
@@ -3663,7 +3791,7 @@ msgstr ""
|
||||
msgid "Never"
|
||||
msgstr ""
|
||||
|
||||
msgid "Never-op"
|
||||
msgid "Never op"
|
||||
msgstr ""
|
||||
|
||||
msgid "Nick"
|
||||
@@ -3677,6 +3805,10 @@ msgstr ""
|
||||
msgid "Nick %s is already an operator."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Nick %s is already confirmed."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Nick %s is an illegal nickname and cannot be used."
|
||||
msgstr ""
|
||||
@@ -3782,7 +3914,7 @@ msgstr ""
|
||||
msgid "No bot"
|
||||
msgstr ""
|
||||
|
||||
msgid "No expire"
|
||||
msgid "No expiry"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
@@ -4497,6 +4629,9 @@ msgstr ""
|
||||
msgid "Server %s must be quit before it can be deleted."
|
||||
msgstr ""
|
||||
|
||||
msgid "Server: {server} = {ip} -- limit: {limit}; state: {state}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Servers"
|
||||
msgstr ""
|
||||
|
||||
@@ -4645,6 +4780,9 @@ msgstr ""
|
||||
msgid "Set the successor for a channel"
|
||||
msgstr ""
|
||||
|
||||
msgid "Set the timezone services will use when messaging you"
|
||||
msgstr ""
|
||||
|
||||
msgid "Set the vhost for all nicks in an account"
|
||||
msgstr ""
|
||||
|
||||
@@ -5165,6 +5303,10 @@ msgstr ""
|
||||
msgid "The Defcon level is now at: %d"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "The confirmation code for %s has been re-sent to %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "The defcon system can be used to implement a pre-defined set of restrictions to services useful during an attempted attack on the network."
|
||||
msgstr ""
|
||||
|
||||
@@ -5453,7 +5595,7 @@ msgstr ""
|
||||
msgid "This command unloads the module named modname."
|
||||
msgstr ""
|
||||
|
||||
msgid "This command will resend you the registration confirmation email."
|
||||
msgid "This command will resend a registration confirmation email."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
@@ -5468,14 +5610,11 @@ msgstr ""
|
||||
msgid "This nickname has been recovered by %s. If you did not do this then %s may have your password, and you should change it."
|
||||
msgstr ""
|
||||
|
||||
msgid "This nickname has been registered; you may not use it."
|
||||
msgstr ""
|
||||
|
||||
msgid "This nickname is suspended."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "This nickname is registered and protected. If it is your nick, type %spassword. Otherwise, please choose a different nick."
|
||||
msgid "This nickname is registered and has protection enabled. If it belongs to you, type %spassword to identify to your account."
|
||||
msgstr ""
|
||||
|
||||
msgid "This option makes a channel unassignable. If a bot is already assigned to the channel, it is unassigned automatically when you enable it."
|
||||
@@ -5484,6 +5623,14 @@ msgstr ""
|
||||
msgid "This option prevents a bot from being assigned to a channel by users that aren't Services Operators."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Timezone changed to %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Timezone for %s changed to %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "To delete, type: %s %d"
|
||||
msgstr ""
|
||||
@@ -5598,6 +5745,10 @@ msgstr ""
|
||||
msgid "Type %soption for more information on a specific option. The options will be set on the given nickname."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Type %sregion to list timezones for a region."
|
||||
msgstr ""
|
||||
|
||||
msgid "Un-Load a module"
|
||||
msgstr ""
|
||||
|
||||
@@ -5605,6 +5756,10 @@ msgstr ""
|
||||
msgid "Unable to find regex engine %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Unable to find the DNS record required to validate %s. If you have not already done this add a TXT record for %s with the value %s and re-execute this command."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Unable to load module %s."
|
||||
msgstr ""
|
||||
@@ -5638,11 +5793,11 @@ msgid "Unknown command %s. Did you mean %s?"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Unknown command %s. Did you mean %s? Type \"%s\" for help."
|
||||
msgid "Unknown command %s. Did you mean %s? Type %s for help."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Unknown command %s. Type \"%s\" for help."
|
||||
msgid "Unknown command %s. Type %s for help."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
@@ -5763,6 +5918,10 @@ msgstr ""
|
||||
msgid "VHost for %s has been rejected."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "VHost for %s has been validated using DNS."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "VHost for account %s set to %s."
|
||||
msgstr ""
|
||||
@@ -5780,6 +5939,12 @@ msgstr ""
|
||||
msgid "VIEW [mask | list]"
|
||||
msgstr ""
|
||||
|
||||
msgid "Validates a previously requested vhost using DNS"
|
||||
msgstr ""
|
||||
|
||||
msgid "Validates a previously requested vhost using DNS. If you own the domain you have requested as a vhost you can validate your ownership of it using a DNS TXT record to approve your own vhost."
|
||||
msgstr ""
|
||||
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
@@ -6103,6 +6268,10 @@ msgstr ""
|
||||
msgid "You must wait %s before registering your nick."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "You must wait for %s before trying DNS validation again."
|
||||
msgstr ""
|
||||
|
||||
msgid "You need to be identified to use this command."
|
||||
msgstr ""
|
||||
|
||||
@@ -6174,24 +6343,10 @@ msgstr ""
|
||||
msgid "Your account %s has been successfully created."
|
||||
msgstr ""
|
||||
|
||||
msgid "Your account is already confirmed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Your account is not confirmed. To confirm it, follow the instructions that were emailed to you."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your account is not confirmed. To confirm it, type %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your account will expire, if not confirmed, in %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your confirmation code has been re-sent to %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your email address has been updated to %s"
|
||||
msgstr ""
|
||||
@@ -6239,9 +6394,6 @@ msgstr ""
|
||||
msgid "Your nick is already registered."
|
||||
msgstr ""
|
||||
|
||||
msgid "Your nick isn't registered."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your nickname is now being changed to %s"
|
||||
msgstr ""
|
||||
@@ -6250,6 +6402,10 @@ msgstr ""
|
||||
msgid "Your nickname now belongs to the account %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your nickname will be changed in %s if you do not identify."
|
||||
msgstr ""
|
||||
|
||||
msgid "Your oper block doesn't require logging in."
|
||||
msgstr ""
|
||||
|
||||
@@ -6271,7 +6427,15 @@ msgstr ""
|
||||
msgid "Your requested vhost has been rejected. Reason: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Your vhost has been requested."
|
||||
msgid "Your requested vhost has been validated via DNS."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your vhost %s has been requested."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Your vhost %s has been requested. If the requested vhost is for a valid DNS name you can add a TXT record for %s with the value %s and automatically approve your vhost using %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
@@ -6296,6 +6460,12 @@ msgstr ""
|
||||
msgid "Zone %s removed."
|
||||
msgstr ""
|
||||
|
||||
msgid "Zone: {zone}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Zone: {zone} = {servers}"
|
||||
msgstr ""
|
||||
|
||||
msgid "[1|2|3|4|5]"
|
||||
msgstr ""
|
||||
|
||||
@@ -6429,3 +6599,87 @@ msgstr ""
|
||||
|
||||
msgid "{ON | delay | OFF}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{mode} -- created by {creator} on {created}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{mode} {param} -- created by {creator} on {created}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {channel}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {channel} (key: {key})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {channel} = {access}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {channel} = {access} ({description})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} ({description})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} -- added by {creator} on {created}; last used: {last_used}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} -- added by {creator} on {created}; last used: {last_used} ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} -- created by {creator} on {created}; {expires} ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} -- {limit} sessions ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} -- {limit} sessions; created by {creator} on {created}; {expires} ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} = {flags} -- added by {creator} at {created}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} = {flags} -- added by {creator} at {created} ({description})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} = {level}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} = {level} ({description})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} = {level} -- created by {creator}; last seen {last_seen}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {mask} = {level} -- created by {creator}; last seen {last_seen} ({description})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {nick} = {vhost} -- created by {creator} at {created}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {word} -- type: {type}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: [{id}] {mask} -- created by {creator} on {created}; {expires} ({reason})"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: sent by {sender} at {date/time}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {command} on {service}: {method}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {message}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {message} -- created by {creator} at {created}"
|
||||
msgstr ""
|
||||
|
||||
msgid "{number}: {text} -- created by {creator} on {created}"
|
||||
msgstr ""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1906
-3639
File diff suppressed because it is too large
Load Diff
+9
-35
@@ -36,7 +36,7 @@ macro(build_modules SRC)
|
||||
if(NOT ${SRC} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR} AND EXISTS "${SRC}/CMakeLists.txt")
|
||||
add_subdirectory("${SRC}")
|
||||
else()
|
||||
file(GLOB MODULES_SRCS "${SRC}/*")
|
||||
file(GLOB MODULES_SRCS CONFIGURE_DEPENDS "${SRC}/*")
|
||||
foreach(MODULE_SRC ${MODULES_SRCS})
|
||||
if(IS_DIRECTORY "${MODULE_SRC}")
|
||||
build_modules("${MODULE_SRC}")
|
||||
@@ -52,12 +52,6 @@ macro(build_modules SRC)
|
||||
file(RELATIVE_PATH FNAME ${SRC} ${MODULE_SRC})
|
||||
# Convert the real source file extension to have a library extension
|
||||
string(REGEX REPLACE "\\.cpp$" "${CMAKE_SHARED_LIBRARY_SUFFIX}" SO ${FNAME})
|
||||
# Reset linker flags
|
||||
set(TEMP_LDFLAGS)
|
||||
# Reset extra dependencies
|
||||
set(TEMP_DEPENDENCIES)
|
||||
# Calculate the library dependencies for the given source file
|
||||
calculate_libraries(${MODULE_SRC} TEMP_LDFLAGS TEMP_DEPENDENCIES)
|
||||
# For Visual Studio only, include win32_memory static library, required to override Visual Studio's overrides of the new/delete operators
|
||||
if(MSVC)
|
||||
set(WIN32_MEMORY win32_memory)
|
||||
@@ -66,6 +60,8 @@ macro(build_modules SRC)
|
||||
endif()
|
||||
# Generate the module and set its linker flags, also set it to depend on the main Anope executable to be built beforehand
|
||||
add_library(${SO} MODULE ${MODULE_SRC})
|
||||
# Execute inline CMake code for the module
|
||||
inline_cmake(${SO} ${MODULE_SRC})
|
||||
# Windows requires this because it's weird
|
||||
if(WIN32)
|
||||
set(WIN32_NO_LIBS "/nodefaultlib:\"libcmt.lib\" /OPT:NOREF")
|
||||
@@ -77,7 +73,7 @@ macro(build_modules SRC)
|
||||
FOLDER "Modules"
|
||||
INSTALL_RPATH_USE_LINK_PATH ON
|
||||
LINKER_LANGUAGE CXX
|
||||
LINK_FLAGS "${TEMP_LDFLAGS} ${WIN32_NO_LIBS}"
|
||||
LINK_FLAGS "${WIN32_NO_LIBS}"
|
||||
PREFIX ""
|
||||
SUFFIX ""
|
||||
)
|
||||
@@ -85,13 +81,12 @@ macro(build_modules SRC)
|
||||
if(HAVE_LOCALIZATION)
|
||||
add_dependencies(${SO} module_language)
|
||||
endif()
|
||||
target_link_libraries(${SO} ${TEMP_DEPENDENCIES})
|
||||
# For Windows only, have the module link to the export library of Anope as well as wsock32 and Ws2_32 libraries (most of the modules probably don't need this, but this is to be on the safe side), also set its version
|
||||
if(WIN32)
|
||||
target_link_libraries(${SO} ${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
|
||||
target_link_libraries(${SO} PUBLIC ${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
|
||||
set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
|
||||
elseif(APPLE)
|
||||
target_link_libraries(${SO} ${PROGRAM_NAME})
|
||||
target_link_libraries(${SO} PUBLIC ${PROGRAM_NAME})
|
||||
endif()
|
||||
# Set the module to be installed to the module directory under the data directory
|
||||
install(TARGETS ${SO}
|
||||
@@ -104,7 +99,7 @@ macro(build_modules SRC)
|
||||
endmacro()
|
||||
|
||||
macro(build_subdir)
|
||||
file(GLOB_RECURSE MODULES_SUBDIR_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
|
||||
file(GLOB_RECURSE MODULES_SUBDIR_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS "*.cpp")
|
||||
list(SORT MODULES_SUBDIR_SRCS)
|
||||
|
||||
GET_FILENAME_COMPONENT(FOLDER_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
@@ -113,31 +108,11 @@ macro(build_subdir)
|
||||
# Set all the files to use C++ as well as set their compile flags (use the module-specific compile flags, though)
|
||||
set_source_files_properties(${MODULES_SUBDIR_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
|
||||
|
||||
# Iterate through the source files in the subdirectory
|
||||
foreach(SRC ${MODULES_SUBDIR_SRCS})
|
||||
# Reset linker flags
|
||||
set(TEMP_LDFLAGS)
|
||||
# Reset extra dependencies
|
||||
set(TEMP_DEPENDENCIES)
|
||||
# Calculate the library dependencies for the given source file
|
||||
calculate_libraries(${SRC} SKIP_LIBRARIES MODULE TEMP_LDFLAGS TEMP_DEPENDENCIES)
|
||||
|
||||
# Append this source file's linker flags to the subdirectoy's linker flags, if there are any to append
|
||||
if(TEMP_DEPENDENCIES)
|
||||
list(APPEND SUBDIR_EXTRA_DEPENDS ${TEMP_DEPENDENCIES})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Remove duplicates from the linker flags
|
||||
if(SUBDIR_LDFLAGS)
|
||||
list(REMOVE_DUPLICATES SUBDIR_LDFLAGS)
|
||||
endif()
|
||||
|
||||
# Remove duplicates from the extra dependencies
|
||||
if(SUBDIR_EXTRA_DEPENDS)
|
||||
list(REMOVE_DUPLICATES SUBDIR_EXTRA_DEPENDS)
|
||||
endif()
|
||||
|
||||
# For Visual Studio only, include win32_memory static library, required to override Visual Studio's overrides of the new/delete operators
|
||||
if(MSVC)
|
||||
set(WIN32_MEMORY win32_memory)
|
||||
@@ -160,13 +135,12 @@ macro(build_subdir)
|
||||
if(HAVE_LOCALIZATION)
|
||||
add_dependencies(${SO} module_language)
|
||||
endif()
|
||||
target_link_libraries(${SO} ${SUBDIR_EXTRA_DEPENDS})
|
||||
# For Windows only, have the module link to the export library of Anope as well as wsock32 and Ws2_32 libraries (most of the modules probably don't need this, but this is to be on the safe side), also set it's version
|
||||
if(WIN32)
|
||||
target_link_libraries(${SO} ${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
|
||||
target_link_libraries(${SO} PUBLIC ${PROGRAM_NAME} PUBLIC wsock32 Ws2_32 ${WIN32_MEMORY})
|
||||
set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
|
||||
elseif(APPLE)
|
||||
target_link_libraries(${SO} ${PROGRAM_NAME})
|
||||
target_link_libraries(${SO} PUBLIC ${PROGRAM_NAME})
|
||||
endif()
|
||||
|
||||
# Set the module to be installed to the module directory under the data directory
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName("OP");
|
||||
char symbol = cm ? anope_dynamic_static_cast<ChannelModeStatus *>(cm)->symbol : 0;
|
||||
const auto message = Anope::printf("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
|
||||
const auto message = Anope::Format("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
|
||||
IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, message);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,11 +246,12 @@ private:
|
||||
{
|
||||
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "LIST";
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
BadWords *bw = ci->GetExt<BadWords>("badwords");
|
||||
|
||||
list.AddColumn(_("Number")).AddColumn(_("Word")).AddColumn(_("Type"));
|
||||
list.SetFlexible(_("{number}: \002{word}\002 -- type: {type}"));
|
||||
|
||||
BadWords *bw = ci->GetExt<BadWords>("badwords");
|
||||
if (!bw || !bw->GetBadWordCount())
|
||||
{
|
||||
source.Reply(_("%s bad words list is empty."), ci->name.c_str());
|
||||
@@ -305,14 +306,8 @@ private:
|
||||
source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Bad words list for %s:"), ci->name.c_str());
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of bad words list."));
|
||||
}
|
||||
}
|
||||
@@ -486,7 +481,8 @@ public:
|
||||
"that starts with \037word\037. If END is specified, a kick "
|
||||
"will be done if a user says a word that ends with "
|
||||
"\037word\037. If you don't specify anything, a kick will "
|
||||
"be issued every time \037word\037 is said by a user."
|
||||
"be issued every time \037word\037 is said by a user. This "
|
||||
"will be shown in the \002LIST\002 output as ANY."
|
||||
"\n\n"
|
||||
"The \002DEL\002 command removes the given word from the "
|
||||
"bad words list. If a list of entry numbers is given, those "
|
||||
|
||||
@@ -88,7 +88,6 @@ private:
|
||||
source.Reply(_("%s!%s@%s (%s) added to the bot list."), bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str());
|
||||
|
||||
FOREACH_MOD(OnBotCreate, (bi));
|
||||
return;
|
||||
}
|
||||
|
||||
void DoChange(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
@@ -227,7 +226,6 @@ private:
|
||||
Log(LOG_ADMIN, source, this) << "CHANGE " << oldnick << " to " << bi->GetMask() << " " << bi->realname;
|
||||
|
||||
FOREACH_MOD(OnBotChange, (bi));
|
||||
return;
|
||||
}
|
||||
|
||||
void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
@@ -259,7 +257,6 @@ private:
|
||||
|
||||
source.Reply(_("Bot \002%s\002 has been deleted."), nick.c_str());
|
||||
delete bi;
|
||||
return;
|
||||
}
|
||||
public:
|
||||
CommandBSBot(Module *creator) : Command(creator, "botserv/bot", 1, 6)
|
||||
@@ -339,8 +336,6 @@ public:
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -41,11 +41,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
unsigned count = 0;
|
||||
ListFormatter list(source.GetAccount());
|
||||
|
||||
list.AddColumn(_("Nick")).AddColumn(_("Mask")).AddColumn(_("Real name"));
|
||||
list.SetFlexible(_("\002{nick}\002 ({mask}) [{real_name}]"));
|
||||
|
||||
unsigned count = 0;
|
||||
for (const auto &[_, bi] : *BotListByNick)
|
||||
{
|
||||
if (is_admin || !bi->oper_only)
|
||||
@@ -66,9 +66,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
if (!count)
|
||||
{
|
||||
source.Reply(_(
|
||||
@@ -79,10 +76,7 @@ public:
|
||||
else
|
||||
{
|
||||
source.Reply(_("Bot list:"));
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("%d bots available."), count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,15 +55,10 @@ public:
|
||||
info[_("Real name")] = bi->realname;
|
||||
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
|
||||
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
|
||||
info[_("Used on")] = Anope::printf(Language::Translate(source.nc, bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
info[_("Used on")] = Anope::Format(Language::Translate(source.nc, bi->GetChannelCount(), N_("%u channel", "%u channels")), bi->GetChannelCount());
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
info.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
info.SendTo(source);
|
||||
|
||||
if (source.HasPriv("botserv/administration"))
|
||||
{
|
||||
@@ -89,12 +84,7 @@ public:
|
||||
Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
|
||||
|
||||
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
info.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
info.SendTo(source);
|
||||
}
|
||||
else
|
||||
source.Reply(_("\002%s\002 is not a valid bot or registered channel."), query.c_str());
|
||||
@@ -116,7 +106,7 @@ public:
|
||||
|
||||
const Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+18
-22
@@ -1112,18 +1112,14 @@ class BSKick final
|
||||
|
||||
static void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) ATTR_FORMAT(3, 4)
|
||||
{
|
||||
va_list args;
|
||||
char buf[1024];
|
||||
|
||||
if (!ci || !ci->bi || !ci->c || !u || u->IsProtected() || !ci->c->FindUser(u))
|
||||
return;
|
||||
|
||||
Anope::string fmt = Language::Translate(u, message);
|
||||
va_start(args, message);
|
||||
vsnprintf(buf, sizeof(buf), fmt.c_str(), args);
|
||||
va_end(args);
|
||||
const auto *fmt = Language::Translate(u, message);
|
||||
|
||||
ci->c->Kick(ci->bi, u, Anope::string(buf));
|
||||
Anope::string buf;
|
||||
ANOPE_FORMAT(message, fmt, buf);
|
||||
ci->c->Kick(ci->bi, u, buf);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1157,7 +1153,7 @@ public:
|
||||
if (kd && kd->badwords)
|
||||
{
|
||||
if (kd->ttb[TTB_BADWORDS])
|
||||
info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]);
|
||||
info[_("Bad words kicker")] = Anope::Format("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]);
|
||||
else
|
||||
info[_("Bad words kicker")] = enabled;
|
||||
}
|
||||
@@ -1167,7 +1163,7 @@ public:
|
||||
if (kd && kd->bolds)
|
||||
{
|
||||
if (kd->ttb[TTB_BOLDS])
|
||||
info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]);
|
||||
info[_("Bolds kicker")] = Anope::Format("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]);
|
||||
else
|
||||
info[_("Bolds kicker")] = enabled;
|
||||
}
|
||||
@@ -1177,9 +1173,9 @@ public:
|
||||
if (kd && kd->caps)
|
||||
{
|
||||
if (kd->ttb[TTB_CAPS])
|
||||
info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent);
|
||||
info[_("Caps kicker")] = Anope::Format(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent);
|
||||
else
|
||||
info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent);
|
||||
info[_("Caps kicker")] = Anope::Format(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent);
|
||||
}
|
||||
else
|
||||
info[_("Caps kicker")] = disabled;
|
||||
@@ -1187,7 +1183,7 @@ public:
|
||||
if (kd && kd->colors)
|
||||
{
|
||||
if (kd->ttb[TTB_COLORS])
|
||||
info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]);
|
||||
info[_("Colors kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]);
|
||||
else
|
||||
info[_("Colors kicker")] = enabled;
|
||||
}
|
||||
@@ -1197,9 +1193,9 @@ public:
|
||||
if (kd && kd->flood)
|
||||
{
|
||||
if (kd->ttb[TTB_FLOOD])
|
||||
info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs);
|
||||
info[_("Flood kicker")] = Anope::Format(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs);
|
||||
else
|
||||
info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs);
|
||||
info[_("Flood kicker")] = Anope::Format(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs);
|
||||
}
|
||||
else
|
||||
info[_("Flood kicker")] = disabled;
|
||||
@@ -1207,9 +1203,9 @@ public:
|
||||
if (kd && kd->repeat)
|
||||
{
|
||||
if (kd->ttb[TTB_REPEAT])
|
||||
info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes);
|
||||
info[_("Repeat kicker")] = Anope::Format(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes);
|
||||
else
|
||||
info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), kd->repeattimes);
|
||||
info[_("Repeat kicker")] = Anope::Format(_("%s (%d times)"), enabled.c_str(), kd->repeattimes);
|
||||
}
|
||||
else
|
||||
info[_("Repeat kicker")] = disabled;
|
||||
@@ -1217,7 +1213,7 @@ public:
|
||||
if (kd && kd->reverses)
|
||||
{
|
||||
if (kd->ttb[TTB_REVERSES])
|
||||
info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]);
|
||||
info[_("Reverses kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]);
|
||||
else
|
||||
info[_("Reverses kicker")] = enabled;
|
||||
}
|
||||
@@ -1227,7 +1223,7 @@ public:
|
||||
if (kd && kd->underlines)
|
||||
{
|
||||
if (kd->ttb[TTB_UNDERLINES])
|
||||
info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]);
|
||||
info[_("Underlines kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]);
|
||||
else
|
||||
info[_("Underlines kicker")] = enabled;
|
||||
}
|
||||
@@ -1237,7 +1233,7 @@ public:
|
||||
if (kd && kd->italics)
|
||||
{
|
||||
if (kd->ttb[TTB_ITALICS])
|
||||
info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]);
|
||||
info[_("Italics kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]);
|
||||
else
|
||||
info[_("Italics kicker")] = enabled;
|
||||
}
|
||||
@@ -1247,7 +1243,7 @@ public:
|
||||
if (kd && kd->amsgs)
|
||||
{
|
||||
if (kd->ttb[TTB_AMSGS])
|
||||
info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]);
|
||||
info[_("AMSG kicker")] = Anope::Format(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]);
|
||||
else
|
||||
info[_("AMSG kicker")] = enabled;
|
||||
}
|
||||
@@ -1369,7 +1365,7 @@ public:
|
||||
BadWords *badwords = ci->GetExt<BadWords>("badwords");
|
||||
|
||||
/* Normalize the buffer */
|
||||
Anope::string nbuf = Anope::NormalizeBuffer(realbuf);
|
||||
Anope::string nbuf = Anope::RemoveFormatting(realbuf);
|
||||
bool casesensitive = Config->GetModule("botserv").Get<bool>("casesensitive");
|
||||
|
||||
/* Normalize can return an empty string if this only contains control codes etc */
|
||||
|
||||
@@ -330,7 +330,7 @@ public:
|
||||
ci->Extend<bool>(def.upper());
|
||||
}
|
||||
|
||||
EventReturn OnCanSet(User *u, const ChannelMode *cm) override
|
||||
EventReturn OnCanSet(User *u, Channel *c, const ChannelMode *cm) override
|
||||
{
|
||||
if (Config->GetModule(this).Get<const Anope::string>("nomlock").find(cm->mchar) != Anope::string::npos
|
||||
|| Config->GetModule(this).Get<const Anope::string>("require").find(cm->mchar) != Anope::string::npos)
|
||||
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
entry["Number"] = Anope::ToString(number);
|
||||
entry["Level"] = access->AccessSerialize();
|
||||
entry["Mask"] = access->Mask();
|
||||
entry["By"] = access->creator;
|
||||
entry["Creator"] = access->creator;
|
||||
entry["Last seen"] = timebuf;
|
||||
entry["Description"] = access->description;
|
||||
list.AddEntry(entry);
|
||||
@@ -382,8 +382,6 @@ private:
|
||||
|
||||
source.Reply(_("\002%s\002 not found on %s access list."), mask.c_str(), ci->name.c_str());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ProcessList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, ListFormatter &list)
|
||||
@@ -435,18 +433,10 @@ private:
|
||||
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Access list for %s:"), ci->name.c_str());
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of access list"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
@@ -459,6 +449,13 @@ private:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002 = {level}")
|
||||
: _("{number}: \002{mask}\002 = {level} ({description})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -471,7 +468,14 @@ private:
|
||||
}
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Last seen")).AddColumn(_("Description"));
|
||||
list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Last seen")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002 = {level} -- created by {creator}; last seen {last_seen}")
|
||||
: _("{number}: \002{mask}\002 = {level} -- created by {creator}; last seen {last_seen} ({description})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -490,8 +494,6 @@ private:
|
||||
bool override = !source.IsFounder(ci);
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the access list";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -559,8 +561,6 @@ public:
|
||||
this->DoClear(source, ci);
|
||||
else
|
||||
this->OnSyntaxError(source, "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
@@ -724,6 +724,7 @@ class CommandCSLevels final
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Name")).AddColumn(_("Level"));
|
||||
list.SetFlexible(_("\002{name}\002 = {level}"));
|
||||
|
||||
const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
|
||||
|
||||
@@ -744,11 +745,7 @@ class CommandCSLevels final
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
|
||||
void DoReset(CommandSource &source, ChannelInfo *ci)
|
||||
@@ -760,7 +757,6 @@ class CommandCSLevels final
|
||||
FOREACH_MOD(OnLevelChange, (source, ci, "ALL", 0));
|
||||
|
||||
source.Reply(_("Access levels for \002%s\002 reset to defaults."), ci->name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -813,8 +809,6 @@ public:
|
||||
this->DoReset(source, ci);
|
||||
else
|
||||
this->OnSyntaxError(source, "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
@@ -825,6 +819,7 @@ public:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Name")).AddColumn(_("Description"));
|
||||
list.SetFlexible(_("\002{name}\002: {description}"));
|
||||
|
||||
for (const auto &p : PrivilegeManager::GetPrivileges())
|
||||
{
|
||||
@@ -834,11 +829,7 @@ public:
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -141,7 +141,7 @@ class CommandCSAKick final
|
||||
}
|
||||
}
|
||||
|
||||
/* Match against the lastusermask of all nickalias's with equal
|
||||
/* Match against the last mask of all nickalias's with equal
|
||||
* or higher access. - Viper */
|
||||
for (const auto &[_, na2] : *NickAliasList)
|
||||
{
|
||||
@@ -150,7 +150,7 @@ class CommandCSAKick final
|
||||
AccessGroup nc_access = ci->AccessFor(na->nc), u_access = source.AccessFor(ci);
|
||||
if (na->nc && (na->nc == ci->GetFounder() || nc_access >= u_access))
|
||||
{
|
||||
Anope::string buf = na->nick + "!" + na->last_usermask;
|
||||
Anope::string buf = na->nick + "!" + na->last_userhost;
|
||||
if (Anope::Match(buf, mask))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
@@ -378,14 +378,8 @@ class CommandCSAKick final
|
||||
source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Autokick list for %s:"), ci->name.c_str());
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of autokick list"));
|
||||
}
|
||||
}
|
||||
@@ -400,6 +394,13 @@ class CommandCSAKick final
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Reason"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Reason"].empty()
|
||||
? _("{number}: \002{mask}\002")
|
||||
: _("{number}: \002{mask}\002 ({reason})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -413,6 +414,13 @@ class CommandCSAKick final
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Last used")).AddColumn(_("Reason"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Reason"].empty()
|
||||
? _("{number}: \002{mask}\002 -- added by {creator} on {created}; last used: {last_used}")
|
||||
: _("{number}: \002{mask}\002 -- added by {creator} on {created}; last used: {last_used} ({reason})");
|
||||
});
|
||||
|
||||
this->ProcessList(source, ci, params, list);
|
||||
}
|
||||
|
||||
@@ -491,8 +499,6 @@ public:
|
||||
this->DoClear(source, ci);
|
||||
else
|
||||
this->OnSyntaxError(source, "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
@@ -506,7 +512,7 @@ public:
|
||||
"%s will ban that user from the channel, then kick "
|
||||
"the user."
|
||||
"\n\n"
|
||||
"The \002%s\032ADD\002 command adds the given nick or usermask "
|
||||
"The \002%s\032ADD\002 command adds the given nick or mask "
|
||||
"to the AutoKick list. If a \037reason\037 is given with "
|
||||
"the command, that reason will be used when the user is "
|
||||
"kicked; if not, the default reason is \"User has been "
|
||||
|
||||
@@ -128,6 +128,8 @@ private:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Message"));
|
||||
list.SetFlexible(_("{number}: {message} -- created by {creator} at {created}"));
|
||||
|
||||
for (unsigned i = 0; i < (*messages)->size(); ++i)
|
||||
{
|
||||
EntryMsg *msg = (*messages)->at(i);
|
||||
@@ -140,11 +142,7 @@ private:
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of entry message list."));
|
||||
}
|
||||
|
||||
@@ -298,12 +296,21 @@ public:
|
||||
if (!messages)
|
||||
return;
|
||||
|
||||
const auto timestamp = Config->GetModule(this).Get<bool>("timestamp", "yes");
|
||||
for (const auto &message : *(*messages))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (u->ShouldPrivmsg())
|
||||
IRCD->SendContextPrivmsg(c->ci->WhoSends(), u, c, message->message);
|
||||
IRCD->SendContextPrivmsg(c->ci->WhoSends(), u, c, message->message, tags);
|
||||
else
|
||||
IRCD->SendContextNotice(c->ci->WhoSends(), u, c, message->message);
|
||||
IRCD->SendContextNotice(c->ci->WhoSends(), u, c, message->message, tags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,8 +309,13 @@ class CommandCSFlags final
|
||||
}
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Flags")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002 = {flags} -- added by {creator} at {created}")
|
||||
: _("{number}: \002{mask}\002 = {flags} -- added by {creator} at {created} ({description})");
|
||||
});
|
||||
|
||||
unsigned count = 0;
|
||||
for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i)
|
||||
@@ -348,12 +353,8 @@ class CommandCSFlags final
|
||||
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Flags list for %s"), ci->name.c_str());
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
if (count == ci->GetAccessCount())
|
||||
source.Reply(_("End of access list."));
|
||||
else
|
||||
@@ -376,8 +377,6 @@ class CommandCSFlags final
|
||||
bool override = !source.IsFounder(ci);
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the access list";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -62,12 +62,7 @@ public:
|
||||
}
|
||||
|
||||
FOREACH_MOD(OnChanInfo, (source, ci, info, show_all));
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
info.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
info.SendTo(source);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -76,6 +76,12 @@ public:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Name")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("\002{name}\002")
|
||||
: _("\002{name}\002 ({description})");
|
||||
});
|
||||
|
||||
Anope::map<ChannelInfo *> ordered_map;
|
||||
for (const auto &[cname, ci] : *RegisteredChannelList)
|
||||
@@ -122,12 +128,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of list - %d/%d matches shown."), nchans > listmax ? listmax : nchans, nchans);
|
||||
}
|
||||
|
||||
@@ -228,8 +229,6 @@ public:
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "PRIVATE");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
|
||||
@@ -138,7 +138,8 @@ public:
|
||||
else
|
||||
{
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Service")).AddColumn(_("Command")).AddColumn(_("Method")).AddColumn("");
|
||||
list.AddColumn(_("Number")).AddColumn(_("Service")).AddColumn(_("Command")).AddColumn(_("Method"));
|
||||
list.SetFlexible(_("{number}: {command} on {service}: {method}"));
|
||||
|
||||
for (unsigned i = 0; i < (*ls)->size(); ++i)
|
||||
{
|
||||
@@ -147,19 +148,13 @@ public:
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Number"] = Anope::ToString(i + 1);
|
||||
entry["Service"] = log->command_service;
|
||||
entry["Command"] = !log->command_name.empty() ? log->command_name : log->service_name;
|
||||
entry["Method"] = log->method;
|
||||
entry[""] = log->extra;
|
||||
entry["Command"] = !log->command_name.empty() ? log->command_name.upper() : log->service_name;
|
||||
entry["Method"] = log->method + (log->extra.empty() ? "" : " ") + log->extra;
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
source.Reply(_("Log list for %s:"), ci->name.c_str());
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
else if (params.size() > 2)
|
||||
|
||||
@@ -288,7 +288,7 @@ class CommandCSMode final
|
||||
for (auto *ml : mlocks)
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
|
||||
if (cm && cm->CanSet(source.GetUser()))
|
||||
if (cm && cm->CanSet(source.GetUser(), ci->c))
|
||||
modelocks->RemoveMLock(cm, ml->set, ml->param);
|
||||
}
|
||||
}
|
||||
@@ -320,7 +320,7 @@ class CommandCSMode final
|
||||
source.Reply(_("Unknown mode character %c ignored."), mode);
|
||||
break;
|
||||
}
|
||||
else if (u && !cm->CanSet(u))
|
||||
else if (u && !cm->CanSet(u, ci->c))
|
||||
{
|
||||
source.Reply(_("You may not (un)lock mode %c."), mode);
|
||||
break;
|
||||
@@ -412,7 +412,7 @@ class CommandCSMode final
|
||||
source.Reply(_("Unknown mode character %c ignored."), mode);
|
||||
break;
|
||||
}
|
||||
else if (u && !cm->CanSet(u))
|
||||
else if (u && !cm->CanSet(u, ci->c))
|
||||
{
|
||||
source.Reply(_("You may not (un)lock mode %c."), mode);
|
||||
break;
|
||||
@@ -450,6 +450,12 @@ class CommandCSMode final
|
||||
{
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Mode")).AddColumn(_("Param")).AddColumn(_("Creator")).AddColumn(_("Created"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Param"].empty()
|
||||
? _("{mode} -- created by {creator} on {created}")
|
||||
: _("{mode} {param} -- created by {creator} on {created}");
|
||||
});
|
||||
|
||||
for (auto *ml : mlocks)
|
||||
{
|
||||
@@ -458,7 +464,7 @@ class CommandCSMode final
|
||||
continue;
|
||||
|
||||
ListFormatter::ListEntry entry;
|
||||
entry["Mode"] = Anope::printf("%c%c", ml->set ? '+' : '-', cm->mchar);
|
||||
entry["Mode"] = Anope::Format("%c%c", ml->set ? '+' : '-', cm->mchar);
|
||||
entry["Param"] = ml->param;
|
||||
entry["Creator"] = ml->setter;
|
||||
entry["Created"] = Anope::strftime(ml->created, NULL, true);
|
||||
@@ -466,12 +472,7 @@ class CommandCSMode final
|
||||
}
|
||||
|
||||
source.Reply(_("Mode locks for %s:"), ci->name.c_str());
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -508,7 +509,7 @@ class CommandCSMode final
|
||||
{
|
||||
ChannelMode *cm = ModeManager::GetChannelModes()[j];
|
||||
|
||||
if (!u || cm->CanSet(u) || can_override)
|
||||
if (!u || cm->CanSet(u, ci->c) || can_override)
|
||||
{
|
||||
if (cm->type == MODE_REGULAR || (!adding && cm->type == MODE_PARAM))
|
||||
{
|
||||
@@ -524,7 +525,7 @@ class CommandCSMode final
|
||||
if (adding == -1)
|
||||
break;
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByChar(mode);
|
||||
if (!cm || (u && !cm->CanSet(u) && !can_override))
|
||||
if (!cm || (u && !cm->CanSet(u, ci->c) && !can_override))
|
||||
continue;
|
||||
switch (cm->type)
|
||||
{
|
||||
@@ -917,9 +918,9 @@ public:
|
||||
if (!m.second.empty())
|
||||
{
|
||||
if (m.first)
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str());
|
||||
else
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str());
|
||||
}
|
||||
else
|
||||
return "";
|
||||
|
||||
@@ -282,7 +282,7 @@ public:
|
||||
if (u2)
|
||||
onlinestatus = ".";
|
||||
else
|
||||
onlinestatus = Anope::printf(Language::Translate(source.nc, _(" but %s mysteriously dematerialized.")), target.c_str());
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(" but %s mysteriously dematerialized.")), target.c_str());
|
||||
|
||||
Anope::string timebuf = Anope::Duration(Anope::CurTime - info->last, source.nc);
|
||||
Anope::string timebuf2 = Anope::strftime(info->last, source.nc, true);
|
||||
@@ -296,9 +296,9 @@ public:
|
||||
{
|
||||
u2 = User::Find(info->nick2, true);
|
||||
if (u2)
|
||||
onlinestatus = Anope::printf(Language::Translate(source.nc, _(". %s is still online.")), u2->nick.c_str());
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(". %s is still online.")), u2->nick.c_str());
|
||||
else
|
||||
onlinestatus = Anope::printf(Language::Translate(source.nc, _(", but %s mysteriously dematerialized.")), info->nick2.c_str());
|
||||
onlinestatus = Anope::Format(Language::Translate(source.nc, _(", but %s mysteriously dematerialized.")), info->nick2.c_str());
|
||||
|
||||
source.Reply(_("%s (%s) was last seen changing nick to %s %s ago%s"),
|
||||
target.c_str(), info->vhost.c_str(), info->nick2.c_str(), timebuf.c_str(), onlinestatus.c_str());
|
||||
|
||||
@@ -253,8 +253,6 @@ public:
|
||||
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to unset the description";
|
||||
source.Reply(_("Description of %s unset."), ci->name.c_str());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
@@ -331,8 +329,6 @@ public:
|
||||
ci->SetFounder(nc);
|
||||
|
||||
source.Reply(_("Founder of \002%s\002 changed to \002%s\002."), ci->name.c_str(), na->nick.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
@@ -465,8 +461,6 @@ public:
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "PEACE");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
@@ -1004,8 +998,6 @@ public:
|
||||
source.Reply(_("Successor for \002%s\002 changed to \002%s\002."), ci->name.c_str(), nc->display.c_str());
|
||||
else
|
||||
source.Reply(_("Successor for \002%s\002 unset."), ci->name.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
@@ -1084,8 +1076,6 @@ public:
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "NOEXPIRE");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &) override
|
||||
@@ -1333,7 +1323,7 @@ public:
|
||||
if (persist.HasExt(ci))
|
||||
info.AddOption(_("Persistent"));
|
||||
if (noexpire.HasExt(ci))
|
||||
info.AddOption(_("No expire"));
|
||||
info.AddOption(_("No expiry"));
|
||||
if (keep_modes.HasExt(ci))
|
||||
info.AddOption(_("Keep modes"));
|
||||
if (noautoop.HasExt(ci))
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
static Module *me;
|
||||
|
||||
static Anope::map<Anope::string> descriptions;
|
||||
static Anope::map<uint16_t> numerics;
|
||||
static Anope::map<unsigned> numerics;
|
||||
|
||||
struct CSMiscData;
|
||||
static Anope::map<ExtensibleItem<CSMiscData> *> items;
|
||||
|
||||
@@ -195,8 +195,6 @@ public:
|
||||
source.Reply(_("Channel \002%s\002 is now released."), ci->name.c_str());
|
||||
|
||||
FOREACH_MOD(OnChanUnsuspend, (ci));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -397,6 +397,12 @@ private:
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{mask}\002")
|
||||
: _("{number}: \002{mask}\002 ({description})");
|
||||
});
|
||||
|
||||
if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos)
|
||||
{
|
||||
@@ -453,12 +459,8 @@ private:
|
||||
source.Reply(_("No matching entries on %s access list."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("%s list for %s"), source.command.nobreak().c_str(), ci->name.c_str());
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,7 +513,7 @@ public:
|
||||
|
||||
const Anope::string GetDesc(CommandSource &source) const override
|
||||
{
|
||||
return Anope::printf(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.nobreak().c_str());
|
||||
return Anope::Format(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.nobreak().c_str());
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
|
||||
@@ -134,9 +134,9 @@ struct UserData final
|
||||
Anope::string info_adder;
|
||||
Anope::string info_message;
|
||||
time_t info_ts = 0;
|
||||
Anope::string last_mask;
|
||||
Anope::string last_quit;
|
||||
Anope::string last_real_mask;
|
||||
Anope::string last_userhost;
|
||||
Anope::string last_userhost_real;
|
||||
bool noexpire = false;
|
||||
bool protect = false;
|
||||
std::optional<time_t> protectafter;
|
||||
@@ -432,7 +432,7 @@ private:
|
||||
// crypt3-md5 Converted to enc_posix
|
||||
// crypt3-sha2-256 Converted to enc_posix
|
||||
// crypt3-sha2-512 Converted to enc_posix
|
||||
// ircservices Converted to enc_old
|
||||
// ircservices NO
|
||||
// pbkdf2 NO
|
||||
// pbkdf2v2 NO
|
||||
// rawmd5 Converted to enc_md5
|
||||
@@ -443,10 +443,9 @@ private:
|
||||
if (pass.compare(0, 18, "$anope$enc_sha256$", 18) == 0)
|
||||
{
|
||||
auto sep = pass.find('$', 18);
|
||||
Anope::string iv, pass;
|
||||
Anope::B64Decode(pass.substr(18, sep - 18), iv);
|
||||
Anope::B64Decode(pass.substr(sep + 1), pass);
|
||||
nc->pass = "sha256:" + Anope::Hex(pass) + ":" + Anope::Hex(iv);
|
||||
auto iv = Anope::B64Decode(pass.substr(18, sep - 18));
|
||||
auto pw = Anope::B64Decode(pass.substr(sep + 1));
|
||||
nc->pass = "sha256:" + Anope::Hex(pw) + ":" + Anope::Hex(iv);
|
||||
}
|
||||
|
||||
else if (pass.compare(0, 9, "$argon2d$", 9) == 0)
|
||||
@@ -460,14 +459,10 @@ private:
|
||||
|
||||
else if (pass.compare(0, 8, "$base64$", 8) == 0)
|
||||
{
|
||||
Anope::string rawpass;
|
||||
Anope::B64Decode(pass.substr(8), rawpass);
|
||||
auto rawpass = Anope::B64Decode(pass.substr(8));
|
||||
Anope::Encrypt(rawpass, nc->pass);
|
||||
}
|
||||
|
||||
else if (pass.compare(0, 13, "$ircservices$", 13) == 0)
|
||||
nc->pass = "oldmd5:" + pass.substr(13);
|
||||
|
||||
else if (pass.compare(0, 8, "$rawmd5$", 8) == 0)
|
||||
nc->pass = "md5:" + pass.substr(8);
|
||||
|
||||
@@ -806,7 +801,7 @@ private:
|
||||
|
||||
auto *ni = news_service->CreateNewsItem();
|
||||
ni->type = NEWS_LOGON;
|
||||
ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->text = Anope::Format("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->who = setter;
|
||||
ni->time = ts;
|
||||
news_service->AddNewsItem(ni);
|
||||
@@ -832,7 +827,7 @@ private:
|
||||
|
||||
auto *ni = news_service->CreateNewsItem();
|
||||
ni->type = NEWS_OPER;
|
||||
ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->text = Anope::Format("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->who = setter;
|
||||
ni->time = ts;
|
||||
news_service->AddNewsItem(ni);
|
||||
@@ -1146,9 +1141,9 @@ private:
|
||||
else if (key == "private:freeze:timestamp")
|
||||
data->suspend_ts = Anope::Convert<time_t>(value, 0);
|
||||
else if (key == "private:host:actual")
|
||||
data->last_real_mask = value;
|
||||
data->last_userhost_real = value;
|
||||
else if (key == "private:host:vhost")
|
||||
data->last_mask = value;
|
||||
data->last_userhost = value;
|
||||
else if (key == "private:lastquit:message")
|
||||
data->last_quit = value;
|
||||
else if (key == "private:loginfail:failnum")
|
||||
@@ -1314,14 +1309,14 @@ private:
|
||||
auto *data = userdata.Get(nc);
|
||||
if (data)
|
||||
{
|
||||
if (!data->last_mask.empty())
|
||||
na->last_usermask = data->last_mask;
|
||||
if (!data->last_userhost.empty())
|
||||
na->last_userhost = data->last_userhost;
|
||||
|
||||
if (!data->last_quit.empty())
|
||||
na->last_quit = data->last_quit;
|
||||
|
||||
if (!data->last_real_mask.empty())
|
||||
na->last_realhost = data->last_real_mask;
|
||||
if (!data->last_userhost_real.empty())
|
||||
na->last_userhost_real = data->last_userhost_real;
|
||||
|
||||
if (data->noexpire)
|
||||
na->Extend<bool>("NS_NO_EXPIRE");
|
||||
|
||||
@@ -11,31 +11,6 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
class SaveData final
|
||||
: public Serialize::Data
|
||||
{
|
||||
public:
|
||||
Anope::string last;
|
||||
std::fstream *fs = nullptr;
|
||||
|
||||
std::iostream &operator[](const Anope::string &key) override
|
||||
{
|
||||
if (key != last)
|
||||
{
|
||||
*fs << "\nDATA " << key << " ";
|
||||
last = key;
|
||||
}
|
||||
|
||||
return *fs;
|
||||
}
|
||||
};
|
||||
|
||||
class LoadData final
|
||||
: public Serialize::Data
|
||||
{
|
||||
@@ -97,133 +72,14 @@ public:
|
||||
|
||||
class DBFlatFile final
|
||||
: public Module
|
||||
, public Pipe
|
||||
{
|
||||
/* Day the last backup was on */
|
||||
int last_day = 0;
|
||||
private:
|
||||
bool loaded = false;
|
||||
|
||||
int child_pid = -1;
|
||||
|
||||
void BackupDatabase()
|
||||
{
|
||||
tm *tm = localtime(&Anope::CurTime);
|
||||
|
||||
if (tm->tm_mday != last_day)
|
||||
{
|
||||
last_day = tm->tm_mday;
|
||||
|
||||
std::set<Anope::string> dbs;
|
||||
dbs.insert(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
for (const auto &type_order : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
Serialize::Type *stype = Serialize::Type::Find(type_order);
|
||||
|
||||
if (stype && stype->GetOwner())
|
||||
dbs.insert("module_" + stype->GetOwner()->name + ".db");
|
||||
}
|
||||
|
||||
const auto backupdir = Anope::ExpandData("backups");
|
||||
for (const auto &db : dbs)
|
||||
{
|
||||
const auto oldname = Anope::ExpandData(db);
|
||||
const auto basename = Anope::Expand(backupdir, db + "-");
|
||||
const auto newname = Anope::printf("%s%04i-%02i-%02i", basename.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
|
||||
/* Backup already exists or no database to backup */
|
||||
if (Anope::IsFile(newname) || !Anope::IsFile(oldname))
|
||||
continue;
|
||||
|
||||
Log(LOG_DEBUG) << "db_flatfile: Attempting to rename " << db << " to " << newname;
|
||||
if (rename(oldname.c_str(), newname.c_str()))
|
||||
{
|
||||
Anope::string err = Anope::LastError();
|
||||
Log(this) << "Unable to back up database " << db << " (" << err << ")!";
|
||||
|
||||
if (!Config->GetModule(this).Get<bool>("nobackupokay"))
|
||||
{
|
||||
Anope::Quitting = true;
|
||||
Anope::QuitReason = "Unable to back up database " + db + " (" + err + ")";
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto keepbackups = Config->GetModule(this).Get<unsigned>("keepbackups", "7");
|
||||
if (!keepbackups)
|
||||
continue;
|
||||
|
||||
std::error_code ec;
|
||||
std::set<Anope::string> old_backups;
|
||||
for (const auto &entry : std::filesystem::directory_iterator(backupdir.str(), ec))
|
||||
{
|
||||
Anope::string entryname = entry.path().string();
|
||||
if (entryname.compare(0, basename.length(), basename) != 0)
|
||||
continue;
|
||||
|
||||
old_backups.insert(entryname);
|
||||
if (old_backups.size() <= keepbackups)
|
||||
continue;
|
||||
|
||||
Log(LOG_DEBUG) << "Deleting expired backup " << *old_backups.begin();
|
||||
if (!std::filesystem::remove(old_backups.begin()->str(), ec))
|
||||
{
|
||||
Log(this) << "Failed to delete expired backup " << *old_backups.begin() << ": " << ec.message();
|
||||
continue;
|
||||
}
|
||||
old_backups.erase(old_backups.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
|
||||
DBFlatFile(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, DATABASE | DEPRECATED | VENDOR)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
void OnRestart() override
|
||||
{
|
||||
OnShutdown();
|
||||
}
|
||||
|
||||
void OnShutdown() override
|
||||
{
|
||||
if (child_pid > -1)
|
||||
{
|
||||
Log(this) << "Waiting for child to exit...";
|
||||
|
||||
int status;
|
||||
waitpid(child_pid, &status, 0);
|
||||
|
||||
Log(this) << "Done";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void OnNotify() override
|
||||
{
|
||||
char buf[512];
|
||||
int i = this->Read(buf, sizeof(buf) - 1);
|
||||
if (i <= 0)
|
||||
return;
|
||||
buf[i] = 0;
|
||||
|
||||
child_pid = -1;
|
||||
|
||||
if (!*buf)
|
||||
{
|
||||
Log(this) << "Finished saving databases";
|
||||
return;
|
||||
}
|
||||
|
||||
Log(this) << "Error saving databases: " << buf;
|
||||
|
||||
if (!Config->GetModule(this).Get<bool>("nobackupokay"))
|
||||
Anope::Quitting = true;
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase() override
|
||||
@@ -270,110 +126,6 @@ public:
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
|
||||
void OnSaveDatabase() override
|
||||
{
|
||||
if (child_pid > -1)
|
||||
{
|
||||
Log(this) << "Database save is already in progress!";
|
||||
return;
|
||||
}
|
||||
|
||||
BackupDatabase();
|
||||
|
||||
int i = -1;
|
||||
#ifndef _WIN32
|
||||
if (!Anope::Quitting && Config->GetModule(this).Get<bool>("fork"))
|
||||
{
|
||||
i = fork();
|
||||
if (i > 0)
|
||||
{
|
||||
child_pid = i;
|
||||
return;
|
||||
}
|
||||
else if (i < 0)
|
||||
Log(this) << "Unable to fork for database save";
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
std::map<Module *, std::fstream *> databases;
|
||||
|
||||
/* First open the databases of all of the registered types. This way, if we have a type with 0 objects, that database will be properly cleared */
|
||||
for (const auto &[_, s_type] : Serialize::Type::GetTypes())
|
||||
{
|
||||
if (databases[s_type->GetOwner()])
|
||||
continue;
|
||||
|
||||
Anope::string db_name;
|
||||
if (s_type->GetOwner())
|
||||
db_name = Anope::ExpandData("module_" + s_type->GetOwner()->name + ".db");
|
||||
else
|
||||
db_name = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream((db_name + ".tmp").c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
|
||||
|
||||
if (!fs->is_open())
|
||||
Log(this) << "Unable to open " << db_name << " for writing";
|
||||
}
|
||||
|
||||
SaveData data;
|
||||
const std::list<Serializable *> &items = Serializable::GetItems();
|
||||
for (auto *base : items)
|
||||
{
|
||||
Serialize::Type *s_type = base->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
data.fs = databases[s_type->GetOwner()];
|
||||
if (!data.fs || !data.fs->is_open())
|
||||
continue;
|
||||
|
||||
*data.fs << "OBJECT " << s_type->GetName();
|
||||
if (base->id)
|
||||
*data.fs << "\nID " << base->id;
|
||||
s_type->Serialize(base, data);
|
||||
*data.fs << "\nEND\n";
|
||||
}
|
||||
|
||||
for (auto &[mod, f] : databases)
|
||||
{
|
||||
const auto db_name = Anope::ExpandData((mod ? (mod->name + ".db") : Config->GetModule(this).Get<const Anope::string>("database", "anope.db")));
|
||||
|
||||
if (!f->is_open() || !f->good())
|
||||
{
|
||||
this->Write("Unable to write database " + db_name);
|
||||
|
||||
f->close();
|
||||
}
|
||||
else
|
||||
{
|
||||
f->close();
|
||||
#ifdef _WIN32
|
||||
/* Windows rename() fails if the file already exists. */
|
||||
remove(db_name.c_str());
|
||||
#endif
|
||||
rename((db_name + ".tmp").c_str(), db_name.c_str());
|
||||
}
|
||||
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (i)
|
||||
throw;
|
||||
}
|
||||
|
||||
if (!i)
|
||||
{
|
||||
this->Notify();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load just one type. Done if a module is reloaded during runtime */
|
||||
void OnSerializeTypeCreate(Serialize::Type *stype) override
|
||||
{
|
||||
if (!loaded)
|
||||
|
||||
@@ -190,7 +190,7 @@ private:
|
||||
return; // No backups.
|
||||
|
||||
auto backupdir = Anope::ExpandData(modconf.Get<Anope::string>("backup_directory", "backups"));
|
||||
if (!fs::is_directory(backupdir.str(), ec) && !ec)
|
||||
if (!fs::is_directory(backupdir.str(), ec))
|
||||
{
|
||||
fs::create_directories(backupdir.str(), ec);
|
||||
if (ec)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -174,9 +174,9 @@ public:
|
||||
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
|
||||
return;
|
||||
|
||||
Anope::string sql = Anope::printf("SELECT * from `%s`", GetTableName(obj).c_str());
|
||||
Anope::string sql = Anope::Format("SELECT * from `%s`", GetTableName(obj).c_str());
|
||||
if (obj->GetTimestamp())
|
||||
sql += Anope::printf(" WHERE (`timestamp` >= %s OR `timestamp` IS NULL)", this->SQL->FromUnixtime(obj->GetTimestamp()).c_str());
|
||||
sql += Anope::Format(" WHERE (`timestamp` >= %s OR `timestamp` IS NULL)", this->SQL->FromUnixtime(obj->GetTimestamp()).c_str());
|
||||
|
||||
Query query(sql);
|
||||
|
||||
|
||||
+39
-1
@@ -142,7 +142,7 @@ class Packet final
|
||||
record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3];
|
||||
pos += 4;
|
||||
|
||||
//record.rdlength = input[pos] << 8 | input[pos + 1];
|
||||
auto rdlength = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
switch (record.type)
|
||||
@@ -192,6 +192,44 @@ class Packet final
|
||||
|
||||
break;
|
||||
}
|
||||
case DNS::QUERY_TXT:
|
||||
{
|
||||
if (pos + rdlength > input_size)
|
||||
throw SocketException("Unable to unpack TXT resource record");
|
||||
|
||||
auto txtlength = input[pos++];
|
||||
if (pos + txtlength > input_size)
|
||||
throw SocketException("Unable to unpack TXT resource record");
|
||||
|
||||
record.rdata = Anope::string(reinterpret_cast<const char* >(input + pos), txtlength);
|
||||
pos += rdlength - 1;
|
||||
break;
|
||||
}
|
||||
case DNS::QUERY_SRV:
|
||||
{
|
||||
if (rdlength < 6 || pos + rdlength > input_size)
|
||||
throw SocketException("Unable to unpack SRV resource record");
|
||||
|
||||
auto srv = std::make_shared<DNS::Record::SRV>();
|
||||
|
||||
srv->priority = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
srv->weight = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
srv->port = input[pos] << 8 | input[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
srv->host = this->UnpackName(input, input_size, pos);
|
||||
if (!IsValidName(srv->host))
|
||||
throw SocketException("Invalid name in SRV resource record");
|
||||
|
||||
record.rdata = Anope::Format("%hu %hu %hu %s", srv->priority,
|
||||
srv->weight, srv->port, srv->host.c_str());
|
||||
record.rdataobj = srv;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ private:
|
||||
|
||||
public:
|
||||
EMD5(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
, md5provider(this, "md5", 16, 64)
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
|
||||
@@ -14,7 +14,7 @@ class ENone final
|
||||
{
|
||||
public:
|
||||
ENone(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
throw ModuleException("enc_none is deprecated and can not be used as a primary encryption method");
|
||||
@@ -35,9 +35,7 @@ public:
|
||||
if (!hash_method.equals_cs("plain"))
|
||||
return;
|
||||
|
||||
Anope::string b64pass;
|
||||
Anope::B64Encode(req->GetPassword(), b64pass);
|
||||
auto enc = "plain:" + b64pass;
|
||||
auto enc = "plain:" + Anope::B64Encode(req->GetPassword());
|
||||
if (nc->pass.equals_cs(enc))
|
||||
{
|
||||
// If we are NOT the first encryption module we want to re-encrypt
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/* Include file for high-level encryption routines.
|
||||
*
|
||||
* (C) 2003-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
* Based on the original code of Epona by Lara.
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/encryption.h"
|
||||
|
||||
class EOld final
|
||||
: public Module
|
||||
{
|
||||
private:
|
||||
ServiceReference<Encryption::Provider> md5;
|
||||
|
||||
Anope::string EncryptInternal(const Anope::string &src)
|
||||
{
|
||||
if (!md5)
|
||||
return {};
|
||||
|
||||
char digest[32];
|
||||
memset(digest, 0, sizeof(digest));
|
||||
|
||||
auto hash = md5->Encrypt(src);
|
||||
if (hash.length() != sizeof(digest))
|
||||
return {}; // Probably a bug?
|
||||
memcpy(digest, hash.data(), hash.length());
|
||||
|
||||
char digest2[16];
|
||||
for (size_t i = 0; i < sizeof(digest); i += 2)
|
||||
digest2[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]);
|
||||
|
||||
return Anope::Hex(digest2, sizeof(digest2));
|
||||
}
|
||||
|
||||
inline static char XTOI(char c)
|
||||
{
|
||||
return c > 9 ? c - 'A' + 10 : c - '0';
|
||||
}
|
||||
|
||||
public:
|
||||
EOld(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
, md5("Encryption::Provider", "md5")
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
throw ModuleException("enc_old is deprecated and can not be used as a primary encryption method");
|
||||
|
||||
ModuleManager::LoadModule("enc_md5", User::Find(creator, true));
|
||||
if (!md5)
|
||||
throw ModuleException("Unable to find md5 reference");
|
||||
}
|
||||
|
||||
void OnCheckAuthentication(User *, IdentifyRequest *req) override
|
||||
{
|
||||
const auto *na = NickAlias::Find(req->GetAccount());
|
||||
if (!na)
|
||||
return;
|
||||
|
||||
NickCore *nc = na->nc;
|
||||
size_t pos = nc->pass.find(':');
|
||||
if (pos == Anope::string::npos)
|
||||
return;
|
||||
|
||||
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
|
||||
if (!hash_method.equals_cs("oldmd5"))
|
||||
return;
|
||||
|
||||
auto enc = EncryptInternal(req->GetPassword());
|
||||
if (!enc.empty() && nc->pass.equals_cs(enc))
|
||||
{
|
||||
// If we are NOT the first encryption module we want to re-encrypt
|
||||
// the password with the primary encryption method.
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
|
||||
Anope::Encrypt(req->GetPassword(), nc->pass);
|
||||
req->Success(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(EOld)
|
||||
@@ -173,7 +173,7 @@ private:
|
||||
|
||||
public:
|
||||
ESHA1(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
, sha1provider(this, "sha1", 20, 64)
|
||||
{
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
|
||||
@@ -17,14 +17,6 @@ class ESHA256 final
|
||||
{
|
||||
private:
|
||||
unsigned iv[8];
|
||||
bool use_iv;
|
||||
|
||||
/* initializes the IV with a new random value */
|
||||
void NewRandomIV()
|
||||
{
|
||||
for (auto &ivsegment : iv)
|
||||
ivsegment = static_cast<uint32_t>(Anope::RandomNumber());
|
||||
}
|
||||
|
||||
/* returns the IV as base64-encrypted string */
|
||||
Anope::string GetIVString()
|
||||
@@ -50,11 +42,6 @@ private:
|
||||
|
||||
Anope::string EncryptInternal(const Anope::string &src)
|
||||
{
|
||||
if (!use_iv)
|
||||
NewRandomIV();
|
||||
else
|
||||
use_iv = false;
|
||||
|
||||
sha256_ctx ctx;
|
||||
sha256_init(&ctx);
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
@@ -69,9 +56,8 @@ private:
|
||||
|
||||
public:
|
||||
ESHA256(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, ENCRYPTION | VENDOR)
|
||||
: Module(modname, creator, DEPRECATED | ENCRYPTION | VENDOR)
|
||||
{
|
||||
use_iv = false;
|
||||
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
throw ModuleException("enc_sha256 is deprecated and can not be used as a primary encryption method");
|
||||
}
|
||||
@@ -92,7 +78,6 @@ public:
|
||||
return;
|
||||
|
||||
GetIVFromPass(nc->pass);
|
||||
use_iv = true;
|
||||
auto enc = EncryptInternal(req->GetPassword());
|
||||
if (nc->pass.equals_cs(enc))
|
||||
{
|
||||
|
||||
@@ -8,8 +8,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: argon2 */
|
||||
/* RequiredWindowsLibraries: argon2 */
|
||||
/// BEGIN CMAKE
|
||||
/// if(WIN32)
|
||||
/// target_link_libraries(${SO} PRIVATE CONAN_PKG::argon2)
|
||||
/// else()
|
||||
/// pkg_check_modules("ARGON2" IMPORTED_TARGET REQUIRED "libargon2")
|
||||
/// target_link_libraries(${SO} PRIVATE PkgConfig::ARGON2)
|
||||
/// endif()
|
||||
/// END CMAKE
|
||||
|
||||
#include <climits>
|
||||
#include <random>
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: crypt */
|
||||
|
||||
#include "module.h"
|
||||
|
||||
class EPOSIX final
|
||||
|
||||
@@ -9,7 +9,12 @@
|
||||
* Based on the original code of Services by Andy Church.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: ldap_r|ldap,lber */
|
||||
/// BEGIN CMAKE
|
||||
/// if(NOT WIN32)
|
||||
/// pkg_check_modules("OPENLDAP" IMPORTED_TARGET REQUIRED "lber" "ldap")
|
||||
/// target_link_libraries(${SO} PRIVATE PkgConfig::OPENLDAP)
|
||||
/// endif()
|
||||
/// END CMAKE
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/ldap.h"
|
||||
|
||||
+14
-8
@@ -6,8 +6,14 @@
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: mysqlclient */
|
||||
/* RequiredWindowsLibraries: libmysql */
|
||||
/// BEGIN CMAKE
|
||||
/// if(WIN32)
|
||||
/// target_link_libraries(${SO} PRIVATE CONAN_PKG::libmysqlclient)
|
||||
/// else()
|
||||
/// pkg_search_module("MYSQL" IMPORTED_TARGET REQUIRED "mysqlclient" "mariadb")
|
||||
/// target_link_libraries(${SO} PRIVATE PkgConfig::MYSQL)
|
||||
/// endif()
|
||||
/// END CMAKE
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/sql.h"
|
||||
@@ -200,7 +206,7 @@ public:
|
||||
|
||||
Anope::string GetColumn(Serialize::DataType dt)
|
||||
{
|
||||
return Anope::printf("%s %s DEFAULT %s",
|
||||
return Anope::Format("%s %s DEFAULT %s",
|
||||
GetColumnType(dt),
|
||||
GetColumnNull(dt) ? "NULL" : "NOT NULL",
|
||||
GetColumnDefault(dt));
|
||||
@@ -245,7 +251,7 @@ public:
|
||||
DThread = new DispatcherThread();
|
||||
DThread->Start();
|
||||
|
||||
Log(this) << "Module was compiled against MySQL version " << (MYSQL_VERSION_ID / 10000) << "." << (MYSQL_VERSION_ID / 100 % 100) << "." << (MYSQL_VERSION_ID % 100) << " and is running against version " << mysql_get_client_info();
|
||||
Log(this) << "Module was compiled against MySQL version " << MYSQL_SERVER_VERSION << " and is running against version " << mysql_get_client_info();
|
||||
}
|
||||
|
||||
~ModuleSQL()
|
||||
@@ -498,24 +504,24 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
|
||||
{
|
||||
// We can't just use MODIFY COLUMN here because the value may not
|
||||
// be valid and we may need to replace with the default.
|
||||
auto res = this->RunQuery(Anope::printf("ALTER TABLE `%s` ADD COLUMN `%s_new` %s; ",
|
||||
auto res = this->RunQuery(Anope::Format("ALTER TABLE `%s` ADD COLUMN `%s_new` %s; ",
|
||||
table.c_str(), column.c_str(), GetColumn(stype).c_str()));
|
||||
|
||||
if (res)
|
||||
{
|
||||
res = this->RunQuery(Anope::printf("UPDATE IGNORE `%s` SET `%s_new` = %s; ",
|
||||
res = this->RunQuery(Anope::Format("UPDATE IGNORE `%s` SET `%s_new` = %s; ",
|
||||
table.c_str(), column.c_str(), column.c_str()));
|
||||
}
|
||||
|
||||
if (res)
|
||||
{
|
||||
res = this->RunQuery(Anope::printf("ALTER TABLE `%s` DROP COLUMN `%s`; ",
|
||||
res = this->RunQuery(Anope::Format("ALTER TABLE `%s` DROP COLUMN `%s`; ",
|
||||
table.c_str(), column.c_str()));
|
||||
}
|
||||
|
||||
if (res)
|
||||
{
|
||||
res = this->RunQuery(Anope::printf("ALTER TABLE `%s` RENAME COLUMN `%s_new` TO `%s`; ",
|
||||
res = this->RunQuery(Anope::Format("ALTER TABLE `%s` RENAME COLUMN `%s_new` TO `%s`; ",
|
||||
table.c_str(), column.c_str(), column.c_str()));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,14 @@
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: pcre2-8 */
|
||||
/* RequiredWindowsLibraries: pcre2-8 */
|
||||
/// BEGIN CMAKE
|
||||
/// if(WIN32)
|
||||
/// target_link_libraries(${SO} PRIVATE CONAN_PKG::pcre2)
|
||||
/// else()
|
||||
/// pkg_check_modules("PCRE2" IMPORTED_TARGET REQUIRED "libpcre2-8")
|
||||
/// target_link_libraries(${SO} PRIVATE PkgConfig::PCRE2)
|
||||
/// endif()
|
||||
/// END CMAKE
|
||||
|
||||
#include "module.h"
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: tre */
|
||||
/// BEGIN CMAKE
|
||||
/// pkg_check_modules("TRE" IMPORTED_TARGET REQUIRED "tre")
|
||||
/// target_link_libraries(${SO} PRIVATE PkgConfig::TRE)
|
||||
/// END CMAKE
|
||||
|
||||
#include "module.h"
|
||||
#include <tre/regex.h>
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: sqlite3 */
|
||||
/* RequiredWindowsLibraries: sqlite3 */
|
||||
/// BEGIN CMAKE
|
||||
/// find_package("SQLite3" REQUIRED)
|
||||
/// target_link_libraries(${SO} PRIVATE SQLite::SQLite3)
|
||||
/// END CMAKE
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/sql.h"
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: gnutls */
|
||||
/* RequiredWindowsLibraries: libgnutls-30 */
|
||||
/// BEGIN CMAKE
|
||||
/// find_package("GnuTLS" REQUIRED)
|
||||
/// target_link_libraries(${SO} PRIVATE GnuTLS::GnuTLS)
|
||||
/// END CMAKE
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/ssl.h"
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: ssl,crypto */
|
||||
/* RequiredWindowsLibraries: libssl,libcrypto */
|
||||
/// BEGIN CMAKE
|
||||
/// find_package("OpenSSL" REQUIRED)
|
||||
/// target_link_libraries(${SO} PRIVATE OpenSSL::Crypto OpenSSL::SSL)
|
||||
/// END CMAKE
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/ssl.h"
|
||||
|
||||
@@ -6,8 +6,11 @@
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
|
||||
/* RequiredLibraries: xmlrpc */
|
||||
/// BEGIN CMAKE
|
||||
/// find_library("XMLRPC" "xmlrpc" REQUIRED)
|
||||
/// message(STATUS "Found XMLRPC: ${XMLRPC}")
|
||||
/// target_link_libraries(${SO} PRIVATE ${XMLRPC})
|
||||
/// END CMAKE
|
||||
|
||||
#include <xmlrpc-c/base.h>
|
||||
|
||||
@@ -148,7 +151,7 @@ public:
|
||||
|
||||
if (request.data.size() < event->GetMinParams())
|
||||
{
|
||||
auto error = Anope::printf("Not enough parameters (given %zu, expected %zu)",
|
||||
auto error = Anope::Format("Not enough parameters (given %zu, expected %zu)",
|
||||
request.data.size(), event->GetMinParams());
|
||||
xmlrpc_env_set_fault(&env, RPC::ERR_INVALID_PARAMS, error.c_str());
|
||||
SendError(reply, env);
|
||||
|
||||
+2
-2
@@ -110,7 +110,7 @@ public:
|
||||
if (params.empty())
|
||||
return;
|
||||
|
||||
Anope::string normalized_param0 = Anope::NormalizeBuffer(params[0]);
|
||||
Anope::string normalized_param0 = Anope::RemoveFormatting(params[0]);
|
||||
Anope::string fantasy_chars = Config->GetModule(this).Get<Anope::string>("fantasycharacter", "!");
|
||||
|
||||
if (!normalized_param0.find(c->ci->bi->nick))
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
full_command.erase(full_command.begin());
|
||||
|
||||
++count;
|
||||
it = Config->Fantasy.find(Anope::NormalizeBuffer(full_command));
|
||||
it = Config->Fantasy.find(Anope::RemoveFormatting(full_command));
|
||||
}
|
||||
|
||||
if (it == Config->Fantasy.end())
|
||||
|
||||
@@ -114,6 +114,8 @@ private:
|
||||
|
||||
ListFormatter list(source.nc);
|
||||
list.AddColumn(_("Number")).AddColumn(_("Message"));
|
||||
list.SetFlexible(_("{number}: {message}"));
|
||||
|
||||
for (size_t i = 0; i < q->size(); ++i)
|
||||
{
|
||||
ListFormatter::ListEntry entry;
|
||||
@@ -121,11 +123,7 @@ private:
|
||||
entry["Message"] = (*q)[i];
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
if (source && !Config->GetModule(this).Get<bool>("anonymousglobal"))
|
||||
{
|
||||
// A source is available and they're not anonymous.
|
||||
line = Anope::printf("[%s] %s", source->GetNick().c_str(), message.c_str());
|
||||
line = Anope::Format("[%s] %s", source->GetNick().c_str(), message.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ public:
|
||||
Anope::string *greet = ns_greet.Get(user->Account());
|
||||
if (bs_greet.HasExt(c->ci) && greet != NULL && !greet->empty() && c->FindUser(c->ci->bi) && c->ci->AccessFor(user).HasPriv("GREET"))
|
||||
{
|
||||
const auto message = Anope::printf("[%s] %s", user->Account()->display.c_str(), greet->c_str());
|
||||
const auto message = Anope::Format("[%s] %s", user->Account()->display.c_str(), greet->c_str());
|
||||
IRCD->SendPrivmsg(*c->ci->bi, c->name, message);
|
||||
c->ci->bi->lastmsg = Anope::CurTime;
|
||||
}
|
||||
|
||||
@@ -183,8 +183,6 @@ public:
|
||||
}
|
||||
|
||||
FOREACH_MOD(OnPostHelp, (source, params));
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -59,8 +59,6 @@ public:
|
||||
}
|
||||
else
|
||||
source.Reply(HOST_NOT_ASSIGNED);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -52,8 +52,10 @@ public:
|
||||
}
|
||||
|
||||
unsigned display_counter = 0, listmax = Config->GetModule(this->owner).Get<unsigned>("listmax", "50");
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("VHost")).AddColumn(_("Creator")).AddColumn(_("Created"));
|
||||
list.SetFlexible(_("{number}: \002{nick}\002 = {vhost} -- created by {creator} at {created}"));
|
||||
|
||||
for (const auto &[_, na] : *NickAliasList)
|
||||
{
|
||||
@@ -112,11 +114,7 @@ public:
|
||||
source.Reply(_("Displayed all records (count: \002%d\002)."), display_counter);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -39,8 +39,6 @@ public:
|
||||
Log(LOG_COMMAND, source, this) << "to disable their vhost";
|
||||
source.Reply(_("Your vhost was removed and the normal cloaking restored."));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -42,8 +42,6 @@ public:
|
||||
}
|
||||
else
|
||||
source.Reply(HOST_NOT_ASSIGNED);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
+221
-21
@@ -15,12 +15,20 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/dns.h"
|
||||
#include "modules/hostserv/request.h"
|
||||
|
||||
static ServiceReference<DNS::Manager> dnsmanager("DNS::Manager", "dns/manager");
|
||||
static ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ");
|
||||
|
||||
static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vident, const Anope::string &vhost);
|
||||
|
||||
namespace
|
||||
{
|
||||
// The name of the DNS record used for validation.
|
||||
Anope::string validation_record;
|
||||
}
|
||||
|
||||
struct HostRequestImpl final
|
||||
: HostRequest
|
||||
, Serializable
|
||||
@@ -29,6 +37,23 @@ struct HostRequestImpl final
|
||||
: Serializable("HostRequest")
|
||||
{
|
||||
}
|
||||
|
||||
static HostRequestImpl *Get(NickAlias *na)
|
||||
{
|
||||
return na ? na->GetExt<HostRequestImpl>("hostrequest") : nullptr;
|
||||
}
|
||||
|
||||
Anope::string Mask() const
|
||||
{
|
||||
if (ident.empty())
|
||||
return host;
|
||||
return ident + "@" + host;
|
||||
}
|
||||
|
||||
Anope::string GetValidationRecord() const
|
||||
{
|
||||
return Anope::Format("%s=%s", validation_record.c_str(), this->validation_token.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
struct HostRequestTypeImpl final
|
||||
@@ -46,6 +71,8 @@ struct HostRequestTypeImpl final
|
||||
data.Store("ident", req->ident);
|
||||
data.Store("host", req->host);
|
||||
data.Store("time", req->time);
|
||||
data.Store("validation_token", req->validation_token);
|
||||
data.Store("last_validation", req->last_validation);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override
|
||||
@@ -68,20 +95,99 @@ struct HostRequestTypeImpl final
|
||||
data["ident"] >> req->ident;
|
||||
data["host"] >> req->host;
|
||||
data["time"] >> req->time;
|
||||
data["validation_token"] >> req->validation_token;
|
||||
data["last_validation"] >> req->last_validation;
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
};
|
||||
|
||||
class DNSHostResolver final
|
||||
: public DNS::Request
|
||||
{
|
||||
private:
|
||||
Command *command;
|
||||
Reference<NickAlias> nickalias;
|
||||
CommandSource source;
|
||||
|
||||
void HandleError(HostRequestImpl *hr)
|
||||
{
|
||||
source.Reply(_(
|
||||
"Unable to find the DNS record required to validate \002%s\002. If you have not already "
|
||||
"done this add a TXT record for %s with the value %s and re-execute this command."
|
||||
),
|
||||
hr->Mask().c_str(),
|
||||
hr->host.c_str(),
|
||||
hr->GetValidationRecord().c_str()
|
||||
);
|
||||
}
|
||||
|
||||
public:
|
||||
DNSHostResolver(Command *cmd, HostRequest *hr, NickAlias *na, const CommandSource &src)
|
||||
: Request(dnsmanager, cmd->module, hr->host, DNS::QUERY_TXT, false)
|
||||
, command(cmd)
|
||||
, nickalias(na)
|
||||
, source(src)
|
||||
{
|
||||
hr->last_validation = Anope::CurTime;
|
||||
Log(LOG_DEBUG) << "Checking " << hr->host << " for " << hr->validation_token;
|
||||
}
|
||||
|
||||
void OnError(const DNS::Query *record) override
|
||||
{
|
||||
NickAlias *na = nickalias;
|
||||
if (!na)
|
||||
return; // Nick has been dropped.
|
||||
|
||||
auto *hr = HostRequestImpl::Get(na);
|
||||
if (!hr)
|
||||
{
|
||||
source.Reply(_("No request for nick %s found."), source.GetNick().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
HandleError(hr);
|
||||
}
|
||||
|
||||
void OnLookupComplete(const DNS::Query *record) override
|
||||
{
|
||||
NickAlias *na = nickalias;
|
||||
if (!na)
|
||||
return; // Nick has been dropped.
|
||||
|
||||
auto *hr = HostRequestImpl::Get(na);
|
||||
if (!hr)
|
||||
{
|
||||
source.Reply(_("No request for nick %s found."), source.GetNick().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &answer : record->answers)
|
||||
{
|
||||
if (answer.rdata != hr->GetValidationRecord())
|
||||
continue; // Not for us.
|
||||
|
||||
na->SetVHost(hr->ident, hr->host, source.GetNick(), hr->time);
|
||||
FOREACH_MOD(OnSetVHost, (na));
|
||||
|
||||
if (Config->GetModule(command->module).Get<bool>("memouser") && memoserv)
|
||||
memoserv->Send(source.service->nick, na->nick, _("Your requested vhost has been validated via DNS."), true);
|
||||
|
||||
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();
|
||||
na->Shrink<HostRequestImpl>("hostrequest");
|
||||
|
||||
return; // We're done.
|
||||
}
|
||||
|
||||
HandleError(hr);
|
||||
}
|
||||
};
|
||||
|
||||
class CommandHSRequest final
|
||||
: public Command
|
||||
{
|
||||
static bool isvalidchar(char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-';
|
||||
}
|
||||
|
||||
public:
|
||||
CommandHSRequest(Module *creator) : Command(creator, "hostserv/request", 1, 1)
|
||||
{
|
||||
@@ -142,13 +248,11 @@ public:
|
||||
source.Reply(HOST_NO_VIDENT);
|
||||
return;
|
||||
}
|
||||
for (const auto &chr : user)
|
||||
|
||||
if (!IRCD->IsIdentValid(user))
|
||||
{
|
||||
if (!isvalidchar(chr))
|
||||
{
|
||||
source.Reply(HOST_SET_IDENT_ERROR);
|
||||
return;
|
||||
}
|
||||
source.Reply(HOST_SET_IDENT_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,9 +282,28 @@ public:
|
||||
req.ident = user;
|
||||
req.host = host;
|
||||
req.time = Anope::CurTime;
|
||||
req.validation_token = Anope::Random(Config->GetBlock("options").Get<size_t>("codelength", "15"));
|
||||
na->Extend<HostRequestImpl>("hostrequest", req);
|
||||
|
||||
source.Reply(_("Your vhost has been requested."));
|
||||
BotInfo *bi;
|
||||
Anope::string cmd;
|
||||
if (dnsmanager && Command::FindCommandFromService("hostserv/validate", bi, cmd))
|
||||
{
|
||||
source.Reply(_(
|
||||
"Your vhost \002%s\002 has been requested. If the requested vhost is for a valid "
|
||||
"DNS name you can add a TXT record for %s with the value %s and automatically "
|
||||
"approve your vhost using \002%s\002."
|
||||
),
|
||||
req.Mask().c_str(),
|
||||
req.host.c_str(),
|
||||
req.GetValidationRecord().c_str(),
|
||||
bi->GetQueryCommand("hostserv/validate").c_str()
|
||||
);
|
||||
}
|
||||
else
|
||||
source.Reply(_("Your vhost \002%s\002 has been requested."), req.Mask().c_str());
|
||||
|
||||
|
||||
req_send_memos(owner, source, user, host);
|
||||
Log(LOG_COMMAND, source, this) << "to request new vhost " << (!user.empty() ? user + "@" : "") << host;
|
||||
}
|
||||
@@ -279,7 +402,7 @@ public:
|
||||
{
|
||||
Anope::string message;
|
||||
if (!reason.empty())
|
||||
message = Anope::printf(_("Your requested vhost has been rejected. Reason: %s"), reason.c_str());
|
||||
message = Anope::Format(_("Your requested vhost has been rejected. Reason: %s"), reason.c_str());
|
||||
else
|
||||
message = _("Your requested vhost has been rejected.");
|
||||
|
||||
@@ -318,9 +441,10 @@ public:
|
||||
{
|
||||
unsigned counter = 0;
|
||||
unsigned display_counter = 0, listmax = Config->GetModule(this->owner).Get<unsigned>("listmax");
|
||||
ListFormatter list(source.GetAccount());
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("VHost")).AddColumn(_("Created"));
|
||||
list.SetFlexible(_("{number}: \002{nick}\002 = {vhost} -- created by {creator} at {created}"));
|
||||
|
||||
for (const auto &[nick, na] : *NickAliasList)
|
||||
{
|
||||
@@ -345,12 +469,7 @@ public:
|
||||
++counter;
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("Displayed \002%d\002 records (\002%d\002 total)."), display_counter, counter);
|
||||
}
|
||||
|
||||
@@ -364,6 +483,78 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CommandHSValidate final
|
||||
: public Command
|
||||
{
|
||||
public:
|
||||
time_t cooldown;
|
||||
|
||||
CommandHSValidate(Module *creator)
|
||||
: Command(creator, "hostserv/validate", 0)
|
||||
{
|
||||
this->SetDesc(_("Validates a previously requested vhost using DNS"));
|
||||
}
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *na = NickAlias::Find(source.GetNick());
|
||||
if (!na || na->nc != source.GetAccount())
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *req = HostRequestImpl::Get(na);
|
||||
if (!req)
|
||||
{
|
||||
source.Reply(_("No request for nick %s found."), source.GetNick().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
auto next_validation = req->last_validation + cooldown;
|
||||
if (req->last_validation && next_validation > Anope::CurTime)
|
||||
{
|
||||
source.Reply(_("You must wait for %s before trying DNS validation again."),
|
||||
Anope::Duration(next_validation - Anope::CurTime).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
DNSHostResolver *res = nullptr;
|
||||
try
|
||||
{
|
||||
if (!dnsmanager)
|
||||
throw SocketException("DNS is not available");
|
||||
|
||||
res = new DNSHostResolver(this, req, na, source);
|
||||
dnsmanager->Process(res);
|
||||
}
|
||||
catch (const SocketException &ex)
|
||||
{
|
||||
Log(this->module) << ex.GetReason();
|
||||
source.Reply("Unable to validate vhosts right now. Please try again later.");
|
||||
delete res;
|
||||
}
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_(
|
||||
"Validates a previously requested vhost using DNS. If you own the domain you "
|
||||
"have requested as a vhost you can validate your ownership of it using a DNS "
|
||||
"TXT record to approve your own vhost."
|
||||
));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class HSRequest final
|
||||
: public Module
|
||||
{
|
||||
@@ -371,6 +562,7 @@ class HSRequest final
|
||||
CommandHSActivate commandhsactive;
|
||||
CommandHSReject commandhsreject;
|
||||
CommandHSWaiting commandhswaiting;
|
||||
CommandHSValidate commandhsvalidate;
|
||||
ExtensibleItem<HostRequestImpl> hostrequest;
|
||||
HostRequestTypeImpl request_type;
|
||||
|
||||
@@ -381,11 +573,19 @@ public:
|
||||
, commandhsactive(this)
|
||||
, commandhsreject(this)
|
||||
, commandhswaiting(this)
|
||||
, commandhsvalidate(this)
|
||||
, hostrequest(this, "hostrequest")
|
||||
{
|
||||
if (!IRCD || !IRCD->CanSetVHost)
|
||||
throw ModuleException("Your IRCd does not support vhosts");
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const auto &block = conf.GetModule(this);
|
||||
commandhsvalidate.cooldown = block.Get<time_t>("validationcooldown", "5m");
|
||||
validation_record = block.Get<const Anope::string>("validationrecord", "anope-dns-validation");
|
||||
}
|
||||
};
|
||||
|
||||
static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vident, const Anope::string &vhost)
|
||||
@@ -404,7 +604,7 @@ static void req_send_memos(Module *me, CommandSource &source, const Anope::strin
|
||||
if (!na)
|
||||
continue;
|
||||
|
||||
Anope::string message = Anope::printf(_("VHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str());
|
||||
Anope::string message = Anope::Format(_("VHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str());
|
||||
|
||||
memoserv->Send(source.service->nick, na->nick, message, true);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,6 @@ public:
|
||||
if (na == NULL)
|
||||
{
|
||||
na = new NickAlias(ii->req->GetAccount(), new NickCore(ii->req->GetAccount()));
|
||||
na->last_realname = ii->user ? ii->user->realname : ii->req->GetAccount();
|
||||
FOREACH_MOD(OnNickRegister, (ii->user, na, ii->req->GetPassword()));
|
||||
BotInfo *NickServ = Config->GetClient("NickServ");
|
||||
if (ii->user && NickServ)
|
||||
|
||||
@@ -59,8 +59,6 @@ public:
|
||||
|
||||
if (!found)
|
||||
source.Reply(_("Nick %s doesn't have a memo from you."), na->nick.c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -121,7 +121,6 @@ public:
|
||||
source.Reply(_("All of your memos have been deleted."));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -77,6 +77,8 @@ public:
|
||||
{
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Mask"));
|
||||
list.SetFlexible(_("\002{mask}\002"));
|
||||
|
||||
for (const auto &ignore : mi->ignores)
|
||||
{
|
||||
ListFormatter::ListEntry entry;
|
||||
@@ -85,18 +87,11 @@ public:
|
||||
}
|
||||
|
||||
source.Reply(_("Memo ignore list:"));
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -61,8 +61,8 @@ public:
|
||||
else
|
||||
{
|
||||
ListFormatter list(source.GetAccount());
|
||||
|
||||
list.AddColumn(_("Number")).AddColumn(_("Sender")).AddColumn(_("Date/Time"));
|
||||
list.SetFlexible(_("{number}: sent by \002{sender}\002 at {date/time}"));
|
||||
|
||||
if (!param.empty() && isdigit(param[0]))
|
||||
{
|
||||
@@ -127,14 +127,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
source.Reply(_("Memos for %s:"), ci ? ci->name.c_str() : source.GetNick().c_str());
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -32,7 +32,7 @@ static void rsend_notify(CommandSource &source, MemoInfo *mi, Memo *m, const Ano
|
||||
|
||||
/* Text of the memo varies if the recipient was a
|
||||
nick or channel */
|
||||
Anope::string text = Anope::printf(Language::Translate(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")), targ.c_str());
|
||||
Anope::string text = Anope::Format(Language::Translate(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")), targ.c_str());
|
||||
|
||||
/* Send notification */
|
||||
MemoServService->Send(source.GetNick(), m->sender, text, true);
|
||||
@@ -191,7 +191,6 @@ public:
|
||||
list.Process();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -191,7 +191,6 @@ private:
|
||||
else
|
||||
source.Reply(_("Memo limit \002disabled\002 for %s."), !chan.empty() ? chan.c_str() : user.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
public:
|
||||
CommandMSSet(Module *creator) : Command(creator, "memoserv/set", 2, 5)
|
||||
@@ -215,8 +214,6 @@ public:
|
||||
{
|
||||
this->OnSyntaxError(source, "");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
|
||||
|
||||
@@ -224,16 +224,21 @@ public:
|
||||
auto protect = protectafter ? *protectafter : block.Get<time_t>("defaultprotect", "1m");
|
||||
protect = std::clamp(protect, block.Get<time_t>("minprotect", "10s"), block.Get<time_t>("maxprotect", "10m"));
|
||||
|
||||
u->SendMessage(NickServ, _(
|
||||
"This nickname is registered and has protection enabled. If it belongs to you, "
|
||||
"type \002%s\032\037password\037\002 to identify to your account."
|
||||
),
|
||||
NickServ->GetQueryCommand("nickserv/identify", u->nick).c_str()
|
||||
);
|
||||
|
||||
if (protect)
|
||||
{
|
||||
u->SendMessage(NickServ, NICK_IS_SECURE, NickServ->GetQueryCommand("nickserv/identify").c_str());
|
||||
u->SendMessage(NickServ, _("If you do not change within %s, I will change your nick."),
|
||||
u->SendMessage(NickServ, _("Your nickname will be changed in %s if you do not identify."),
|
||||
Anope::Duration(protect, u->Account()).c_str());
|
||||
new NickServCollide(this, this, u, na, protect);
|
||||
}
|
||||
else
|
||||
{
|
||||
u->SendMessage(NickServ, FORCENICKCHANGE_NOW);
|
||||
this->Collide(u, na);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,13 @@ class CommandNSAJoin final
|
||||
{
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Channel")).AddColumn(_("Key"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Key"].empty()
|
||||
? _("{number}: \002{channel}\002")
|
||||
: _("{number}: \002{channel}\002 (key: {key})");
|
||||
});
|
||||
|
||||
for (unsigned i = 0; i < (*channels)->size(); ++i)
|
||||
{
|
||||
AJoinEntry *aj = (*channels)->at(i);
|
||||
@@ -124,12 +131,7 @@ class CommandNSAJoin final
|
||||
}
|
||||
|
||||
source.Reply(_("%s's auto join list:"), nc->display.c_str());
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
list.SendTo(source);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +38,16 @@ public:
|
||||
nc = na->nc;
|
||||
}
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
int chan_count = 0;
|
||||
|
||||
ListFormatter list(source.GetAccount());
|
||||
list.AddColumn(_("Number")).AddColumn(_("Channel")).AddColumn(_("Access")).AddColumn(_("Description"));
|
||||
list.SetFlexible([](ListFormatter::ListEntry &row)
|
||||
{
|
||||
return row["Description"].empty()
|
||||
? _("{number}: \002{channel}\002 = {access}")
|
||||
: _("{number}: \002{channel}\002 = {access} ({description})");
|
||||
});
|
||||
|
||||
std::deque<ChannelInfo *> queue;
|
||||
nc->GetChannelReferences(queue);
|
||||
@@ -87,9 +93,6 @@ public:
|
||||
list.AddEntry(entry);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> replies;
|
||||
list.Process(replies);
|
||||
|
||||
if (!chan_count)
|
||||
{
|
||||
source.Reply(_("\002%s\002 has no access in any channels."), nc->display.c_str());
|
||||
@@ -97,10 +100,7 @@ public:
|
||||
else
|
||||
{
|
||||
source.Reply(_("Channels that \002%s\002 has access on:"), nc->display.c_str());
|
||||
|
||||
for (const auto &reply : replies)
|
||||
source.Reply(reply);
|
||||
|
||||
list.SendTo(source);
|
||||
source.Reply(_("End of list - %d channels shown."), chan_count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,7 +430,7 @@ public:
|
||||
|
||||
auto *NickServ = Config->GetClient("NickServ");
|
||||
u->SendMessage(NickServ, _("SSL certificate fingerprint accepted, you are now identified to \002%s\002."), nc->display.c_str());
|
||||
Log(NickServ) << u->GetMask() << " automatically identified for account " << nc->display << " via SSL certificate fingerprint";
|
||||
Log(NickServ) << u->GetMask() << " automatically identified for account " << nc->display << " via SSL certificate fingerprint " << u->fingerprint;
|
||||
}
|
||||
|
||||
void OnNickRegister(User *u, NickAlias *na, const Anope::string &pass) override
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user