Initial commit

This commit is contained in:
Dionysus 2023-05-07 13:44:21 -04:00
commit 45be6747c9
Signed by: acidvegas
GPG Key ID: EF4B922DB85DC9DE
435 changed files with 245769 additions and 0 deletions

19
.BANNER Normal file
View File

@ -0,0 +1,19 @@
___
/ _ \ https://www.anope.org/
| /_\ | _ __ _ _ _ _ ___
| _ || '_ \/ _ \/ _ \ / _ \
| | | || | | |_| |_| | __/
|_| |_||_| |_\___/| _/ \___|
| |
|_| IRC Services
CURVER
This program will help you to compile your Services, and ask you
questions regarding the compile-time settings of it during the
process. For more options type SOURCE_DIR/Config --help
Anope is a set of Services for IRC networks that allows users to
manage their nicks and channels in a secure and efficient way,
and administrators to manage their network with powerful tools.
For all your Anope needs please visit our portal at
https://www.anope.org/

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
build/
config.cache
include/sysconf.h
modules/m_ldap.cpp
modules/m_ldap_authentication.cpp
modules/m_ldap_oper.cpp
modules/m_mysql.cpp
modules/m_regex_pcre.cpp
modules/m_regex_pcre2.cpp
modules/m_regex_posix.cpp
modules/m_regex_tre.cpp
modules/m_sql_authentication.cpp
modules/m_sql_log.cpp
modules/m_sql_oper.cpp
modules/m_sqlite.cpp
modules/m_ssl_gnutls.cpp
modules/m_ssl_openssl.cpp
modules/stats
run/

50
.mailmap Normal file
View File

@ -0,0 +1,50 @@
(svnadmin) <svn@localhost> <svn svn@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Adam <adam@anope.org> <adam-@5417fbe8-f217-4b02-8779-1006273d7864>
Adam <adam@anope.org> <adam@adam-laptop.(none)>
Adam <adam@anope.org> <Adam@anope.org>
Adam <adam@anope.org> <Adam@drink-coca-cola.info>
Adam <adam@anope.org> <Adam@sigterm.info>
Adam Kramer <ribosome@anope.org> <ribosome ribosome@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Alvaro Toledo <atoledo@keldon.org> <atoledo atoledo@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Attila Molnar <attilamolnar@hush.com>
Björn Stiddien <keeper@anope.org> <keeper keeper@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Charles Kingsley <chaz@anope.org>
Charles Kingsley <chaz@anope.org> <sjaz@5417fbe8-f217-4b02-8779-1006273d7864>
Cronus <cronus@nite-serv.com>
Daniel Engel <dane@zero.org> <dane dane@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
David Robson <rob@anope.org> <robbeh@5417fbe8-f217-4b02-8779-1006273d7864>
David Robson <rob@anope.org> <rob rob@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Dennis Friis <peavey@inspircd.org> <peavey peavey@inspircd.org@5417fbe8-f217-4b02-8779-1006273d7864>
Fabio Scotoni <cculex@gmail.com>
Florian Schulze <certus@anope.org> <certus certus@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Gabriel Acevedo H. <drstein@anope.org> <drstein drstein@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Harakiri <harakiri@overstack.fr>
Jan Milants <viper@anope.org>
Jan Milants <viper@anope.org> <jantje_85@5417fbe8-f217-4b02-8779-1006273d7864>
Jan Milants <viper@anope.org> <viper viper@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Jens Voss <dukepyrolator@anope.org> <anope@s15355730.onlinehome-server.info>
Jens Voss <dukepyrolator@anope.org> <DukePyrolator@5417fbe8-f217-4b02-8779-1006273d7864>
Jens Voss <dukepyrolator@anope.org> <DukePyrolator@anope.org>
Jens Voss <dukepyrolator@anope.org> Jens Voß <jens@pyrobook.(none)>
Lee Holmes <lethality@anope.org>
Lee Holmes <lethality@anope.org> <lee@lethality.me.uk>
Mark Summers <mark@goopler.net> <mark mark@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Matt Schatz <genius3000@g3k.solutions>
Matt Ullman <matt@airraidsirens.com> <blindsight@gamesurge.net>
Michael Hazell <michaelhazell@hotmail.com> <Techman-@users.noreply.github.com>
Michael Wobst <wobst.michael@web.de>
Michael Wobst <wobst.michael@web.de> <michael@static.163.129.251.148.clients.your-server.de>
Michael Wobst <wobst.michael@web.de> <michael@wobst.at>
Naram Qashat <cyberbotx@anope.org> <cyberbotx@5417fbe8-f217-4b02-8779-1006273d7864>
Naram Qashat <cyberbotx@anope.org> <cyberbotx@cyberbotx.com>
Naram Qashat <cyberbotx@anope.org> <Naram Qashat cyberbotx@cyberbotx.com@5417fbe8-f217-4b02-8779-1006273d7864>
Pieter Bootsma <geniusdex@anope.org> <geniusdex geniusdex@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
Robby <robby@chatbelgie.be> <robby@anope.org>
Robby <robby@chatbelgie.be> <robby@chat.be>
Robin Burchell <w00t@inspircd.org> <rburchell@5417fbe8-f217-4b02-8779-1006273d7864>
Robin Burchell <w00t@inspircd.org> <Robin Burchell w00t@inspircd.org@5417fbe8-f217-4b02-8779-1006273d7864>
Sadie Powell <sadie@witchery.services> Peter Powell <petpow@saberuk.com>
Sebastian Barfurth <github@afreshmelon.com>
Sebastian V. <hal9000@denorastats.org>
Sebastian V. <hal9000@denorastats.org> <pimpmylinux@5417fbe8-f217-4b02-8779-1006273d7864>
Trystan S. Lee <trystan@nomadirc.net> <trystan trystan@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>

559
CMakeLists.txt Normal file
View File

@ -0,0 +1,559 @@
# This usage of CMake requires at least version 2.4 (checks are made to determine what to use when certain versions lack functions)
cmake_minimum_required(VERSION 2.4 FATAL_ERROR)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
if(POLICY CMP0026)
cmake_policy(SET CMP0026 OLD)
endif(POLICY CMP0026)
if(POLICY CMP0007)
cmake_policy(SET CMP0007 OLD)
endif(POLICY CMP0007)
endif(COMMAND cmake_policy)
# Set the project as C++ primarily, but have C enabled for the checks required later
project(Anope CXX)
enable_language(C)
# Detect the version of CMake for the later conditional checks
execute_process(COMMAND ${CMAKE_COMMAND} --version OUTPUT_VARIABLE VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX REPLACE "cmake version 2\\.(.*)" "\\1" ONLY_VERSION "${VERSION}")
string(REGEX MATCH "-patch .*$" HAS_PATCH "${ONLY_VERSION}")
if(HAS_PATCH)
string(REGEX REPLACE "(.*)-patch .*" "\\1" MINOR_VERSION "${ONLY_VERSION}")
string(REGEX REPLACE ".*-patch (.*)" "\\1" PATCH_VERSION "${ONLY_VERSION}")
else(HAS_PATCH)
string(REGEX MATCH "\\." HAS_DOT "${ONLY_VERSION}")
if(HAS_DOT)
string(REGEX REPLACE "(.*)\\..*" "\\1" MINOR_VERSION "${ONLY_VERSION}")
string(REGEX REPLACE ".*\\.(.*)" "\\1" PATCH_VERSION "${ONLY_VERSION}")
else(HAS_DOT)
string(REGEX REPLACE "(.*)-beta" "\\1" MINOR_VERSION "${ONLY_VERSION}")
if(MINOR_VERSION STREQUAL "4-1\n")
set(PATCH_VERSION 1)
else(MINOR_VERSION STREQUAL "4-1\n")
set(PATCH_VERSION 0)
endif(MINOR_VERSION STREQUAL "4-1\n")
set(MINOR_VERSION 4)
endif(HAS_DOT)
endif(HAS_PATCH)
# Detect is we are using CMake 2.6 or better, these versions include functions that require less work than CMake 2.4 does
if(MINOR_VERSION GREATER 5)
set(CMAKE26_OR_BETTER TRUE)
set(CMAKE248_OR_BETTER TRUE)
set(CMAKE244_OR_BETTER TRUE)
set(CMAKE242_OR_BETTER TRUE)
else(MINOR_VERSION GREATER 5)
set(CMAKE26_OR_BETTER FALSE)
# Also detect if we are using CMake 2.4.8 or better, the FIND sub-command of list() is nonexistent in earlier versions
if(PATCH_VERSION GREATER 7)
set(CMAKE248_OR_BETTER TRUE)
set(CMAKE244_OR_BETTER TRUE)
set(CMAKE242_OR_BETTER TRUE)
else(PATCH_VERSION GREATER 7)
set(CMAKE248_OR_BETTER FALSE)
# Also detect if we are using CMake 2.4.4 or better, the CheckCXXCompilerFlag module and SORT sub-command of list() are nonexistent in earlier versions
if(PATCH_VERSION GREATER 3)
set(CMAKE244_OR_BETTER TRUE)
set(CMAKE242_OR_BETTER TRUE)
else(PATCH_VERSION GREATER 3)
set(CMAKE244_OR_BETTER FALSE)
# ALSO detect if we are using CMake 2.4.2 or better, the APPEND sub-command of list() is nonexistent in earlier versions
if(PATCH_VERSION GREATER 1)
set(CMAKE242_OR_BETTER TRUE)
else(PATCH_VERSION GREATER 1)
set(CMAKE242_OR_BETTER FALSE)
endif(PATCH_VERSION GREATER 1)
endif(PATCH_VERSION GREATER 3)
endif(PATCH_VERSION GREATER 7)
endif(MINOR_VERSION GREATER 5)
# Override the module include path to include our directory, for our Anope.cmake, as well as we are using our own version of the NSIS template
set(CMAKE_MODULE_PATH ${Anope_SOURCE_DIR}/cmake)
include(Anope)
# Force the locale to C for later uses of things like gcc so the messages come up in English, not the user's default language
set(ENV{LC_ALL} C)
# Start with empty defaults for library and include directories, to be used by GNU compilers only
set(DEFAULT_LIBRARY_DIRS)
set(DEFAULT_INCLUDE_DIRS)
# Check that we aren't running on an ancient broken GCC
if(CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_FULL_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX REPLACE "^(\\d+\\.\\d+)" "\\1" GCC_VERSION ${GCC_FULL_VERSION})
if(GCC_VERSION LESS 4.2)
message(FATAL_ERROR "Your compiler is too old to build Anope. Upgrade to GCC 4.2 or newer!")
endif(GCC_VERSION LESS 4.2)
if(GCC_VERSION GREATER 6.0 OR GCC_VERSION EQUAL 6.0)
set(CXXFLAGS "${CXXFLAGS} -fno-delete-null-pointer-checks")
endif(GCC_VERSION GREATER 6.0 OR GCC_VERSION EQUAL 6.0)
endif(CMAKE_COMPILER_IS_GNUCXX)
# If we are using a GNU compiler (have to use CXX because it seems to fail on C), we will be able to determine it's default paths for libraries and includes
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
# First look for the compiler's default library directories
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-search-dirs OUTPUT_VARIABLE LINES OUTPUT_STRIP_TRAILING_WHITESPACE)
# Find only the part after "libraries: "
string(REGEX REPLACE ".*\nlibraries: (.*)$" "\\1" LINE "${LINES}")
# Replace the colons in the list with semicolons (only when not on MinGW, which uses semicolons already), and if on MinGW, just copy the line
if(NOT MINGW)
string(REGEX REPLACE ":" ";" LIBRARIES ${LINE})
else(NOT MINGW)
set(LIBRARIES "${LINE}")
endif(NOT MINGW)
# Iterate through the libraries
foreach(LIBRARY ${LIBRARIES})
# Check if the first character is an equal sign, and skip that library directory as it is (I believe) the primary default and shows up later in the list anyways
string(SUBSTRING ${LIBRARY} 0 1 FIRST_CHAR)
if(NOT FIRST_CHAR STREQUAL "=")
# If the directory had no = in front of it, make sure it's absolute and add it to the list of default library directories
get_filename_component(LIBRARY ${LIBRARY} ABSOLUTE)
append_to_list(DEFAULT_LIBRARY_DIRS ${LIBRARY})
endif(NOT FIRST_CHAR STREQUAL "=")
endforeach(LIBRARY)
# Remove duplicate entries from the list
if(DEFAULT_LIBRARY_DIRS)
remove_list_duplicates(DEFAULT_LIBRARY_DIRS)
endif(DEFAULT_LIBRARY_DIRS)
# Create a temporary file to test for the default include directories
FILE(WRITE empty.cpp "")
# Next, we look for the compiler's default include directories
# Run the command to find the default include directories
execute_process(COMMAND ${CMAKE_C_COMPILER} -v -x c++ -E ${CMAKE_CURRENT_SOURCE_DIR}/empty.cpp ERROR_VARIABLE LINES OUTPUT_QUIET ERROR_STRIP_TRAILING_WHITESPACE)
# Remove the empty file, it is no longer needed
FILE(REMOVE empty.cpp)
# Convert the new lines to semicolons
string(REGEX REPLACE "\n" ";" LINES ${LINES})
# Temporary variable saying if we are in the search list or not
set(IN_SEARCH_LIST FALSE)
# Iterate through the lines
foreach(LINE ${LINES})
# If the line has the following on it, the next lines will contain directory names
if(LINE STREQUAL "#include <...> search starts here:")
set(IN_SEARCH TRUE)
else(LINE STREQUAL "#include <...> search starts here:")
# If the line has the following on it, we hit the end of the list
if(LINE STREQUAL "End of search list.")
set(IN_SEARCH FALSE)
else(LINE STREQUAL "End of search list.")
# If we are within the block between the above two lines...
if(IN_SEARCH)
# Get everything but the first character of the line
string(LENGTH ${LINE} LINE_LENGTH)
math(EXPR LINE_LENGTH "${LINE_LENGTH} - 1")
string(SUBSTRING ${LINE} 1 ${LINE_LENGTH} INCLUDE)
# For systems like Mac OS X, look for include paths that say " (framework directory)" at the end of them and strip that off
string(REGEX REPLACE " \\(framework directory\\)$" "" INCLUDE ${INCLUDE})
# Convert the path to an absolute one, just in case it wasn't
get_filename_component(INCLUDE ${INCLUDE} ABSOLUTE)
# Add that directory to the list of default include directories
append_to_list(DEFAULT_INCLUDE_DIRS ${INCLUDE})
endif(IN_SEARCH)
endif(LINE STREQUAL "End of search list.")
endif(LINE STREQUAL "#include <...> search starts here:")
endforeach(LINE)
# Remove duplicate entries from the list
if(DEFAULT_INCLUDE_DIRS)
remove_list_duplicates(DEFAULT_INCLUDE_DIRS)
endif(DEFAULT_INCLUDE_DIRS)
endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
# If we are using Visual Studio, locate the path of the Windows Server 2008 SDK or Windows Server 2003 Platform SDK, depending on which is installed
if(MSVC)
# If the path comes up as "/registry" from any of these, the path wasn't found, otherwise, we'll set WSDK_PATH to the corresponding path
# Look for the 2008 SDK under HKLM first
get_filename_component(WSDK2008_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" ABSOLUTE CACHE)
if(WSDK2008_PATH STREQUAL "/registry")
# If not found, look for the 2003 SDK under HKLM
get_filename_component(WSDK2003_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1;Install Dir]" ABSOLUTE CACHE)
if(WSDK2003_PATH STREQUAL "/registry")
# If not found, look for the 2008 SDK under HKCU
get_filename_component(WSDK2008_PATH "[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" ABSOLUTE CACHE)
if(WSDK2008_PATH STREQUAL "/registry")
# If not found, look for the 2003 SDK under HKCU
get_filename_component(WSDK2003_PATH "[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\MicrosoftSDK\\InstalledSDKs\\D2FF9F89-8AA2-4373-8A31-C838BF4DBBE1;Install Dir]" ABSOLUTE CACHE)
if(WSDK2003_PATH STREQUAL "/registry")
# The SDK was never found, set the path to nothing
set(WSDK_PATH "")
else(WSDK2003_PATH STREQUAL "/registry")
set(WSDK_PATH "${WSDK2003_PATH}")
endif(WSDK2003_PATH STREQUAL "/registry")
else(WSDK2008_PATH STREQUAL "/registry")
set(WSDK_PATH "${WSDK2008_PATH}")
endif(WSDK2008_PATH STREQUAL "/registry")
else(WSDK2003_PATH STREQUAL "/registry")
set(WSDK_PATH "${WSDK2003_PATH}")
endif(WSDK2003_PATH STREQUAL "/registry")
else(WSDK2008_PATH STREQUAL "/registry")
set(WSDK_PATH "${WSDK2008_PATH}")
endif(WSDK2008_PATH STREQUAL "/registry")
endif(MSVC)
# If the user specifies -DCMAKE_BUILD_TYPE on the command line, take their definition
# and dump it in the cache along with proper documentation, otherwise set CMAKE_BUILD_TYPE
# to Debug
# Only do this if not using Visual Studio
if(NOT MSVC)
if(CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
else(CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE DEBUG CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
endif(CMAKE_BUILD_TYPE)
endif(NOT MSVC)
# If running under MinGW, we have to force the resource compiler settings (hopefully this will be fixed in a later version of CMake)
if(MINGW)
set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC)
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -o <OBJECT> <SOURCE>")
endif(MINGW)
# Include the checking functions used later in this CMakeLists.txt
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckTypeSize)
include(CheckLibraryExists)
if(CMAKE244_OR_BETTER)
include(CheckCXXCompilerFlag)
else(CMAKE244_OR_BETTER)
include(TestCXXAcceptsFlag)
endif(CMAKE244_OR_BETTER)
# If extra include directories were specified, tell cmake about them.
if(EXTRA_INCLUDE)
include_directories(${EXTRA_INCLUDE})
endif(EXTRA_INCLUDE)
# If extra library directories were specified, tell cmake about them.
if(EXTRA_LIBS)
link_directories(${EXTRA_LIBS})
endif(EXTRA_LIBS)
# Find gettext
find_package(Gettext)
option(USE_PCH "Use precompiled headers" OFF)
# Use the following directories as includes
# Note that it is important the binary include directory comes before the
# source include directory so the precompiled headers work correctly.
include_directories(${Anope_BINARY_DIR}/include ${Anope_SOURCE_DIR}/include ${Anope_BINARY_DIR}/language ${Anope_SOURCE_DIR}/modules/pseudoclients)
# Pass on REPRODUCIBLE_BUILD
if(REPRODUCIBLE_BUILD)
add_definitions(-DREPRODUCIBLE_BUILD)
endif(REPRODUCIBLE_BUILD)
# If using Windows, always add the _WIN32 define
if(WIN32)
add_definitions(-D_WIN32)
# And include the windows specific folder for our anope_windows.h
include_directories(${Anope_SOURCE_DIR}/src/win32)
endif(WIN32)
# If using Visual Studio, set the C++ flags accordingly
if(MSVC)
# Remove the default exception handling flags, also remove default warning level flag
string(REPLACE "/EHsc " "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
string(REPLACE "/GX " "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
string(REPLACE "/W3 " "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
# Set the compile flags to have warnings on the max setting (but disable a few annoying ones), exception handling turned on, the proper defines
set(CXXFLAGS "${CXXFLAGS} /W4 /wd4100 /wd4127 /wd4250 /wd4251 /wd4355 /wd4706 /wd4800 /wd4996 /EHs")
add_definitions(-DMSVCPP -D_CRT_SECURE_NO_WARNINGS)
# Otherwise, we're not using Visual Studio
else(MSVC)
# Set the compile flags to have all warnings on (including shadowed variables)
set(CXXFLAGS "${CXXFLAGS} -Wall -Wshadow")
# If on a *nix system, also set the compile flags to remove GNU extensions (favor ISO C++) as well as reject non-ISO C++ code, also remove all leading underscores in exported symbols (only on GNU compiler)
if(UNIX)
set(CXXFLAGS "${CXXFLAGS} -ansi -pedantic ${CMAKE_CXX_FLAGS}")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CXXFLAGS "${CXXFLAGS} -Wno-long-long -fno-leading-underscore")
endif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# If we aren't on a *nix system, we are using MinGW
else(UNIX)
# Also, if we are building under MinGW, add another define for MinGW
if(MINGW)
add_definitions(-DMINGW)
endif(MINGW)
endif(UNIX)
endif(MSVC)
# If CMake has found that the given system requires a special library for dl* calls, include it with the linker flags
if(CMAKE_DL_LIBS)
append_to_list(LINK_LIBS ${CMAKE_DL_LIBS})
endif(CMAKE_DL_LIBS)
# Under MinGW, the -shared flag isn't properly set in the module-specific linker flags, add it from the C flags for shared libraries
if(MINGW)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS}")
endif(MINGW)
if(NOT PROGRAM_NAME)
# Under Windows, we set the executable name for Anope to be anope
if(WIN32)
set(PROGRAM_NAME anope)
# Under *nix, we set the executable name for Anope to be services
else(WIN32)
set(PROGRAM_NAME services)
endif(WIN32)
endif(NOT PROGRAM_NAME)
# If we are not using Visual Studio, we'll run the following checks
if(NOT MSVC)
# Check if the C++ compiler can accept the -pipe flag, and add it to the compile flags if it works
if(CMAKE244_OR_BETTER)
# If using CMake 2.4.4 or better, we can use check_cxx_compiler_flag
check_cxx_compiler_flag(-pipe HAVE_PIPE_FLAG)
else(CMAKE244_OR_BETTER)
# If using CMake 2.4.3 or older, we will use check_cxx_accepts_flags instead
check_cxx_accepts_flag(-pipe HAVE_PIPE_FLAG)
endif(CMAKE244_OR_BETTER)
# If the flag was accepted, add it to the list of flags
if(HAVE_PIPE_FLAG)
set(CXXFLAGS "${CXXFLAGS} -pipe")
endif(HAVE_PIPE_FLAG)
# The following are additional library checks, they are not required for Windows
if(NOT WIN32)
# Check if socket is within the socket library (if the library exists), and add it to the linker flags if needed
check_library_exists(socket socket "" HAVE_SOCKET_LIB)
if(HAVE_SOCKET_LIB)
append_to_list(LINK_LIBS socket)
endif(HAVE_SOCKET_LIB)
# Check if inet_addr is within the nsl library (if the library exists), and add it to the linker flags if needed
check_library_exists(nsl inet_addr "" HAVE_NSL_LIB)
if(HAVE_NSL_LIB)
append_to_list(LINK_LIBS nsl)
endif(HAVE_NSL_LIB)
# Check if pthread_create is within the pthread library (if the library exists), and add it to the linker flags if needed
check_library_exists(pthread pthread_create "" HAVE_PTHREAD)
if(HAVE_PTHREAD)
if(NOT APPLE)
set(LDFLAGS "${LDFLAGS} -pthread")
endif(NOT APPLE)
else(HAVE_PTHREAD)
message(FATAL_ERROR "The pthread library is required to build Anope")
endif(HAVE_PTHREAD)
endif(NOT WIN32)
endif(NOT MSVC)
# If DEFUMASK wasn't passed to CMake, set a default depending on if RUNGROUP was passed in or not
if(NOT DEFUMASK)
if(RUNGROUP)
set(DEFUMASK "007")
else(RUNGROUP)
set(DEFUMASK "077")
endif(RUNGROUP)
endif(NOT DEFUMASK)
# Set the DEBUG_BUILD for sysconf.h
if(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
set(DEBUG_BUILD TRUE)
endif(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
# Check for the existence of the following include files
check_include_file(cstdint HAVE_CSTDINT)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(strings.h HAVE_STRINGS_H)
# Check for the existence of the following functions
check_function_exists(strcasecmp HAVE_STRCASECMP)
check_function_exists(stricmp HAVE_STRICMP)
check_function_exists(umask HAVE_UMASK)
check_function_exists(epoll_wait HAVE_EPOLL)
check_function_exists(poll HAVE_POLL)
check_function_exists(kqueue HAVE_KQUEUE)
# Strip the leading and trailing spaces from the compile flags
if(CXXFLAGS)
strip_string(${CXXFLAGS} CXXFLAGS)
endif(CXXFLAGS)
# Strip the leading and trailing spaces from the linker flags
if(LDFLAGS)
strip_string(${LDFLAGS} LDFLAGS)
endif(LDFLAGS)
# Search for the following programs
find_program(GREP grep)
find_program(SH sh)
find_program(CHGRP chgrp)
find_program(CHMOD chmod)
# If a INSTDIR was passed in to CMake, use it as the install prefix, otherwise set the default install prefix to the services directory under the user's home directory
if(INSTDIR)
set(CMAKE_INSTALL_PREFIX "${INSTDIR}")
elseif(NOT CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/services")
endif(INSTDIR)
# Set default paths for various directories if not already defined
if(NOT BIN_DIR)
set(BIN_DIR "bin")
endif(NOT BIN_DIR)
if(NOT DB_DIR)
set(DB_DIR "data")
endif(NOT DB_DIR)
if(NOT DOC_DIR)
set(DOC_DIR "doc")
endif(NOT DOC_DIR)
if(NOT CONF_DIR)
set(CONF_DIR "conf")
endif(NOT CONF_DIR)
if(NOT LIB_DIR)
set(LIB_DIR "lib")
endif(NOT LIB_DIR)
if(NOT LOCALE_DIR)
set(LOCALE_DIR "locale")
endif(NOT LOCALE_DIR)
if(NOT LOGS_DIR)
set(LOGS_DIR "logs")
endif(NOT LOGS_DIR)
# Version number processing
# Find all lines in src/version.sh that start with VERSION_
read_from_file(${Anope_SOURCE_DIR}/src/version.sh "^VERSION_" VERSIONS)
# Iterate through the strings found
foreach(VERSION_STR ${VERSIONS})
string(REGEX REPLACE "^VERSION_([A-Z]+)=\"?([^\"]*)\"?$" "\\1;\\2" VERSION_OUT ${VERSION_STR})
# Depends on CMP0007 OLD
list(LENGTH VERSION_OUT VERSION_LEN)
list(GET VERSION_OUT 0 VERSION_TYPE)
if(${VERSION_LEN} GREATER 1)
list(GET VERSION_OUT 1 VERSION_DATA)
set(VERSION_${VERSION_TYPE} ${VERSION_DATA})
endif(${VERSION_LEN} GREATER 1)
endforeach(VERSION_STR ${VERSIONS})
# Default build version to 0
set(VERSION_BUILD 0)
# Only change the build number if version.h exists
if(EXISTS "${Anope_SOURCE_DIR}/include/version.h")
# Attempt to read the build number from include/version.h
read_from_file(${Anope_SOURCE_DIR}/include/version.h "^#define VERSION_BUILD" VERSIONS)
foreach(VERSION_STR ${VERSIONS})
# Get the length of the string
string(LENGTH ${VERSION_STR} VERSION_LEN)
# Subtract 22 from the string's length
math(EXPR VERSION_NUM_LEN "${VERSION_LEN} - 22")
# Extract the value from the string
string(SUBSTRING ${VERSION_STR} 22 ${VERSION_NUM_LEN} VERSION)
# Set VERSION_BUILD correctly
set(VERSION_BUILD ${VERSION})
endforeach(VERSION_STR ${VERSIONS})
endif(EXISTS "${Anope_SOURCE_DIR}/include/version.h")
# Set the version variables based on what was found above
set(VERSION_COMMA "${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_BUILD}")
set(VERSION_DOTTED_NOBUILD "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
set(VERSION_DOTTED "${VERSION_DOTTED_NOBUILD}.${VERSION_BUILD}")
set(VERSION_FULL "${VERSION_DOTTED}${VERSION_EXTRA}")
set(VERSION_FULL_NOBUILD "${VERSION_DOTTED_NOBUILD}${VERSION_EXTRA}")
# Only do the following for Windows
if(WIN32)
# Generate the win32.rc file using the above variables
configure_file(${Anope_SOURCE_DIR}/src/win32/win32.rc.cmake ${Anope_BINARY_DIR}/src/win32/win32.rc)
endif(WIN32)
# Add the initial files to ignore which will be ignored regardless of if you are building in-source or out-of-source
add_to_cpack_ignored_files(".git\;config.cache\;CMakeFiles\;sysconf.h$\;build" TRUE)
# Add the files we don't want the periods converted for
add_to_cpack_ignored_files(".\\\\\\\\.so$;.\\\\\\\\.o$;.\\\\\\\\.s$;${Anope_SOURCE_DIR}/Makefile$")
# If the two directories are the same, we are building in-source, thus we need to ignore more files from the build
if(${Anope_SOURCE_DIR} STREQUAL ${Anope_BINARY_DIR})
# Add the files that need their periods converted
add_to_cpack_ignored_files("Makefile\;cmake_install.cmake\;sysconf.h$\;CMakeCache.txt\;install_manifest.txt" TRUE)
# Add the files we don't want the periods converted for
add_to_cpack_ignored_files(".\\\\\\\\.so$;CPack.;anope-${VERSION_FULL_NOBUILD}-source\\\\\\\\..")
# If using Visual Studio, add these files as well
if(MSVC)
add_to_cpack_ignored_files(".vcproj$\;.sln$\;.ncb$\;.suo$\;.dir$\;.ilk$\;.exp$\;.pdb$\;.lib$\;/debug$;/release$;/relwithdebinfo$;/minsizerel$" TRUE)
endif(MSVC)
endif(${Anope_SOURCE_DIR} STREQUAL ${Anope_BINARY_DIR})
# Go into the following directories and run their CMakeLists.txt as well
add_subdirectory(data)
add_subdirectory(docs)
add_subdirectory(language)
add_subdirectory(src)
add_subdirectory(modules)
add_subdirectory(include)
# Get the filename of the Anope binary, to use later
get_target_property(SERVICES_BINARY ${PROGRAM_NAME} LOCATION)
get_filename_component(SERVICES_BINARY ${SERVICES_BINARY} NAME)
# At install time, create the following additional directories
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/backups\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${LOGS_DIR}\")")
if(WIN32)
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/runtime\")")
endif(WIN32)
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the below directories, as well as the group of the data directory
if(NOT WIN32 AND RUNGROUP)
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DB_DIR}/backups\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${LOGS_DIR}\")")
install(CODE "execute_process(COMMAND ${CHGRP} -R ${RUNGROUP} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}\")")
endif(NOT WIN32 AND RUNGROUP)
# On Windows platforms, install extra files
if(WIN32)
install(FILES ${Anope_SOURCE_DIR}/src/win32/anope.bat
DESTINATION ${BIN_DIR}
)
# Package any DLLs in src/win/
file(GLOB EXTRA_DLLS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${Anope_SOURCE_DIR}/src/win32/*.dll")
install(FILES ${EXTRA_DLLS} DESTINATION ${BIN_DIR})
endif(WIN32)
install(CODE "file(REMOVE_RECURSE \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/modules\")")
# Only process the CPack section if we have CPack
if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
# Various options for CPack
set(CPACK_PACKAGE_NAME "Anope IRC Services")
set(CPACK_PACKAGE_VENDOR "Anope Team")
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}${VERSION_EXTRA}")
set(CPACK_PACKAGE_FILE_NAME "anope-${VERSION_FULL_NOBUILD}")
set(CPACK_RESOURCE_FILE_LICENSE "${Anope_SOURCE_DIR}/docs/COPYING")
# The following doesn't actually do anything. :(
#set(CPACK_RESOURCE_FILE_README "${Anope_SOURCE_DIR}/docs/README")
# The following is primarily for NSIS
if(WIN32)
# By default, do not warn when built on machines using only VS Express:
IF(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS)
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON)
ENDIF(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS)
# Also for Windows, include installing the MSVCRT library
include(InstallRequiredSystemLibraries)
set(CPACK_GENERATOR "NSIS")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Anope")
set(CPACK_PACKAGE_EXECUTABLES "")
set(CPACK_NSIS_MENU_LINKS
"bin\\\\${SERVICES_BINARY}" "Anope IRC Services"
"bin\\\\anope.bat\\\" \\\"-debug -nofork" "Anope IRC Services (Debug and Window Logging)"
"bin\\\\anope.bat\\\" \\\"-nofork" "Anope IRC Services (Window Logging)"
"bin\\\\anope.bat\\\" \\\"-nothird" "Anope IRC Services (No Third Party Modules)"
"https://www.anope.org/" "Anope Web Site"
)
# The following doesn't work, but a bug report has been filed about it
#set(CPACK_CREATE_DESKTOP_LINK_${SERVICES_BINARY} TRUE)
set(CPACK_NSIS_MUI_ICON "${Anope_SOURCE_DIR}/src\\\\win32\\\\anope-icon.ico")
set(CPACK_NSIS_MUI_UNIICON "${Anope_SOURCE_DIR}/src\\\\win32\\\\anope-icon.ico")
set(CPACK_NSIS_INSTALLED_ICON_NAME "${SERVICES_BINARY}")
set(CPACK_NSIS_URL_INFO_ABOUT "https://www.anope.org/")
set(CPACK_NSIS_COMPRESSOR "/SOLID lzma")
endif(WIN32)
set(CPACK_SOURCE_PACKAGE_FILE_NAME "anope-${VERSION_FULL_NOBUILD}-source")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "$ENV{CPACK_IGNORED_FILES}")
set(CPACK_MONOLITHIC_INSTALL TRUE)
include(CPack)
endif(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")

417
Config Executable file
View File

@ -0,0 +1,417 @@
#!/bin/sh
#
# Configuration script for Services.
#
# Anope (C) 2003-2022 Anope Team
# Contact us at team@anope.org
#
# This program is free but copyrighted software; see the file COPYING for
# details.
#
# Based on the original code of Epona by PegSoft.
# Based on the original code of Services by Andy Church.
#
###########################################################################
echo2 () {
$ECHO2 "$*$ECHO2SUF" # these are defined later
}
exists () { # because some shells don't have test -e
if [ -f $1 -o -d $1 -o -p $1 -o -c $1 -o -b $1 ] ; then
return 0
else
return 1
fi
}
Load_Cache () {
if [ -f $SOURCE_DIR/config.cache -a -r $SOURCE_DIR/config.cache -a ! "$IGNORE_CACHE" ] ; then
echo "Using defaults from config.cache. To ignore, $SOURCE_DIR/Config -nocache"
echo ""
. $SOURCE_DIR/config.cache
CAN_QUICK="yes"
else
CAN_QUICK="no"
fi
}
Run_Build_System () {
WITH_INST=""
WITH_RUN=""
WITH_PERM=""
EXTRA_INCLUDE=""
EXTRA_LIBS=""
GEN_TYPE=""
if [ "$INSTDIR" != "" ] ; then
WITH_INST="-DINSTDIR:STRING=$INSTDIR"
fi
if [ "$RUNGROUP" != "" ] ; then
WITH_RUN="-DRUNGROUP:STRING=$RUNGROUP"
fi
if [ "$UMASK" != "" ] ; then
WITH_PERM="-DDEFUMASK:STRING=$UMASK"
fi
if [ "$DEBUG" = "yes" ] ; then
BUILD_TYPE="-DCMAKE_BUILD_TYPE:STRING=DEBUG"
else
BUILD_TYPE="-DCMAKE_BUILD_TYPE:STRING=RELEASE"
fi
if [ "$USE_PCH" = "yes" ] ; then
PCH="-DUSE_PCH:BOOLEAN=ON"
else
PCH="-DUSE_PCH:BOOLEAN=OFF"
fi
if [ "$EXTRA_INCLUDE_DIRS" != "" ] ; then
EXTRA_INCLUDE="-DEXTRA_INCLUDE:STRING=$EXTRA_INCLUDE_DIRS"
fi
if [ "$EXTRA_LIB_DIRS" != "" ] ; then
EXTRA_LIBS="-DEXTRA_LIBS:STRING=$EXTRA_LIB_DIRS"
fi
case `uname -s` in
MINGW*)
GEN_TYPE="-G\"MSYS Makefiles\""
;;
esac
if [ "$SOURCE_DIR" = "." ] ; then
pwdsave=`pwd`
test -d build || mkdir build
cd "build"
REAL_SOURCE_DIR=".."
else
REAL_SOURCE_DIR="$SOURCE_DIR"
fi
echo "cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $PCH $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $REAL_SOURCE_DIR"
cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $PCH $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $REAL_SOURCE_DIR
if [ $? -ne 0 ]; then
echo "You should fix these issues and then run ./Config -quick to rerun CMake."
exit 1
fi
echo ""
if [ "$SOURCE_DIR" = "." ] ; then
echo "Now cd build, then run make to build Anope."
cd "$pwdsave"
else
echo "Now run make to build Anope."
fi
}
ECHO2SUF=''
if [ "`echo -n a ; echo -n b`" = "ab" ] ; then
ECHO2='echo -n'
elif [ "`echo 'a\c' ; echo 'b\c'`" = "ab" ] ; then
ECHO2='echo' ; ECHO2SUF='\c'
elif [ "`printf 'a' 2>&1 ; printf 'b' 2>&1`" = "ab" ] ; then
ECHO2='printf "%s"'
else
# oh well...
ECHO2='echo'
fi
export ECHO2 ECHO2SUF
###########################################################################
# Init values
###########################################################################
INSTDIR=$HOME/services
RUNGROUP=
UMASK=
DEBUG="no"
USE_PCH="no"
EXTRA_INCLUDE_DIRS=
EXTRA_LIB_DIRS=
EXTRA_CONFIG_ARGS=
CAN_QUICK="no"
SOURCE_DIR=`dirname $0`
###########################################################################
# Check out the options
###########################################################################
while [ $# -ge 1 ] ; do
if [ $1 = "--help" ] ; then
echo "Config utility for Anope"
echo "------------------------"
echo "Syntax: ./Config [options]"
echo "-nocache Ignore settings saved in config.cache"
echo "-nointro Skip intro (disclaimer, etc)"
echo "-quick Skip questions, go straight to cmake"
exit 0
elif [ $1 = "-devel" ] ; then
DEBUG="yes"
INSTDIR="$PWD/run"
elif [ $1 = "-nocache" ] ; then
IGNORE_CACHE="1"
elif [ $1 = "-nointro" ] ; then
NO_INTRO="1"
elif [ $1 = "-quick" -o $1 = "-q" ] ; then
Load_Cache
if [ "$CAN_QUICK" = "yes" ] ; then
Run_Build_System
else
echo ""
echo "Can't find cache file (config.cache), aborting..."
fi
exit 0
fi
shift 1
done
###########################################################################
# Check for CMake and (optionally) install it
###########################################################################
cmake --version 2>&1 > /dev/null
if [ $? -ne 0 ] ; then
clear
echo "Anope requires CMake 2.4 or newer, which can be downloaded at https://cmake.org/ or through your system's package manager."
echo "If you have installed CMake already, ensure it is in your PATH environment variable."
exit 0
fi
###########################################################################
if [ ! "$NO_INTRO" ] ; then
case `uname -s` in
MINGW*)
PAGER=less
;;
*)
PAGER=more
clear
;;
esac
. $SOURCE_DIR/src/version.sh
cat $SOURCE_DIR/.BANNER | sed "s/CURVER/$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH$VERSION_EXTRA/" | sed "s@SOURCE_DIR@$SOURCE_DIR@" | $PAGER
echo ""
else
echo ""
fi
echo "Beginning Services configuration."
echo ""
###########################################################################
# Load the cache
###########################################################################
if [ ! "$IGNORE_CACHE" ] ; then
Load_Cache
fi
# Ask the user anything we need to know ahead of time.
export ok INPUT
####
ok=0
echo "In what directory should Anope be installed?"
while [ $ok -eq 0 ] ; do
echo2 "[$INSTDIR] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ ! "$INPUT" ] ; then
INPUT=$INSTDIR
fi
if [ ! -d "$INPUT" ] ; then
if exists "$INPUT" ; then
echo "$INPUT exists, but is not a directory!"
else
echo "$INPUT does not exist. Create it?"
echo2 "[y] "
read YN
if [ "$YN" != "n" ] ; then
if mkdir -p $INPUT ; then
ok=1
fi
fi
fi
elif exists "$INPUT/include/services.h" ; then
echo "You cannot use the Services source directory as a target directory."
else
ok=1
fi
done
INSTDIR=$INPUT
echo ""
####
OLD_RUNGROUP="$RUNGROUP"
if [ "$RUNGROUP" ] ; then
echo "Which group should all Services data files be owned by? (If Services"
echo "should not force files to be owned by a particular group, type \"none\""
echo "(without the quotes) and press Return.)"
else
echo "Which group should all Services data files be owned by? (If Services"
echo "should not force files to be owned by a particular group, just press"
echo "Return.)"
fi
echo2 "[$RUNGROUP] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "none" ] ; then
RUNGROUP=""
else
RUNGROUP="$INPUT"
fi
fi
echo ""
####
if [ ! "$UMASK" -o "$RUNGROUP" != "$OLD_RUNGROUP" ] ; then
if [ "$RUNGROUP" ] ; then
UMASK=007
else
UMASK=077
fi
fi
ok=0
echo "What should the default umask for data files be (in octal)?"
echo "(077 = only accessible by owner; 007 = accessible by owner and group)"
while [ $ok -eq 0 ] ; do
echo2 "[$UMASK] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ ! "$INPUT" ] ; then
INPUT=$UMASK
fi
if [ `echo "$INPUT" | grep -c '[^0-7]'` -gt 0 ] ; then
echo "$UMASK is not a valid octal number!"
else
if [ "`echo $INPUT | cut -c1`" != "0" ] ; then
INPUT=0$INPUT
fi
ok=1
fi
done
UMASK=$INPUT
echo ""
####
TEMP_YN="n"
if [ "$DEBUG" = "yes" ] ; then
TEMP_YN="y"
fi
echo "Would you like to build a debug version of Anope?"
echo2 "[$TEMP_YN] "
read YN
if [ "$YN" ] ; then
if [ "$YN" = "y" ] ; then
DEBUG="yes"
else
DEBUG="no"
fi
fi
echo ""
####
TEMP_YN="n"
if [ "$USE_PCH" = "yes" ] ; then
TEMP_YN="y"
fi
echo "Do you want to build using precompiled headers? This can speed up"
echo "the build, but uses more disk space."
echo2 "[$TEMP_YN] "
read YN
if [ "$YN" ] ; then
if [ "$YN" = "y" ] ; then
USE_PCH="yes"
else
USE_PCH="no"
fi
fi
echo ""
####
echo "Are there any extra include directories you wish to use?"
echo "You may only need to do this if CMake is unable to locate"
echo "missing dependencies without hints."
echo "Separate directories with semicolons."
echo "If you need no extra include directories, enter NONE in all caps."
echo2 "[$EXTRA_INCLUDE_DIRS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
EXTRA_INCLUDE_DIRS=""
else
EXTRA_INCLUDE_DIRS=$INPUT
fi
fi
echo ""
####
echo "Are there any extra library directories you wish to use?"
echo "You may only need to do this if CMake is unable to locate"
echo "missing dependencies without hints."
echo "Separate directories with semicolons."
echo "If you need no extra library directories, enter NONE in all caps."
echo2 "[$EXTRA_LIB_DIRS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
EXTRA_LIB_DIRS=""
else
EXTRA_LIB_DIRS=$INPUT
fi
fi
echo ""
####
echo "Are there any extra arguments you wish to pass to CMake?"
echo "If you need no extra arguments to CMake, enter NONE in all caps."
echo2 "[$EXTRA_CONFIG_ARGS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
EXTRA_CONFIG_ARGS=""
else
EXTRA_CONFIG_ARGS=$INPUT
fi
fi
echo ""
####
################################################################################
# Store values
################################################################################
echo2 "Saving configuration results in config.cache... "
cat <<EOT >$SOURCE_DIR/config.cache
INSTDIR="$INSTDIR"
RUNGROUP="$RUNGROUP"
UMASK=$UMASK
DEBUG="$DEBUG"
USE_PCH="$USE_PCH"
EXTRA_INCLUDE_DIRS="$EXTRA_INCLUDE_DIRS"
EXTRA_LIB_DIRS="$EXTRA_LIB_DIRS"
EXTRA_CONFIG_ARGS="$EXTRA_CONFIG_ARGS"
EOT
echo "done."
################################################################################
# Build the build system string
################################################################################
Run_Build_System

BIN
Config.exe Normal file

Binary file not shown.

46
README.md Normal file
View File

@ -0,0 +1,46 @@
## About
Anope is an open source set of IRC Services. It is highly modular, with a vast number of configurable parameters, and is the most used IRC services package. There are also many modules on the [modsite](https://modules.anope.org) to add additional features. It runs on Linux, BSD, and Windows, and supports many modern IRCds, including InspIRCd, UnrealIRCd, and ircd-hybrid. For more details, credits, command line options, and contact information see [docs/README](https://github.com/anope/anope/blob/2.0/docs/README).
* [Website](https://anope.org)
* [GitHub](https://github.com/anope)
* IRC \#anope on irc.anope.org
## Installation
### Linux/BSD
Download the latest release off of the [releases page](https://github.com/anope/anope/releases).
```
$ ./Config
$ cd build
$ make
$ make install
```
Now change to the directory where you installed Anope to, e.g. `$ cd ~/services/`
### Windows
Download the latest release off of the [releases page](https://github.com/anope/anope/releases) and run the installer.
## Configuration
Copy conf/example.conf to conf/services.conf
```
$ cp conf/example.conf conf/services.conf
```
Edit services.conf, configuring the uplink, serverinfo, and protocol module configurations. Example link blocks for popular IRCds are included in the the example.conf documentation. The [Anope wiki](https://wiki.anope.org) is also a good source of information. Our support channel is located at #anope on [irc.anope.org](irc://irc.anope.org/#anope).
Note that the example configuration file includes other example configuration files. If you want to modify the other example configuration files, copy them (e.g. `modules.example.conf` to `modules.conf`) and modify the `include` directive in `services.conf` to include the new file.
## Running
Run `$ ./bin/services` to start Anope. If asked to provide logs for support, use the `--support` flag, e.g.: `$ ./bin/services --support`
## Installing extra modules
Extra modules, which are usually modules which require extra libraries to use, such as m\_mysql, can be enabled with the `./extras` command from the source directory. Then re-run `Config`, `make` and `make install` again. Third party modules can be installed by placing them into the `modules/third` directory.

555
cmake/Anope.cmake Normal file
View File

@ -0,0 +1,555 @@
###############################################################################
# strip_string(<input string> <output string>)
#
# A macro to handle stripping the leading and trailing spaces from a string,
# uses string(STRIP) if using CMake 2.6.x or better, otherwise uses
# string(REGEX REPLACE).
###############################################################################
macro(strip_string INPUT_STRING OUTPUT_STRING)
if(CMAKE26_OR_BETTER)
# For CMake 2.6.x or better, we can just use the STRIP sub-command of string()
string(STRIP ${INPUT_STRING} ${OUTPUT_STRING})
else(CMAKE26_OR_BETTER)
# For CMake 2.4.x, we will have to use the REGEX REPLACE sub-command of string() instead
# First check if the input string is empty or not
if (${INPUT_STRING} STREQUAL "")
set(${OUTPUT_STRING} "")
else(${INPUT_STRING} STREQUAL "")
# Determine if the string is entirely empty or not
string(REGEX MATCH "^[ \t]*$" EMPTY_STRING "${INPUT_STRING}")
if(EMPTY_STRING)
set(${OUTPUT_STRING} "")
else(EMPTY_STRING)
# We detect if there is any leading whitespace and remove any if there is
string(SUBSTRING "${INPUT_STRING}" 0 1 FIRST_CHAR)
if(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t")
string(REGEX REPLACE "^[ \t]+" "" TEMP_STRING "${INPUT_STRING}")
else(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t")
set(TEMP_STRING "${INPUT_STRING}")
endif(FIRST_CHAR STREQUAL " " OR FIRST_CHAR STREQUAL "\t")
# Next we detect if there is any trailing whitespace and remove any if there is
string(LENGTH "${TEMP_STRING}" STRING_LEN)
math(EXPR STRING_LEN "${STRING_LEN} - 1")
string(SUBSTRING "${TEMP_STRING}" ${STRING_LEN} 1 LAST_CHAR)
if(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t")
string(REGEX REPLACE "[ \t]+$" "" ${OUTPUT_STRING} "${TEMP_STRING}")
else(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t")
set(${OUTPUT_STRING} "${TEMP_STRING}")
endif(LAST_CHAR STREQUAL " " OR LAST_CHAR STREQUAL "\t")
endif(EMPTY_STRING)
endif(${INPUT_STRING} STREQUAL "")
endif(CMAKE26_OR_BETTER)
endmacro(strip_string)
###############################################################################
# append_to_list(<list> <args>...)
#
# A macro to handle appending to lists, uses list(APPEND) if using CMake 2.4.2
# or better, otherwise uses set() instead.
###############################################################################
macro(append_to_list LIST)
if(CMAKE242_OR_BETTER)
# For CMake 2.4.2 or better, we can just use the APPEND sub-command of list()
list(APPEND ${LIST} ${ARGN})
else(CMAKE242_OR_BETTER)
# For CMake 2.4.x before 2.4.2, we have to do this manually use set() instead
set(${LIST} ${${LIST}} ${ARGN})
endif(CMAKE242_OR_BETTER)
endmacro(append_to_list)
###############################################################################
# find_in_list(<list> <value> <output variable>)
#
# A macro to handle searching within a list, will store the result in the
# given <output variable>, uses list(FIND) if using CMake 2.6.x or better
# (or CMake 2.4.8 or better), otherwise it iterates through the list to find
# the item.
###############################################################################
macro(find_in_list LIST ITEM_TO_FIND FOUND)
if(CMAKE248_OR_BETTER)
# For CMake 2.4.8 or better, we can use the FIND sub-command of list()
list(FIND ${LIST} ${ITEM_TO_FIND} ITEM_FOUND)
else(CMAKE248_OR_BETTER)
# For CMake 2.4.x before 2.4.8, we have to do this ourselves (NOTE: This is very slow due to a lack of break() as well)
# Firstly we set the position to -1 indicating nothing found, we also use a temporary position
set(ITEM_FOUND -1)
set(POS 0)
# Iterate through the list
foreach(ITEM ${${LIST}})
# If the item we are looking at is the item we are trying to find, set that we've found the item
if(${ITEM} STREQUAL ${ITEM_TO_FIND})
set(ITEM_FOUND ${POS})
endif(${ITEM} STREQUAL ${ITEM_TO_FIND})
# Increase the position value by 1
math(EXPR POS "${POS} + 1")
endforeach(ITEM)
endif(CMAKE248_OR_BETTER)
# Set the given FOUND variable to the result
set(${FOUND} ${ITEM_FOUND})
endmacro(find_in_list)
###############################################################################
# remove_list_duplicates(<list>)
#
# A macro to handle removing duplicates from a list, uses
# list(REMOVE_DUPLICATES) if using CMake 2.6.x or better, otherwise it uses
# a slower method of creating a temporary list and only adding to it when
# a duplicate item hasn't been found.
###############################################################################
macro(remove_list_duplicates LIST)
if(CMAKE26_OR_BETTER)
# For CMake 2.6.x or better, this can be done automatically
list(REMOVE_DUPLICATES ${LIST})
else(CMAKE26_OR_BETTER)
# For CMake 2.4.x, we have to do this ourselves, firstly we'll clear a temporary list
set(NEW_LIST)
# Iterate through the old list
foreach(ITEM ${${LIST}})
# Check if the item is in the new list
find_in_list(NEW_LIST ${ITEM} FOUND_ITEM)
if(FOUND_ITEM EQUAL -1)
# If the item was not found, append it to the list
append_to_list(NEW_LIST ${ITEM})
endif(FOUND_ITEM EQUAL -1)
endforeach(ITEM)
# Replace the old list with the new list
set(${LIST} ${NEW_LIST})
endif(CMAKE26_OR_BETTER)
endmacro(remove_list_duplicates)
###############################################################################
# remove_item_from_list(<list> <value>)
#
# A macro to handle removing a value from a list, uses list(REMOVE_ITEM) in
# both cases, but can remove the value itself using CMake 2.4.2 or better,
# while older versions use a slower method of iterating the list to find the
# index of the value to remove.
###############################################################################
macro(remove_item_from_list LIST VALUE)
if(CMAKE242_OR_BETTER)
# For CMake 2.4.2 or better, this can be done automatically
list(REMOVE_ITEM ${LIST} ${VALUE})
else(CMAKE242_OR_BETTER)
# For CMake 2.4.x before 2.4.2, we have to do this ourselves, firstly we set the index and a variable to indicate if the item was found
set(INDEX 0)
set(FOUND FALSE)
# Iterate through the old list
foreach(ITEM ${${LIST}})
# If the item hasn't been found yet, but the current item is the same, remove it
if(NOT FOUND)
if(ITEM STREQUAL ${VALUE})
set(FOUND TRUE)
list(REMOVE_ITEM ${LIST} ${INDEX})
endif(ITEM STREQUAL ${VALUE})
endif(NOT FOUND)
# Increase the index value by 1
math(EXPR INDEX "${INDEX} + 1")
endforeach(ITEM)
endif(CMAKE242_OR_BETTER)
endmacro(remove_item_from_list)
###############################################################################
# sort_list(<list>)
#
# A macro to handle sorting a list, uses list(SORT) if using CMake 2.4.4 or
# better, otherwise it uses a slower method of creating a temporary list and
# adding elements in alphabetical order.
###############################################################################
macro(sort_list LIST)
if(CMAKE244_OR_BETTER)
# For CMake 2.4.4 or better, this can be done automatically
list(SORT ${LIST})
else(CMAKE244_OR_BETTER)
# For CMake 2.4.x before 2.4.4, we have to do this ourselves, firstly we'll create a temporary list
set(NEW_LIST)
# Iterate through the old list
foreach(ITEM ${${LIST}})
# Temporary index position for the new list, as well as temporary value to store if the item was ever found
set(INDEX 0)
set(FOUND FALSE)
# Iterate through the new list
foreach(NEW_ITEM ${NEW_LIST})
# Compare the items, only if nothing was found before
if(NOT FOUND)
if(NEW_ITEM STRGREATER "${ITEM}")
set(FOUND TRUE)
list(INSERT NEW_LIST ${INDEX} ${ITEM})
endif(NEW_ITEM STRGREATER "${ITEM}")
endif(NOT FOUND)
# Increase the index value by 1
math(EXPR INDEX "${INDEX} + 1")
endforeach(NEW_ITEM)
# If the item was never found, just append it to the end
if(NOT FOUND)
append_to_list(NEW_LIST ${ITEM})
endif(NOT FOUND)
endforeach(ITEM)
# Replace the old list with the new list
set(${LIST} ${NEW_LIST})
endif(CMAKE244_OR_BETTER)
endmacro(sort_list)
###############################################################################
# read_from_file(<filename> <regex> <output variable>)
#
# A macro to handle reading specific lines from a file, uses file(STRINGS) if
# using CMake 2.6.x or better, otherwise we read in the entire file and
# perform a string(REGEX MATCH) on each line of the file instead. This
# macro can also be used to read in all the lines of a file if REGEX is set
# to "".
###############################################################################
macro(read_from_file FILE REGEX STRINGS)
if(CMAKE26_OR_BETTER)
# For CMake 2.6.x or better, we can just use the STRINGS sub-command to get the lines that match the given regular expression (if one is given, otherwise get all lines)
if(REGEX STREQUAL "")
file(STRINGS ${FILE} RESULT)
else(REGEX STREQUAL "")
file(STRINGS ${FILE} RESULT REGEX ${REGEX})
endif(REGEX STREQUAL "")
else(CMAKE26_OR_BETTER)
# For CMake 2.4.x, we need to do this manually, firstly we read the file in
execute_process(COMMAND ${CMAKE_COMMAND} -DFILE:STRING=${FILE} -P ${Anope_SOURCE_DIR}/cmake/ReadFile.cmake ERROR_VARIABLE ALL_STRINGS)
# Next we replace all newlines with semicolons
string(REGEX REPLACE "\n" ";" ALL_STRINGS ${ALL_STRINGS})
if(REGEX STREQUAL "")
# For no regular expression, just set the result to all the lines
set(RESULT ${ALL_STRINGS})
else(REGEX STREQUAL "")
# Clear the result list
set(RESULT)
# Iterate through all the lines of the file
foreach(STRING ${ALL_STRINGS})
# Check for a match against the given regular expression
string(REGEX MATCH ${REGEX} STRING_MATCH ${STRING})
# If we had a match, append the match to the list
if(STRING_MATCH)
append_to_list(RESULT ${STRING})
endif(STRING_MATCH)
endforeach(STRING)
endif(REGEX STREQUAL "")
endif(CMAKE26_OR_BETTER)
# Set the given STRINGS variable to the result
set(${STRINGS} ${RESULT})
endmacro(read_from_file)
###############################################################################
# extract_include_filename(<line> <output variable> [<optional output variable of quote type>])
#
# This macro will take a #include line and extract the filename.
###############################################################################
macro(extract_include_filename INCLUDE FILENAME)
# Strip the leading and trailing spaces from the include line
strip_string(${INCLUDE} INCLUDE_STRIPPED)
# Make sure to only do the following if there is a string
if(INCLUDE_STRIPPED STREQUAL "")
set(FILE "")
else(INCLUDE_STRIPPED STREQUAL "")
# Extract the filename including the quotes or angle brackets
string(REGEX REPLACE "^.*([\"<].*[\">]).*$" "\\1" FILE "${INCLUDE_STRIPPED}")
# If an optional 3rd argument is given, we'll store if the quote style was quoted or angle bracketed
if(${ARGC} GREATER 2)
string(SUBSTRING ${FILE} 0 1 QUOTE)
if(QUOTE STREQUAL "<")
set(${ARGV2} "angle brackets")
else(QUOTE STREQUAL "<")
set(${ARGV2} "quotes")
endif(QUOTE STREQUAL "<")
endif(${ARGC} GREATER 2)
# Now remove the quotes or angle brackets
string(REGEX REPLACE "^[\"<](.*)[\">]$" "\\1" FILE "${FILE}")
endif(INCLUDE_STRIPPED STREQUAL "")
# Set the filename to the the given variable
set(${FILENAME} "${FILE}")
endmacro(extract_include_filename)
###############################################################################
# find_includes(<source filename> <output variable>)
#
# This macro will search through a file for #include lines, regardless of
# whitespace, but only returns the lines that are valid for the current
# platform CMake is running on.
###############################################################################
macro(find_includes SRC INCLUDES)
# Read all lines from the file that start with #, regardless of whitespace before the #
read_from_file(${SRC} "^[ \t]*#.*$" LINES)
# Set that any #include lines found are valid, and create temporary variables for the last found #ifdef/#ifndef
set(VALID_LINE TRUE)
set(LAST_DEF)
set(LAST_CHECK)
# Create an empty include list
set(INCLUDES_LIST)
# Iterate through all the # lines
foreach(LINE ${LINES})
# Search for #ifdef, #ifndef, #else, #endif, and #include
string(REGEX MATCH "^[ \t]*#[ \t]*ifdef[ \t]*.*$" FOUND_IFDEF ${LINE})
string(REGEX MATCH "^[ \t]*#[ \t]*ifndef[ \t]*.*$" FOUND_IFNDEF ${LINE})
string(REGEX MATCH "^[ \t]*#[ \t]*else.*$" FOUND_ELSE ${LINE})
string(REGEX MATCH "^[ \t]*#[ \t]*endif.*$" FOUND_ENDIF ${LINE})
string(REGEX MATCH "^[ \t]*#[ \t]*include[ \t]*[\"<].*[\">][\ t]*.*$" FOUND_INCLUDE ${LINE})
# If we found a #ifdef on the line, extract the data after the #ifdef and set if the lines after it are valid based on the variables in CMake
if(FOUND_IFDEF)
# Extract the define
string(REGEX REPLACE "^[ \t]*#[ \t]*ifdef[ \t]*(.*)$" "\\1" DEFINE ${LINE})
# Replace _WIN32 with WIN32, so we can check if the WIN32 variable of CMake is set instead of _WIN32
if(DEFINE STREQUAL "_WIN32")
set(DEFINE WIN32)
endif(DEFINE STREQUAL "_WIN32")
# Set the last define to this one, and set the last check to true, so when #else is encountered, we can do an opposing check
set(LAST_DEF ${DEFINE})
set(LAST_CHECK TRUE)
# If the define is true (it either exists or is a non-false result), the lines following will be checked, otherwise they will be skipped
if(${DEFINE})
set(VALID_LINE TRUE)
else(${DEFINE})
set(VALID_LINE FALSE)
endif(${DEFINE})
else(FOUND_IFDEF)
# If we found a #ifndef on the line, the same thing as #ifdef is done, except with the checks in the opposite direction
if(FOUND_IFNDEF)
# Extract the define
string(REGEX REPLACE "^[ \t]*#[ \t]*ifndef[ \t]*(.*)$" "\\1" DEFINE ${LINE})
# Replace _WIN32 with WIN32, so we can check if the WIN32 variable of CMake is set instead of _WIN32
if(DEFINE STREQUAL "_WIN32")
set(DEFINE WIN32)
endif(DEFINE STREQUAL "_WIN32")
# Set the last define to this one, and set the last check to false, so when #else is encountered, we can do an opposing check
set(LAST_DEF ${DEFINE})
set(LAST_CHECK FALSE)
# If the define is not true (it either doesn't exists or is a false result), the lines following will be checked, otherwise they will be skipped
if(${DEFINE})
set(VALID_LINE FALSE)
else(${DEFINE})
set(VALUE_LINE TRUE)
endif(${DEFINE})
else(FOUND_IFNDEF)
# If we found a #else on the line, we check the last define in the opposite direction
if(FOUND_ELSE)
# When LAST_CHECK is true, we were inside a #ifdef, now act as if we are entering a #ifndef section by doing an opposing check
if(LAST_CHECK)
if(${LAST_DEF})
set(VALID_LINE FALSE)
else(${LAST_DEF})
set(VALID_LINE TRUE)
endif(${LAST_DEF})
# When LAST_CHECK is false, we were inside a #ifndef, now act as if we are entering a #ifdef section by doing an opposing check
else(LAST_CHECK)
if(${LAST_DEF})
set(VALID_LINE TRUE)
else(${LAST_DEF})
set(VALID_LINE FALSE)
endif(${LAST_DEF})
endif(LAST_CHECK)
else(FOUND_ELSE)
# If we found a #endif on the line, we'll assume everything following the line is valid until we meet another one of the above lines
if(FOUND_ENDIF)
set(VALID_LINE TRUE)
else(FOUND_ENDIF)
# If we found a #include on the line, add the entire line to the list of includes unless the line isn't valid
if(FOUND_INCLUDE)
if(VALID_LINE)
append_to_list(INCLUDES_LIST "${LINE}")
endif(VALID_LINE)
endif(FOUND_INCLUDE)
endif(FOUND_ENDIF)
endif(FOUND_ELSE)
endif(FOUND_IFNDEF)
endif(FOUND_IFDEF)
endforeach(LINE)
set(${INCLUDES} ${INCLUDES_LIST})
endmacro(find_includes)
###############################################################################
# calculate_depends(<source filename> [<optional output variable for includes>])
#
# This macro is used in most of the src (sub)directories to calculate the
# header file dependencies for the given source file.
###############################################################################
macro(calculate_depends SRC)
# Temporarily set that we didn't get a 3rd argument before we actually check if we did get one or not
set(CHECK_ANGLE_INCLUDES FALSE)
# Check for a third argument
if(${ARGC} GREATER 1)
set(CHECK_ANGLE_INCLUDES TRUE)
endif(${ARGC} GREATER 1)
# Find all the lines in the given source file that have any form of #include on them, regardless of whitespace, but only if they are valid for the platform we are on
find_includes(${SRC} INCLUDES)
# Reset the list of headers to empty
set(HEADERS)
# Iterate through the strings containing #include (if any)
foreach(INCLUDE ${INCLUDES})
# Extract the filename from the #include line
extract_include_filename(${INCLUDE} FILENAME QUOTE_TYPE)
if(QUOTE_TYPE STREQUAL "angle brackets")
# The following checks will only be done if there was a request for angle includes to be checked
if(CHECK_ANGLE_INCLUDES)
# Find the path of the include file
if(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/include $ENV{VCINSTALLDIR}/include ${EXTRA_INCLUDE})
else(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} ${EXTRA_INCLUDE})
endif(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
# If the include file was found, add it's path to the list of include paths, but only if it doesn't already exist and isn't in the defaults for the compiler
if(FOUND_${FILENAME}_INCLUDE)
# This used to be find_in_list, but it was changed to this loop to do a find on each default include directory, this fixes Mac OS X trying to get it's framework directories in here
set(FOUND_IN_DEFAULTS -1)
foreach(DEFAULT_INCLUDE_DIR ${DEFAULT_INCLUDE_DIRS})
string(REGEX REPLACE "\\+" "\\\\+" DEFAULT_INCLUDE_DIR ${DEFAULT_INCLUDE_DIR})
string(REGEX MATCH ${DEFAULT_INCLUDE_DIR} FOUND_DEFAULT ${FOUND_${FILENAME}_INCLUDE})
if(FOUND_DEFAULT)
set(FOUND_IN_DEFAULTS 0)
endif(FOUND_DEFAULT)
endforeach(DEFAULT_INCLUDE_DIR)
if(FOUND_IN_DEFAULTS EQUAL -1)
find_in_list(${ARGV1} "${FOUND_${FILENAME}_INCLUDE}" FOUND_IN_INCLUDES)
if(FOUND_IN_INCLUDES EQUAL -1)
append_to_list(${ARGV1} "${FOUND_${FILENAME}_INCLUDE}")
endif(FOUND_IN_INCLUDES EQUAL -1)
endif(FOUND_IN_DEFAULTS EQUAL -1)
else(FOUND_${FILENAME}_INCLUDE)
# XXX
if(NOT ${FILENAME} STREQUAL "libintl.h")
message(FATAL_ERROR "${SRC} needs header file ${FILENAME} but we were unable to locate that header file! Check that the header file is within the search path of your OS.")
endif(NOT ${FILENAME} STREQUAL "libintl.h")
endif(FOUND_${FILENAME}_INCLUDE)
endif(CHECK_ANGLE_INCLUDES)
endif(QUOTE_TYPE STREQUAL "angle brackets")
endforeach(INCLUDE)
endmacro(calculate_depends)
###############################################################################
# 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)
read_from_file(${SRC} "/\\\\*[ \t]*RequiredWindowsLibraries:[ \t]*.*[ \t]*\\\\*/" REQUIRED_LIBRARIES)
else(WIN32)
read_from_file(${SRC} "/\\\\*[ \t]*RequiredLibraries:[ \t]*.*[ \t]*\\\\*/" REQUIRED_LIBRARIES)
endif(WIN32)
# 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(${LIBRARY} MATCHES "^.+\\|.+$")
# Locate the library to see if it exists
if(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${LIBRARY_ALT} PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib ${EXTRA_INCLUDE} ${EXTRA_LIBS})
else(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
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(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
# 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
append_to_list(EXTRA_DEPENDENCIES "${FOUND_${LIBRARY}_LIBRARY}")
else(MSVC)
# Get the path only of the library, to add it to library paths.
get_filename_component(LIBRARY_PATH ${FOUND_${LIBRARY}_LIBRARY} PATH)
append_to_list(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})
append_to_list(LIBRARIES ${LIBRARY_NAME})
endif(MSVC)
else(FOUND_${LIBRARY}_LIBRARY)
# 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(FOUND_${LIBRARY}_LIBRARY)
endforeach(LIBRARY)
endforeach(REQUIRED_LIBRARY)
# Remove duplicates from the library paths
if(LIBRARY_PATHS)
remove_list_duplicates(LIBRARY_PATHS)
endif(LIBRARY_PATHS)
# Remove diplicates from the libraries
if(LIBRARIES)
remove_list_duplicates(LIBRARIES)
endif(LIBRARIES)
# Iterate through library paths and add them to the linker flags
foreach(LIBRARY_PATH ${LIBRARY_PATHS})
find_in_list(DEFAULT_LIBRARY_DIRS "${LIBRARY_PATH}" FOUND_IN_DEFAULTS)
if(FOUND_IN_DEFAULTS EQUAL -1)
set(THIS_LDFLAGS "${THIS_LDFLAGS} -L${LIBRARY_PATH}")
endif(FOUND_IN_DEFAULTS EQUAL -1)
endforeach(LIBRARY_PATH)
# Iterate through libraries and add them to the linker flags
foreach(LIBRARY ${LIBRARIES})
append_to_list(EXTRA_DEPENDENCIES "${LIBRARY}")
endforeach(LIBRARY)
set(${SRC_LDFLAGS} "${THIS_LDFLAGS}")
set(${EXTRA_DEPENDS} "${EXTRA_DEPENDENCIES}")
endmacro(calculate_libraries)
###############################################################################
# check_functions(<source filename> <output variable set to TRUE on success>)
#
# This macro is used in most of the module (sub)directories to calculate the
# function dependencies for the given source file.
###############################################################################
macro(check_functions SRC SUCCESS)
# Default to true
set(${SUCCESS} TRUE)
# Check to see if there are any lines matching: /* RequiredFunctions: [something] */
read_from_file(${SRC} "/\\\\*[ \t]*RequiredFunctions:[ \t]*.*[ \t]*\\\\*/" REQUIRED_FUNCTIONS)
# Iterate through those lines
foreach(REQUIRED_FUNCTION ${REQUIRED_FUNCTIONS})
# Strip off the /* RequiredFunctions: and */ from the line
string(REGEX REPLACE "/\\*[ \t]*RequiredFunctions:[ \t]*([^ \t]*)[ \t]*\\*/" "\\1" REQUIRED_FUNCTION ${REQUIRED_FUNCTION})
# Replace all commas with semicolons
string(REGEX REPLACE "," ";" REQUIRED_FUNCTION ${REQUIRED_FUNCTION})
# Iterate through the functions given
foreach(FUNCTION ${REQUIRED_FUNCTION})
# Check if the function exists
check_function_exists(${REQUIRED_FUNCTION} HAVE_${REQUIRED_FUNCTION})
# If we don't have the function warn the user and set SUCCESS to FALSE
if(NOT HAVE_${REQUIRED_FUNCTION})
message("${SRC} needs function ${REQUIRED_FUNCTION} but we were unable to locate that function!")
set(${SUCCESS} FALSE)
endif(NOT HAVE_${REQUIRED_FUNCTION})
endforeach(FUNCTION)
endforeach(REQUIRED_FUNCTION)
endmacro(check_functions)
###############################################################################
# add_to_cpack_ignored_files(<item> [TRUE])
#
# A macro to update the environment variable CPACK_IGNORED_FILES which
# contains a list of files for CPack to ignore. If the optional 2nd argument
# of TRUE is given, periods will be converted to \\. for CPack.
###############################################################################
macro(add_to_cpack_ignored_files ITEM)
# Temporary copy of the orignal item
set(REAL_ITEM "${ITEM}")
# If we have 2+ arguments, assume that the second one was something like TRUE (doesn't matter really) and convert periods so they will be \\. for CPack
if(${ARGC} GREATER 1)
string(REPLACE "." "\\\\." REAL_ITEM ${REAL_ITEM})
endif(${ARGC} GREATER 1)
# If the environment variable is already defined, just tack the item to the end
if(DEFINED ENV{CPACK_IGNORED_FILES})
set(ENV{CPACK_IGNORED_FILES} "$ENV{CPACK_IGNORED_FILES};${REAL_ITEM}")
# Otherwise set the environment variable to the item
else(DEFINED ENV{CPACK_IGNORED_FILES})
set(ENV{CPACK_IGNORED_FILES} "${REAL_ITEM}")
endif(DEFINED ENV{CPACK_IGNORED_FILES})
endmacro(add_to_cpack_ignored_files)

26
cmake/FindGettext.cmake Normal file
View File

@ -0,0 +1,26 @@
# Find the header files, libs, and executables for gettext
if(NOT WIN32)
find_path(GETTEXT_INCLUDE libintl.h /usr/include /usr/local/include ${EXTRA_INCLUDE})
find_library(GETTEXT_LIBRARY intl PATHS /usr/lib /usr/lib64 ${EXTRA_LIBS})
find_program(GETTEXT_MSGFMT msgfmt PATHS /usr/bin/ /usr/local/bin ${EXTRA_INCLUDE})
if(GETTEXT_INCLUDE AND GETTEXT_MSGFMT)
set(GETTEXT_FOUND TRUE)
if(GETTEXT_LIBRARY)
set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY})
endif(GETTEXT_LIBRARY)
endif(GETTEXT_INCLUDE AND GETTEXT_MSGFMT)
else(NOT WIN32)
find_path(GETTEXT_INCLUDE libintl.h ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/include $ENV{VCINSTALLDIR}/include gettext/include ${EXTRA_INCLUDE})
find_library(GETTEXT_LIBRARY libintl PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_LIBS})
find_program(GETTEXT_MSGFMT msgfmt PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/bin $ENV{VCINSTALLDIR}/bin gettext/bin ${EXTRA_INCLUDE})
if(GETTEXT_INCLUDE AND GETTEXT_LIBRARY AND GETTEXT_MSGFMT)
set(GETTEXT_FOUND TRUE)
set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY})
endif(GETTEXT_INCLUDE AND GETTEXT_LIBRARY AND GETTEXT_MSGFMT)
endif(NOT WIN32)
# If we found everything we need set variables correctly for lang/CMakeLists.txt to use
if(GETTEXT_FOUND)
include_directories("${GETTEXT_INCLUDE}")
set(GETTEXT_MSGFMT_EXECUTABLE ${GETTEXT_MSGFMT})
endif(GETTEXT_FOUND)

825
cmake/NSIS.template.in Normal file
View File

@ -0,0 +1,825 @@
; CPack install script designed for a nmake build
;--------------------------------
; You must define these values
!define VERSION "@CPACK_PACKAGE_VERSION@"
!define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@"
;--------------------------------
;Variables
Var MUI_TEMP
Var STARTMENU_FOLDER
Var SV_ALLUSERS
Var START_MENU
Var DO_NOT_ADD_TO_PATH
Var ADD_TO_PATH_ALL_USERS
Var ADD_TO_PATH_CURRENT_USER
Var INSTALL_DESKTOP
;--------------------------------
;Include Modern UI
!include "MUI2.nsh"
;Default installation folder
InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
;--------------------------------
;General
;Name and file
Name "@CPACK_PACKAGE_NAME@ @CPACK_PACKAGE_VERSION@"
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
;Set compression
SetCompressor @CPACK_NSIS_COMPRESSOR@
@CPACK_NSIS_DEFINES@
!include Sections.nsh
;--- Component support macros: ---
; The code for the add/remove functionality is from:
; http://nsis.sourceforge.net/Add/Remove_Functionality
; It has been modified slightly and extended to provide
; inter-component dependencies.
Var AR_SecFlags
Var AR_RegFlags
@CPACK_NSIS_SECTION_SELECTED_VARS@
; Loads the "selected" flag for the section named SecName into the
; variable VarName.
!macro LoadSectionSelectedIntoVar SecName VarName
SectionGetFlags ${${SecName}} $${VarName}
IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits
!macroend
; Loads the value of a variable... can we get around this?
!macro LoadVar VarName
IntOp $R0 0 + $${VarName}
!macroend
; Sets the value of a variable
!macro StoreVar VarName IntValue
IntOp $${VarName} 0 + ${IntValue}
!macroend
!macro InitSection SecName
; This macro reads component installed flag from the registry and
;changes checked state of the section on the components page.
;Input: section index constant name specified in Section command.
ClearErrors
;Reading component status from registry
ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" "Installed"
IfErrors "default_${SecName}"
;Status will stay default if registry value not found
;(component was never installed)
IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits
SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags
IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off
IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit
; Note whether this component was installed before
!insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags
IntOp $R0 $AR_RegFlags & $AR_RegFlags
;Writing modified flags
SectionSetFlags ${${SecName}} $AR_SecFlags
"default_${SecName}:"
!insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
!macroend
!macro FinishSection SecName
; This macro reads section flag set by user and removes the section
;if it is not selected.
;Then it writes component installed flag to registry
;Input: section index constant name specified in Section command.
SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags
;Checking lowest bit:
IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED}
IntCmp $AR_SecFlags 1 "leave_${SecName}"
;Section is not selected:
;Calling Section uninstall macro and writing zero installed flag
!insertmacro "Remove_${${SecName}}"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \
"Installed" 0
Goto "exit_${SecName}"
"leave_${SecName}:"
;Section is selected:
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@\Components\${SecName}" \
"Installed" 1
"exit_${SecName}:"
!macroend
!macro RemoveSection_CPack SecName
; This macro is used to call section's Remove_... macro
;from the uninstaller.
;Input: section index constant name specified in Section command.
!insertmacro "Remove_${${SecName}}"
!macroend
; Determine whether the selection of SecName changed
!macro MaybeSelectionChanged SecName
!insertmacro LoadVar ${SecName}_selected
SectionGetFlags ${${SecName}} $R1
IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits
; See if the status has changed:
IntCmp $R0 $R1 "${SecName}_unchanged"
!insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected
IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected"
!insertmacro "Deselect_required_by_${SecName}"
goto "${SecName}_unchanged"
"${SecName}_was_selected:"
!insertmacro "Select_${SecName}_depends"
"${SecName}_unchanged:"
!macroend
;--- End of Add/Remove macros ---
;--------------------------------
;Interface Settings
!define MUI_ABORTWARNING
;----------------------------------------
; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02"
;----------------------------------------
!verbose 3
!include "WinMessages.NSH"
!verbose 4
;====================================================
; get_NT_environment
; Returns: the selected environment
; Output : head of the stack
;====================================================
!macro select_NT_profile UN
Function ${UN}select_NT_profile
StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single
DetailPrint "Selected environment for all users"
Push "all"
Return
environment_single:
DetailPrint "Selected environment for current user only."
Push "current"
Return
FunctionEnd
!macroend
!insertmacro select_NT_profile ""
!insertmacro select_NT_profile "un."
;----------------------------------------------------
!define NT_current_env 'HKCU "Environment"'
!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
!ifndef WriteEnvStr_RegKey
!ifdef ALL_USERS
!define WriteEnvStr_RegKey \
'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
!else
!define WriteEnvStr_RegKey 'HKCU "Environment"'
!endif
!endif
; AddToPath - Adds the given dir to the search path.
; Input - head of the stack
; Note - Win9x systems requires reboot
Function AddToPath
Exch $0
Push $1
Push $2
Push $3
# don't add if the path doesn't exist
IfFileExists "$0\*.*" "" AddToPath_done
ReadEnvStr $1 PATH
Push "$1;"
Push "$0;"
Call StrStr
Pop $2
StrCmp $2 "" "" AddToPath_done
Push "$1;"
Push "$0\;"
Call StrStr
Pop $2
StrCmp $2 "" "" AddToPath_done
GetFullPathName /SHORT $3 $0
Push "$1;"
Push "$3;"
Call StrStr
Pop $2
StrCmp $2 "" "" AddToPath_done
Push "$1;"
Push "$3\;"
Call StrStr
Pop $2
StrCmp $2 "" "" AddToPath_done
Call IsNT
Pop $1
StrCmp $1 1 AddToPath_NT
; Not on NT
StrCpy $1 $WINDIR 2
FileOpen $1 "$1\autoexec.bat" a
FileSeek $1 -1 END
FileReadByte $1 $2
IntCmp $2 26 0 +2 +2 # DOS EOF
FileSeek $1 -1 END # write over EOF
FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n"
FileClose $1
SetRebootFlag true
Goto AddToPath_done
AddToPath_NT:
ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
StrCmp $1 "" AddToPath_NTdoIt
Push $1
Call Trim
Pop $1
StrCpy $0 "$1;$0"
AddToPath_NTdoIt:
WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $0
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
AddToPath_done:
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
; RemoveFromPath - Remove a given dir from the path
; Input: head of the stack
Function un.RemoveFromPath
Exch $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
IntFmt $6 "%c" 26 # DOS EOF
Call un.IsNT
Pop $1
StrCmp $1 1 unRemoveFromPath_NT
; Not on NT
StrCpy $1 $WINDIR 2
FileOpen $1 "$1\autoexec.bat" r
GetTempFileName $4
FileOpen $2 $4 w
GetFullPathName /SHORT $0 $0
StrCpy $0 "SET PATH=%PATH%;$0"
Goto unRemoveFromPath_dosLoop
unRemoveFromPath_dosLoop:
FileRead $1 $3
StrCpy $5 $3 1 -1 # read last char
StrCmp $5 $6 0 +2 # if DOS EOF
StrCpy $3 $3 -1 # remove DOS EOF so we can compare
StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine
StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine
StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine
StrCmp $3 "" unRemoveFromPath_dosLoopEnd
FileWrite $2 $3
Goto unRemoveFromPath_dosLoop
unRemoveFromPath_dosLoopRemoveLine:
SetRebootFlag true
Goto unRemoveFromPath_dosLoop
unRemoveFromPath_dosLoopEnd:
FileClose $2
FileClose $1
StrCpy $1 $WINDIR 2
Delete "$1\autoexec.bat"
CopyFiles /SILENT $4 "$1\autoexec.bat"
Delete $4
Goto unRemoveFromPath_done
unRemoveFromPath_NT:
ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH"
StrCpy $5 $1 1 -1 # copy last char
StrCmp $5 ";" +2 # if last char != ;
StrCpy $1 "$1;" # append ;
Push $1
Push "$0;"
Call un.StrStr ; Find `$0;` in $1
Pop $2 ; pos of our dir
StrCmp $2 "" unRemoveFromPath_done
; else, it is in path
# $0 - path to add
# $1 - path var
StrLen $3 "$0;"
StrLen $4 $2
StrCpy $5 $1 -$4 # $5 is now the part before the path to remove
StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove
StrCpy $3 $5$6
StrCpy $5 $3 1 -1 # copy last char
StrCmp $5 ";" 0 +2 # if last char == ;
StrCpy $3 $3 -1 # remove last char
WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $3
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
unRemoveFromPath_done:
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Uninstall stuff
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
###########################################
# Utility Functions #
###########################################
;====================================================
; IsNT - Returns 1 if the current system is NT, 0
; otherwise.
; Output: head of the stack
;====================================================
; IsNT
; no input
; output, top of the stack = 1 if NT or 0 if not
;
; Usage:
; Call IsNT
; Pop $R0
; ($R0 at this point is 1 or 0)
!macro IsNT un
Function ${un}IsNT
Push $0
ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
StrCmp $0 "" 0 IsNT_yes
; we are not NT.
Pop $0
Push 0
Return
IsNT_yes:
; NT!!!
Pop $0
Push 1
FunctionEnd
!macroend
!insertmacro IsNT ""
!insertmacro IsNT "un."
; StrStr
; input, top of stack = string to search for
; top of stack-1 = string to search in
; output, top of stack (replaces with the portion of the string remaining)
; modifies no other variables.
;
; Usage:
; Push "this is a long ass string"
; Push "ass"
; Call StrStr
; Pop $R0
; ($R0 at this point is "ass string")
!macro StrStr un
Function ${un}StrStr
Exch $R1 ; st=haystack,old$R1, $R1=needle
Exch ; st=old$R1,haystack
Exch $R2 ; st=old$R1,old$R2, $R2=haystack
Push $R3
Push $R4
Push $R5
StrLen $R3 $R1
StrCpy $R4 0
; $R1=needle
; $R2=haystack
; $R3=len(needle)
; $R4=cnt
; $R5=tmp
loop:
StrCpy $R5 $R2 $R3 $R4
StrCmp $R5 $R1 done
StrCmp $R5 "" done
IntOp $R4 $R4 + 1
Goto loop
done:
StrCpy $R1 $R2 "" $R4
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Exch $R1
FunctionEnd
!macroend
!insertmacro StrStr ""
!insertmacro StrStr "un."
Function Trim ; Added by Pelaca
Exch $R1
Push $R2
Loop:
StrCpy $R2 "$R1" 1 -1
StrCmp "$R2" " " RTrim
StrCmp "$R2" "$\n" RTrim
StrCmp "$R2" "$\r" RTrim
StrCmp "$R2" ";" RTrim
GoTo Done
RTrim:
StrCpy $R1 "$R1" -1
Goto Loop
Done:
Pop $R2
Exch $R1
FunctionEnd
Function ConditionalAddToRegistry
Pop $0
Pop $1
StrCmp "$0" "" ConditionalAddToRegistry_EmptyString
WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" \
"$1" "$0"
;MessageBox MB_OK "Set Registry: '$1' to '$0'"
DetailPrint "Set install registry entry: '$1' to '$0'"
ConditionalAddToRegistry_EmptyString:
FunctionEnd
;--------------------------------
!ifdef CPACK_USES_DOWNLOAD
Function DownloadFile
IfFileExists $INSTDIR\* +2
CreateDirectory $INSTDIR
Pop $0
; Skip if already downloaded
IfFileExists $INSTDIR\$0 0 +2
Return
StrCpy $1 "@CPACK_DOWNLOAD_SITE@"
try_again:
NSISdl::download "$1/$0" "$INSTDIR\$0"
Pop $1
StrCmp $1 "success" success
StrCmp $1 "Cancelled" cancel
MessageBox MB_OK "Download failed: $1"
cancel:
Return
success:
FunctionEnd
!endif
;--------------------------------
; Installation types
@CPACK_NSIS_INSTALLATION_TYPES@
;--------------------------------
; Component sections
@CPACK_NSIS_COMPONENT_SECTIONS@
;--------------------------------
; Define some macro setting for the gui
@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@
@CPACK_NSIS_INSTALLER_ICON_CODE@
@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@
;--------------------------------
;Pages
!define MUI_LANGDLL_REGISTRY_ROOT "SHCTX"
!define MUI_LANGDLL_REGISTRY_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@"
!define MUI_LANGDLL_REGISTRY_VALUENAME "NSIS:Language"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@"
!insertmacro MUI_PAGE_DIRECTORY
;Start Menu Folder Page Configuration
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder"
!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
@CPACK_NSIS_PAGE_COMPONENTS@
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\doc\README.txt"
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "Dutch"
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Italian"
!insertmacro MUI_LANGUAGE "Portuguese"
!insertmacro MUI_LANGUAGE "Spanish"
;--------------------------------
;Installer Sections
Section "-Core installation"
;Use the entire tree produced by the INSTALL target. Keep the
;list of directories here in sync with the RMDir commands below.
SetOutPath "$INSTDIR"
@CPACK_NSIS_FULL_INSTALL@
;Store installation folder
WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR
;Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
Push "DisplayName"
Push "@CPACK_NSIS_DISPLAY_NAME@"
Call ConditionalAddToRegistry
Push "DisplayVersion"
Push "@CPACK_PACKAGE_VERSION@"
Call ConditionalAddToRegistry
Push "Publisher"
Push "@CPACK_PACKAGE_VENDOR@"
Call ConditionalAddToRegistry
Push "UninstallString"
Push "$INSTDIR\Uninstall.exe"
Call ConditionalAddToRegistry
Push "NoRepair"
Push "1"
Call ConditionalAddToRegistry
!ifdef CPACK_NSIS_ADD_REMOVE
;Create add/remove functionality
Push "ModifyPath"
Push "$INSTDIR\AddRemove.exe"
Call ConditionalAddToRegistry
!else
Push "NoModify"
Push "1"
Call ConditionalAddToRegistry
!endif
; Optional registration
Push "DisplayIcon"
Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@"
Call ConditionalAddToRegistry
Push "HelpLink"
Push "@CPACK_NSIS_HELP_LINK@"
Call ConditionalAddToRegistry
Push "URLInfoAbout"
Push "@CPACK_NSIS_URL_INFO_ABOUT@"
Call ConditionalAddToRegistry
Push "Contact"
Push "@CPACK_NSIS_CONTACT@"
Call ConditionalAddToRegistry
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
;Create shortcuts
CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
@CPACK_NSIS_CREATE_ICONS@
@CPACK_NSIS_CREATE_ICONS_EXTRA@
CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
; Write special uninstall registry entries
Push "StartMenu"
Push "$STARTMENU_FOLDER"
Call ConditionalAddToRegistry
Push "DoNotAddToPath"
Push "$DO_NOT_ADD_TO_PATH"
Call ConditionalAddToRegistry
Push "AddToPathAllUsers"
Push "$ADD_TO_PATH_ALL_USERS"
Call ConditionalAddToRegistry
Push "AddToPathCurrentUser"
Push "$ADD_TO_PATH_CURRENT_USER"
Call ConditionalAddToRegistry
Push "InstallToDesktop"
Push "$INSTALL_DESKTOP"
Call ConditionalAddToRegistry
@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@
!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd
;--------------------------------
; determine admin versus local install
Function un.onInit
ClearErrors
UserInfo::GetName
IfErrors noLM
Pop $0
UserInfo::GetAccountType
Pop $1
StrCmp $1 "Admin" 0 +3
SetShellVarContext all
;MessageBox MB_OK 'User "$0" is in the Admin group'
Goto done
StrCmp $1 "Power" 0 +3
SetShellVarContext all
;MessageBox MB_OK 'User "$0" is in the Power Users group'
Goto done
noLM:
;Get installation folder from registry if available
done:
!insertmacro MUI_UNGETLANGUAGE
FunctionEnd
;--- Add/Remove callback functions: ---
!macro SectionList MacroName
;This macro used to perform operation on multiple sections.
;List all of your components in following manner here.
@CPACK_NSIS_COMPONENT_SECTION_LIST@
!macroend
Section -FinishComponents
;Removes unselected components and writes component status to registry
!insertmacro SectionList "FinishSection"
!ifdef CPACK_NSIS_ADD_REMOVE
; Get the name of the installer executable
System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1'
StrCpy $R3 $R0
; Strip off the last 13 characters, to see if we have AddRemove.exe
StrLen $R1 $R0
IntOp $R1 $R0 - 13
StrCpy $R2 $R0 13 $R1
StrCmp $R2 "AddRemove.exe" addremove_installed
; We're not running AddRemove.exe, so install it
CopyFiles $R3 $INSTDIR\AddRemove.exe
addremove_installed:
!endif
SectionEnd
;--- End of Add/Remove callback functions ---
;--------------------------------
; Component dependencies
Function .onSelChange
!insertmacro SectionList MaybeSelectionChanged
FunctionEnd
;--------------------------------
;Uninstaller Section
Section "Uninstall"
ReadRegStr $START_MENU SHCTX \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "StartMenu"
;MessageBox MB_OK "Start menu is in: $START_MENU"
ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "DoNotAddToPath"
ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathAllUsers"
ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "AddToPathCurrentUser"
;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS"
ReadRegStr $INSTALL_DESKTOP SHCTX \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@" "InstallToDesktop"
;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP "
@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@
;Remove files we installed.
;Keep the list of directories here in sync with the File commands above.
@CPACK_NSIS_DELETE_FILES@
@CPACK_NSIS_DELETE_DIRECTORIES@
!ifdef CPACK_NSIS_ADD_REMOVE
;Remove the add/remove program
Delete "$INSTDIR\AddRemove.exe"
!endif
;Remove the uninstaller itself.
Delete "$INSTDIR\Uninstall.exe"
DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_NAME@"
;Remove the installation directory if it is empty.
RMDir "$INSTDIR"
; Remove the registry entries.
DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
; Removes all optional components
!insertmacro SectionList "RemoveSection_CPack"
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
@CPACK_NSIS_DELETE_ICONS@
@CPACK_NSIS_DELETE_ICONS_EXTRA@
;Delete empty start menu parent directories
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
startMenuDeleteLoop:
ClearErrors
RMDir $MUI_TEMP
GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
IfErrors startMenuDeleteLoopDone
StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop
startMenuDeleteLoopDone:
; If the user changed the shortcut, then uninstall may not work. This should
; try to fix it.
StrCpy $MUI_TEMP "$START_MENU"
Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk"
@CPACK_NSIS_DELETE_ICONS_EXTRA@
;Delete empty start menu parent directories
StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP"
secondStartMenuDeleteLoop:
ClearErrors
RMDir $MUI_TEMP
GetFullPathName $MUI_TEMP "$MUI_TEMP\.."
IfErrors secondStartMenuDeleteLoopDone
StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop
secondStartMenuDeleteLoopDone:
DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@"
Push $INSTDIR\bin
StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0
Call un.RemoveFromPath
doNotRemoveFromPath:
SectionEnd
;--------------------------------
; determine admin versus local install
; Is install for "AllUsers" or "JustMe"?
; Default to "JustMe" - set to "AllUsers" if admin or on Win9x
; This function is used for the very first "custom page" of the installer.
; This custom page does not show up visibly, but it executes prior to the
; first visible page and sets up $INSTDIR properly...
; Choose different default installation folder based on SV_ALLUSERS...
; "Program Files" for AllUsers, "My Documents" for JustMe...
Function .onInit
!insertmacro MUI_LANGDLL_DISPLAY
; Reads components status for registry
!insertmacro SectionList "InitSection"
StrCpy $SV_ALLUSERS "JustMe"
StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
ClearErrors
UserInfo::GetName
IfErrors noLM
Pop $0
UserInfo::GetAccountType
Pop $1
StrCmp $1 "Admin" 0 +3
SetShellVarContext all
;MessageBox MB_OK 'User "$0" is in the Admin group'
StrCpy $SV_ALLUSERS "AllUsers"
Goto done
StrCmp $1 "Power" 0 +3
SetShellVarContext all
;MessageBox MB_OK 'User "$0" is in the Power Users group'
StrCpy $SV_ALLUSERS "AllUsers"
Goto done
noLM:
StrCpy $SV_ALLUSERS "AllUsers"
;Get installation folder from registry if available
done:
StrCmp $SV_ALLUSERS "AllUsers" 0 +2
StrCpy $INSTDIR "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
FunctionEnd

5
cmake/ReadFile.cmake Normal file
View File

@ -0,0 +1,5 @@
# This file is external to the read_from_file macro in Anope.cmake in order to
# get around a possible memory leak in older versions of CMake.
file(READ "${FILE}" RESULT)
message("${RESULT}")

4
data/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
set(DATA botserv.conf chanserv.conf global.conf hostserv.conf nickserv.conf operserv.conf services.conf)
install(FILES ${DATA}
DESTINATION ${CONF_DIR}
)

132
data/botserv.conf Normal file
View File

@ -0,0 +1,132 @@
service {
nick = "BotServ"
user = "services"
host = "services.host"
gecos = "Bot Service"
#channels = "@#services,#mychan"
}
module {
name = "botserv"
client = "BotServ"
defaults = "dontkickops fantasy greet"
minusers = 1
botmodes = "o"
}
command { service = "BotServ"; name = "HELP"; command = "generic/help"; }
module { name = "bs_assign" }
command { service = "BotServ"; name = "ASSIGN"; command = "botserv/assign"; }
command { service = "BotServ"; name = "UNASSIGN"; command = "botserv/unassign"; }
command { service = "BotServ"; name = "SET NOBOT"; command = "botserv/set/nobot"; permission = "botserv/set/nobot"; }
module {
name = "bs_autoassign"
bot = "ChanServ"
}
module {
name = "bs_badwords"
badwordsmax = 32
}
command { service = "BotServ"; name = "BADWORDS"; command = "botserv/badwords"; }
module { name = "bs_bot" }
command { service = "BotServ"; name = "BOT"; command = "botserv/bot"; permission = "botserv/bot"; }
module { name = "bs_botlist" }
command { service = "BotServ"; name = "BOTLIST"; command = "botserv/botlist"; }
module { name = "bs_control" }
command { service = "BotServ"; name = "ACT"; command = "botserv/act"; }
command { service = "BotServ"; name = "SAY"; command = "botserv/say"; }
module { name = "bs_info" }
command { service = "BotServ"; name = "INFO"; command = "botserv/info"; }
module {
name = "bs_kick"
keepdata = 10m
gentlebadwordreason = yes
}
command { service = "BotServ"; name = "KICK"; command = "botserv/kick"; }
command { service = "BotServ"; name = "KICK AMSG"; command = "botserv/kick/amsg"; }
command { service = "BotServ"; name = "KICK BADWORDS"; command = "botserv/kick/badwords"; }
command { service = "BotServ"; name = "KICK BOLDS"; command = "botserv/kick/bolds"; }
command { service = "BotServ"; name = "KICK CAPS"; command = "botserv/kick/caps"; }
command { service = "BotServ"; name = "KICK COLORS"; command = "botserv/kick/colors"; }
command { service = "BotServ"; name = "KICK FLOOD"; command = "botserv/kick/flood"; }
command { service = "BotServ"; name = "KICK ITALICS"; command = "botserv/kick/italics"; }
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"; }
module { name = "bs_set" }
command { service = "BotServ"; name = "SET"; command = "botserv/set"; }
command { service = "BotServ"; name = "SET BANEXPIRE"; command = "botserv/set/banexpire"; }
command { service = "BotServ"; name = "SET PRIVATE"; command = "botserv/set/private"; permission = "botserv/set/private"; }
module { name = "greet" }
command { service = "BotServ"; name = "SET GREET"; command = "botserv/set/greet"; }
command { service = "NickServ"; name = "SET GREET"; command = "nickserv/set/greet"; }
command { service = "NickServ"; name = "SASET GREET"; command = "nickserv/saset/greet"; permission = "nickserv/saset/greet"; }
privilege {
name = "GREET"
rank = 40
level = 5
flag = "g"
xop = "AOP"
}
module {
name = "fantasy"
}
command { service = "BotServ"; name = "SET FANTASY"; command = "botserv/set/fantasy"; }
fantasy { name = "ACCESS"; command = "chanserv/access"; }
fantasy { name = "AKICK"; command = "chanserv/akick"; }
fantasy { name = "AOP"; command = "chanserv/xop"; }
fantasy { name = "BAN"; command = "chanserv/ban"; }
fantasy { name = "CLONE"; command = "chanserv/clone"; }
fantasy { name = "DEHALFOP"; command = "chanserv/modes"; }
fantasy { name = "DEOP"; command = "chanserv/modes"; }
fantasy { name = "DEOWNER"; command = "chanserv/modes"; }
fantasy { name = "DEPROTECT"; command = "chanserv/modes"; }
fantasy { name = "DEVOICE"; command = "chanserv/modes"; }
fantasy { name = "DOWN"; command = "chanserv/down"; }
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 = false; }
fantasy { name = "HOP"; command = "chanserv/xop"; }
fantasy { name = "INFO"; command = "chanserv/info"; prepend_channel = false; }
fantasy { name = "INVITE"; command = "chanserv/invite"; }
fantasy { name = "K"; command = "chanserv/kick"; }
fantasy { name = "KB"; command = "chanserv/ban"; }
fantasy { name = "KICK"; command = "chanserv/kick"; }
fantasy { name = "LEVELS"; command = "chanserv/levels"; }
fantasy { name = "LIST"; command = "chanserv/list"; prepend_channel = false; }
fantasy { name = "LOG"; command = "chanserv/log"; }
fantasy { name = "MODE"; command = "chanserv/mode"; }
fantasy { name = "MUTE"; command = "chanserv/ban"; kick = no; mode = "QUIET"; }
fantasy { name = "OP"; command = "chanserv/modes"; }
fantasy { name = "OWNER"; command = "chanserv/modes"; }
fantasy { name = "PROTECT"; command = "chanserv/modes"; }
fantasy { name = "QOP"; command = "chanserv/xop"; }
fantasy { name = "SEEN"; command = "chanserv/seen"; prepend_channel = false; }
fantasy { name = "SOP"; command = "chanserv/xop"; }
fantasy { name = "STATUS"; command = "chanserv/status"; }
fantasy { name = "SUSPEND"; command = "chanserv/suspend"; permission = "chanserv/suspend"; }
fantasy { name = "SYNC"; command = "chanserv/sync"; }
fantasy { name = "TOPIC"; command = "chanserv/topic"; }
fantasy { name = "UNBAN"; command = "chanserv/unban"; }
fantasy { name = "UNSUSPEND"; command = "chanserv/unsuspend"; permission = "chanserv/suspend"; }
fantasy { name = "UP"; command = "chanserv/up"; }
fantasy { name = "VOICE"; command = "chanserv/modes"; }
fantasy { name = "VOP"; command = "chanserv/xop"; }

472
data/chanserv.conf Normal file
View File

@ -0,0 +1,472 @@
service {
nick = "ChanServ"
user = "services"
host = "services.host"
gecos = "Channel Registration Service"
#channels = "@#services,#mychan"
}
module {
name = "chanserv"
client = "ChanServ"
defaults = "keeptopic peace cs_secure secureops securefounder cs_keep_modes"
maxregistered = 5
expire = 7d
accessmax = 100
inhabit = 15s
nomlock = "CnLpPs"
reasonmax = 100
signkickformat = "%m (%n)"
disallow_hostmask_access = true
disallow_channel_access = true
always_lower_ts = false
}
privilege {
name = "ACCESS_CHANGE"
rank = 360 # 0 ?
level = 10000 # 10 ?
flag = "f"
xop = "QOP" # SOP?
}
privilege {
name = "ACCESS_LIST"
rank = 10
level = 3
flag = "f"
xop = "VOP"
}
privilege {
name = "AKICK"
rank = 250
level = 10
flag = "K"
xop = "SOP"
}
privilege {
name = "ASSIGN"
rank = 270
level = "founder"
flag = "s"
xop = "QOP"
}
privilege {
name = "AUTOHALFOP"
rank = 100
level = 4
flag = "H"
xop = "HOP"
}
privilege {
name = "AUTOOP"
rank = 210
level = 5
flag = "O"
xop = "AOP"
}
privilege {
name = "AUTOOWNER"
rank = 330
level = 9999
flag = "Q"
xop = "QOP"
}
privilege {
name = "AUTOPROTECT"
rank = 240
level = 10
flag = "A"
xop = "SOP"
}
privilege {
name = "AUTOVOICE"
rank = 50
level = 3
flag = "V"
xop = "VOP"
}
privilege {
name = "BADWORDS"
rank = 260
level = 10
flag = "K"
xop = "SOP"
}
privilege {
name = "BAN"
rank = 150
level = 4
flag = "b"
xop = "HOP"
}
privilege {
name = "FANTASIA"
rank = 30
level = 3
flag = "c"
xop = "VOP"
}
privilege {
name = "FOUNDER"
rank = 360
level = 10000
flag = "F"
xop = "QOP"
}
privilege {
name = "GETKEY"
rank = 180
level = 5
flag = "G"
xop = "AOP"
}
privilege {
name = "HALFOP"
rank = 120
level = 5
flag = "h"
xop = "AOP"
}
privilege {
name = "HALFOPME"
rank = 110
level = 4
flag = "h"
xop = "HOP"
}
privilege {
name = "INFO"
rank = 80
level = 9999
flag = "I"
xop = "QOP"
}
privilege {
name = "INVITE"
rank = 190
level = 5
flag = "i"
xop = "AOP"
}
privilege {
name = "KICK"
rank = 130
level = 4
flag = "k"
xop = "HOP"
}
privilege {
name = "MEMO"
rank = 280
level = 10
flag = "m"
xop = "SOP"
}
privilege {
name = "MODE"
rank = 170
level = 9999
flag = "s"
xop = "QOP"
}
privilege {
name = "NOKICK"
rank = 20
level = 1
flag = "N"
xop = "VOP"
}
privilege {
name = "OP"
rank = 230
level = 5
flag = "o"
xop = "SOP"
}
privilege {
name = "OPME"
rank = 220
level = 5
flag = "o"
xop = "AOP"
}
privilege {
name = "OWNER"
rank = 350
level = "founder"
flag = "q"
xop = "QOP"
}
privilege {
name = "OWNERME"
rank = 340
level = 9999
flag = "q"
xop = "QOP"
}
privilege {
name = "PROTECT"
rank = 310
level = 9999
flag = "a"
xop = "QOP"
}
privilege {
name = "PROTECTME"
rank = 300
level = 10
flag = "a"
xop = "SOP"
}
privilege {
name = "SAY"
rank = 90
level = 5
flag = "B"
xop = "AOP"
}
privilege {
name = "SET"
rank = 320
level = 9999
flag = "s"
xop = "QOP"
}
privilege {
name = "SIGNKICK"
rank = 140
level = 9999
flag = "K"
xop = "QOP"
}
privilege {
name = "TOPIC"
rank = 160
level = 5
flag = "t"
xop = "AOP"
}
privilege {
name = "UNBAN"
rank = 200
level = 4
flag = "u"
xop = "HOP"
}
privilege {
name = "VOICE"
rank = 70
level = 4
flag = "v"
xop = "HOP"
}
privilege {
name = "VOICEME"
rank = 60
level = 3
flag = "v"
xop = "VOP"
}
command_group {
name = "chanserv/access"
description = _("Used to manage the list of privileged users")
}
command_group {
name = "chanserv/status"
description = _("Used to modify the channel status of you or other users")
}
command_group {
name = "chanserv/management"
description = _("Used to manage channels")
}
command_group {
name = "chanserv/admin"
description = _("Services Operator commands")
}
command { service = "ChanServ"; name = "HELP"; command = "generic/help"; }
module {
name = "cs_akick"
autokickmax = 32
autokickreason = "8,4 E N T E R T H E V O I D "
}
command { service = "ChanServ"; name = "AKICK"; command = "chanserv/akick"; group = "chanserv/management"; }
module { name = "cs_ban" }
command { service = "ChanServ"; name = "BAN"; command = "chanserv/ban"; }
module { name = "cs_clone" }
command { service = "ChanServ"; name = "CLONE"; command = "chanserv/clone"; group = "chanserv/management"; }
module { name = "cs_drop" }
command { service = "ChanServ"; name = "DROP"; command = "chanserv/drop"; }
module { name = "cs_enforce" }
command { service = "ChanServ"; name = "ENFORCE"; command = "chanserv/enforce"; group = "chanserv/management"; }
module {
name = "cs_entrymsg"
maxentries = 5
}
command { service = "ChanServ"; name = "ENTRYMSG"; command = "chanserv/entrymsg"; group = "chanserv/management"; }
module { name = "cs_flags" }
command { service = "ChanServ"; name = "FLAGS"; command = "chanserv/flags"; group = "chanserv/access"; }
#module { name = "cs_getkey" }
#command { service = "ChanServ"; name = "GETKEY"; command = "chanserv/getkey"; }
module { name = "cs_info" }
command { service = "ChanServ"; name = "INFO"; command = "chanserv/info"; }
module { name = "cs_invite" }
command { service = "ChanServ"; name = "INVITE"; command = "chanserv/invite"; }
module { name = "cs_kick" }
command { service = "ChanServ"; name = "KICK"; command = "chanserv/kick"; }
module {
name = "cs_list"
listmax = 50
}
command { service = "ChanServ"; name = "LIST"; command = "chanserv/list"; }
command { service = "ChanServ"; name = "SET PRIVATE"; command = "chanserv/set/private"; }
module {
name = "cs_log"
}
command { service = "ChanServ"; name = "LOG"; command = "chanserv/log"; group = "chanserv/management"; }
module {
name = "cs_mode"
mlock = "+nst"
max = 100
}
command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; group = "chanserv/management"; }
command { service = "ChanServ"; name = "OWNER"; command = "chanserv/modes"; group = "chanserv/status"; set = "OWNER" }
command { service = "ChanServ"; name = "DEOWNER"; command = "chanserv/modes"; group = "chanserv/status"; unset = "OWNER" }
command { service = "ChanServ"; name = "PROTECT"; command = "chanserv/modes"; group = "chanserv/status"; set = "PROTECT" }
command { service = "ChanServ"; name = "DEPROTECT"; command = "chanserv/modes"; group = "chanserv/status"; unset = "PROTECT" }
command { service = "ChanServ"; name = "OP"; command = "chanserv/modes"; group = "chanserv/status"; set = "OP" }
command { service = "ChanServ"; name = "DEOP"; command = "chanserv/modes"; group = "chanserv/status"; unset = "OP" }
command { service = "ChanServ"; name = "HALFOP"; command = "chanserv/modes"; group = "chanserv/status"; set = "HALFOP" }
command { service = "ChanServ"; name = "DEHALFOP"; command = "chanserv/modes"; group = "chanserv/status"; unset = "HALFOP" }
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" }
module { name = "cs_register" }
command { service = "ChanServ"; name = "REGISTER"; command = "chanserv/register"; }
module {
name = "cs_seen"
simple = false
purgetime = "30d"
}
command { service = "OperServ"; name = "SEEN"; command = "operserv/seen"; permission = "operserv/seen"; }
module {
name = "cs_set"
defbantype = 2
persist_lower_ts = true
}
command { service = "ChanServ"; name = "SET"; command = "chanserv/set"; group = "chanserv/management"; }
command { service = "ChanServ"; name = "SET AUTOOP"; command = "chanserv/set/autoop"; }
command { service = "ChanServ"; name = "SET BANTYPE"; command = "chanserv/set/bantype"; }
command { service = "ChanServ"; name = "SET DESCRIPTION"; command = "chanserv/set/description"; }
command { service = "ChanServ"; name = "SET DESC"; command = "chanserv/set/description"; hide = yes; }
command { service = "ChanServ"; name = "SET FOUNDER"; command = "chanserv/set/founder"; }
command { service = "ChanServ"; name = "SET KEEPMODES"; command = "chanserv/set/keepmodes"; }
command { service = "ChanServ"; name = "SET PEACE"; command = "chanserv/set/peace"; }
command { service = "ChanServ"; name = "SET PERSIST"; command = "chanserv/set/persist"; }
command { service = "ChanServ"; name = "SET RESTRICTED"; command = "chanserv/set/restricted"; }
command { service = "ChanServ"; name = "SET SECURE"; command = "chanserv/set/secure"; }
command { service = "ChanServ"; name = "SET SECUREFOUNDER"; command = "chanserv/set/securefounder"; }
command { service = "ChanServ"; name = "SET SECUREOPS"; command = "chanserv/set/secureops"; }
command { service = "ChanServ"; name = "SET SIGNKICK"; command = "chanserv/set/signkick"; }
command { service = "ChanServ"; name = "SET SUCCESSOR"; command = "chanserv/set/successor"; }
command { service = "ChanServ"; name = "SET NOEXPIRE"; command = "chanserv/saset/noexpire"; permission = "chanserv/saset/noexpire"; }
module { name = "cs_set_misc" }
command { service = "ChanServ"; name = "SET URL"; command = "chanserv/set/misc"; misc_description = _("Associate a URL with the channel"); }
command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc"; misc_description = _("Associate an E-mail address with the channel"); }
module { name = "cs_status" }
command { service = "ChanServ"; name = "STATUS"; command = "chanserv/status"; }
module {
name = "cs_suspend"
#expire = 90d
#show = "suspended, by, reason, on, expires"
}
command { service = "ChanServ"; name = "SUSPEND"; command = "chanserv/suspend"; permission = "chanserv/suspend"; group = "chanserv/admin"; }
command { service = "ChanServ"; name = "UNSUSPEND"; command = "chanserv/unsuspend"; permission = "chanserv/suspend"; group = "chanserv/admin"; }
module { name = "cs_sync" }
command { service = "ChanServ"; name = "SYNC"; command = "chanserv/sync"; group = "chanserv/management"; }
module { name = "cs_topic" }
command { service = "ChanServ"; name = "TOPIC"; command = "chanserv/topic"; group = "chanserv/management"; }
command { service = "ChanServ"; name = "SET KEEPTOPIC"; command = "chanserv/set/keeptopic"; }
module { name = "cs_unban" }
command { service = "ChanServ"; name = "UNBAN"; command = "chanserv/unban"; }
module { name = "cs_updown" }
command { service = "ChanServ"; name = "DOWN"; command = "chanserv/down"; group = "chanserv/status"; }
command { service = "ChanServ"; name = "UP"; command = "chanserv/up"; group = "chanserv/status"; }
module { name = "cs_xop" }
command { service = "ChanServ"; name = "QOP"; command = "chanserv/xop"; group = "chanserv/access"; }
command { service = "ChanServ"; name = "SOP"; command = "chanserv/xop"; group = "chanserv/access"; }
command { service = "ChanServ"; name = "AOP"; command = "chanserv/xop"; group = "chanserv/access"; }
command { service = "ChanServ"; name = "HOP"; command = "chanserv/xop"; group = "chanserv/access"; }
command { service = "ChanServ"; name = "VOP"; command = "chanserv/xop"; group = "chanserv/access"; }
module { name = "cs_statusupdate" }

20
data/global.conf Normal file
View File

@ -0,0 +1,20 @@
service {
nick = "Global"
user = "services"
host = "services.host"
gecos = "Global Noticer"
#channels = "@#services,#mychan"
}
module {
name = "global"
client = "Global"
globaloncycledown = "Services are restarting and will be back shortly. Please cause as much chaos as possible in the mean time..."
globaloncycleup = "Services are now back online"
anonymousglobal = yes
}
command { service = "Global"; name = "HELP"; command = "generic/help"; }
module { name = "gl_global" }
command { service = "Global"; name = "GLOBAL"; command = "global/global"; permission = "global/global"; }

49
data/hostserv.conf Normal file
View File

@ -0,0 +1,49 @@
service {
nick = "HostServ"
user = "services"
host = "services.host"
gecos = "vHost Service"
#channels = "@#services,#mychan"
}
module {
name = "hostserv"
client = "HostServ"
activate_on_set = false
}
command { service = "HostServ"; name = "HELP"; command = "generic/help"; }
module { name = "hs_del" }
command { service = "HostServ"; name = "DEL"; command = "hostserv/del"; permission = "hostserv/del"; }
command { service = "HostServ"; name = "DELALL"; command = "hostserv/delall"; permission = "hostserv/del"; }
module {
name = "hs_group"
syncongroup = false
synconset = false
}
command { service = "HostServ"; name = "GROUP"; command = "hostserv/group"; }
module { name = "hs_list" }
command { service = "HostServ"; name = "LIST"; command = "hostserv/list"; permission = "hostserv/list"; }
module { name = "hs_off" }
command { service = "HostServ"; name = "OFF"; command = "hostserv/off"; }
module { name = "hs_on" }
command { service = "HostServ"; name = "ON"; command = "hostserv/on"; }
module {
name = "hs_request"
memouser = no
memooper = no
}
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"; }
module { name = "hs_set" }
command { service = "HostServ"; name = "SET"; command = "hostserv/set"; permission = "hostserv/set"; }
command { service = "HostServ"; name = "SETALL"; command = "hostserv/setall"; permission = "hostserv/set"; }

178
data/nickserv.conf Normal file
View File

@ -0,0 +1,178 @@
service {
nick = "NickServ"
user = "services"
host = "services.host"
gecos = "Nickname Registration Service"
#channels = "@#services,#mychan"
}
module {
name = "nickserv"
client = "NickServ"
forceemail = no
confirmemailchanges = no
unregistered_notice = "Your nickname is not registered. To register it, use: /msg NickServ REGISTER password"
defaults = "kill_quick ns_secure ns_private hide_email hide_mask hide_status hide_quit autoop ns_keep_modes"
regdelay = 1h
expire = 7d
secureadmins = yes
modeonid = yes
#modesonid = "+R"
hidenetsplitquit = yes
killquick = 10s
kill = 30s
#restrictopernicks = yes
enforceruser = "enforcer"
enforcerhost = "services.host"
releasetimeout = 1m
guestnickprefix = "FAGGOT"
nonicknameownership = no
passlen = 100
}
command_group {
name = "nickserv/admin"
description = _("Services Operator commands")
}
command { service = "NickServ"; name = "HELP"; command = "generic/help"; }
module {
name = "ns_access"
accessmax = 10
addaccessonreg = no
}
command { service = "NickServ"; name = "ACCESS"; command = "nickserv/access"; }
module {
name = "ns_ajoin"
ajoinmax = 10
}
command { service = "NickServ"; name = "AJOIN"; command = "nickserv/ajoin"; }
module { name = "ns_alist" }
command { service = "NickServ"; name = "ALIST"; command = "nickserv/alist"; }
module {
name = "ns_cert"
max = 3
}
command { service = "NickServ"; name = "CERT"; command = "nickserv/cert"; }
module { name = "ns_drop" }
command { service = "NickServ"; name = "DROP"; command = "nickserv/drop"; }
#module { name = "ns_getemail" }
#command { service = "NickServ"; name = "GETEMAIL"; command = "nickserv/getemail"; permission = "nickserv/getemail"; group = "nickserv/admin"; }
#module { name = "ns_getpass" }
#command { service = "NickServ"; name = "GETPASS"; command = "nickserv/getpass"; permission = "nickserv/getpass"; }
module {
name = "ns_group"
maxaliases = 5
nogroupchange = yes
}
command { service = "NickServ"; name = "GLIST"; command = "nickserv/glist"; }
command { service = "NickServ"; name = "GROUP"; command = "nickserv/group"; }
command { service = "NickServ"; name = "UNGROUP"; command = "nickserv/ungroup"; }
module {
name = "ns_identify"
maxlogins = 3
}
command { service = "NickServ"; name = "ID"; command = "nickserv/identify"; hide = true; }
command { service = "NickServ"; name = "IDENTIFY"; command = "nickserv/identify"; }
module { name = "ns_info" }
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"; }
module {
name = "ns_list"
listmax = 100
}
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"; }
module { name = "ns_logout" }
command { service = "NickServ"; name = "LOGOUT"; command = "nickserv/logout"; }
module {
name = "ns_recover"
restoreonrecover = yes
}
command { service = "NickServ"; name = "RECOVER"; command = "nickserv/recover"; }
command { service = "NickServ"; name = "GHOST"; command = "nickserv/recover"; }
command { service = "NickServ"; name = "RELEASE"; command = "nickserv/recover"; }
module {
name = "ns_register"
registration = "none"
nickregdelay = 1h
}
command { service = "NickServ"; name = "CONFIRM"; command = "nickserv/confirm"; }
command { service = "NickServ"; name = "REGISTER"; command = "nickserv/register"; }
#command { service = "NickServ"; name = "RESEND"; command = "nickserv/resend"; }
#module { name = "ns_resetpass" }
#command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpass"; }
module {
name = "ns_set"
allowkillimmed = yes
}
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 EMAIL"; command = "nickserv/set/email"; }
command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/email"; permission = "nickserv/saset/email"; }
command { service = "NickServ"; name = "SET KEEPMODES"; command = "nickserv/set/keepmodes"; }
command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/saset/keepmodes"; permission = "nickserv/saset/keepmodes"; }
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
command { service = "NickServ"; name = "SET LANGUAGE"; command = "nickserv/set/language"; }
command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/saset/language"; permission = "nickserv/saset/language"; }
command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
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 SECURE"; command = "nickserv/set/secure"; }
command { service = "NickServ"; name = "SASET SECURE"; command = "nickserv/saset/secure"; permission = "nickserv/saset/secure"; }
command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; permission = "nickserv/saset/noexpire"; }
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"; }
module { name = "ns_status" }
command { service = "NickServ"; name = "STATUS"; command = "nickserv/status"; }
module {
name = "ns_suspend"
#suspendexpire = 90d
#show = "suspended, by, reason, on, expires"
}
command { service = "NickServ"; name = "SUSPEND"; command = "nickserv/suspend"; permission = "nickserv/suspend"; group = "nickserv/admin"; }
command { service = "NickServ"; name = "UNSUSPEND"; command = "nickserv/unsuspend"; permission = "nickserv/suspend"; group = "nickserv/admin"; }
module { name = "ns_update" }
command { service = "NickServ"; name = "UPDATE"; command = "nickserv/update"; }

148
data/operserv.conf Normal file
View File

@ -0,0 +1,148 @@
service {
nick = "OperServ"
user = "services"
host = "services.host"
gecos = "Operator Service"
#channels = "@#services,#mychan"
}
module {
name = "operserv"
client = "OperServ"
autokillexpiry = 7d
chankillexpiry = 7d
snlineexpiry = 7d
sqlineexpiry = 7d
akillonadd = yes
killonsnline = yes
killonsqline = yes
addakiller = yes
akillids = yes
opersonly = yes
}
command { service = "OperServ"; name = "HELP"; command = "generic/help"; }
module { name = "os_akill" }
command { service = "OperServ"; name = "AKILL"; command = "operserv/akill"; permission = "operserv/akill"; }
module { name = "os_chankill" }
command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"; permission = "operserv/chankill"; }
module {
name = "os_defcon"
defaultlevel = 5
level4 = "silentoperonly" # GET
level3 = "silentoperonly" # FUCKED
level2 = "silentoperonly" # GET
level1 = "silentoperonly" # FUCKED
timeout = 1h
}
command { service = "OperServ"; name = "DEFCON"; command = "operserv/defcon"; permission = "operserv/defcon"; }
module { name = "os_config" }
command { service = "OperServ"; name = "CONFIG"; command = "operserv/config"; permission = "operserv/config"; }
module { name = "os_forbid" }
command { service = "OperServ"; name = "FORBID"; command = "operserv/forbid"; permission = "operserv/forbid"; }
module { name = "os_ignore" }
command { service = "OperServ"; name = "IGNORE"; command = "operserv/ignore"; permission = "operserv/ignore"; }
module { name = "os_info" }
command { service = "OperServ"; name = "INFO"; command = "operserv/info"; permission = "operserv/info"; }
module { name = "os_jupe" }
command { service = "OperServ"; name = "JUPE"; command = "operserv/jupe"; permission = "operserv/jupe"; }
module { name = "os_kick" }
command { service = "OperServ"; name = "KICK"; command = "operserv/kick"; permission = "operserv/kick"; }
module { name = "os_kill" }
command { service = "OperServ"; name = "KILL"; command = "operserv/kill"; permission = "operserv/kill"; }
module { name = "os_list" }
command { service = "OperServ"; name = "CHANLIST"; command = "operserv/chanlist"; permission = "operserv/chanlist"; }
command { service = "OperServ"; name = "USERLIST"; command = "operserv/userlist"; permission = "operserv/userlist"; }
module { name = "os_login" }
command { service = "OperServ"; name = "LOGIN"; command = "operserv/login"; }
command { service = "OperServ"; name = "LOGOUT"; command = "operserv/logout"; }
module {
name = "os_logsearch"
logname = "services.log"
}
command { service = "OperServ"; name = "LOGSEARCH"; command = "operserv/logsearch"; permission = "operserv/logsearch"; }
module { name = "os_mode" }
command { service = "OperServ"; name = "UMODE"; command = "operserv/umode"; permission = "operserv/umode"; }
command { service = "OperServ"; name = "MODE"; command = "operserv/mode"; permission = "operserv/mode"; }
module { name = "os_modinfo" }
command { service = "OperServ"; name = "MODINFO"; command = "operserv/modinfo"; permission = "operserv/modinfo"; }
command { service = "OperServ"; name = "MODLIST"; command = "operserv/modlist"; permission = "operserv/modinfo"; }
module { name = "os_module" }
command { service = "OperServ"; name = "MODLOAD"; command = "operserv/modload"; permission = "operserv/modload"; }
command { service = "OperServ"; name = "MODRELOAD"; command = "operserv/modreload"; permission = "operserv/modload"; }
command { service = "OperServ"; name = "MODUNLOAD"; command = "operserv/modunload"; permission = "operserv/modload"; }
module {
name = "os_news"
announcer = "Global"
oper_announcer = "OperServ"
newscount = 5
}
command { service = "OperServ"; name = "LOGONNEWS"; command = "operserv/logonnews"; permission = "operserv/news"; }
command { service = "OperServ"; name = "OPERNEWS"; command = "operserv/opernews"; permission = "operserv/news"; }
command { service = "OperServ"; name = "RANDOMNEWS"; command = "operserv/randomnews"; permission = "operserv/news"; }
module { name = "os_noop" }
command { service = "OperServ"; name = "NOOP"; command = "operserv/noop"; permission = "operserv/noop"; }
module { name = "os_oper" }
command { service = "OperServ"; name = "OPER"; command = "operserv/oper"; permission = "operserv/oper"; }
module { name = "os_reload" }
command { service = "OperServ"; name = "RELOAD"; command = "operserv/reload"; permission = "operserv/reload"; }
module {
name = "os_session"
defaultsessionlimit = 3
maxsessionlimit = 100
#exceptionexpiry = 1d
sessionlimitexceeded = "The session limit for your IP %IP% has been exceeded."
maxsessionkill = 10
sessionautokillexpiry = 1h
session_ipv4_cidr = 32
session_ipv6_cidr = 64
}
command { service = "OperServ"; name = "EXCEPTION"; command = "operserv/exception"; permission = "operserv/exception"; }
command { service = "OperServ"; name = "SESSION"; command = "operserv/session"; permission = "operserv/session"; }
module {
name = "os_set"
#superadmin = yes
}
command { service = "OperServ"; name = "SET"; command = "operserv/set"; permission = "operserv/set"; }
module { name = "os_shutdown" }
command { service = "OperServ"; name = "QUIT"; command = "operserv/quit"; permission = "operserv/quit"; }
command { service = "OperServ"; name = "RESTART"; command = "operserv/restart"; permission = "operserv/restart"; }
command { service = "OperServ"; name = "SHUTDOWN"; command = "operserv/shutdown"; permission = "operserv/shutdown"; }
module { name = "os_stats" }
command { service = "OperServ"; name = "STATS"; command = "operserv/stats"; permission = "operserv/stats"; }
module { name = "os_svs" }
command { service = "OperServ"; name = "SVSNICK"; command = "operserv/svsnick"; permission = "operserv/svs"; }
command { service = "OperServ"; name = "SVSJOIN"; command = "operserv/svsjoin"; permission = "operserv/svs"; }
command { service = "OperServ"; name = "SVSPART"; command = "operserv/svspart"; permission = "operserv/svs"; }
module { name = "os_sxline" }
command { service = "OperServ"; name = "SNLINE"; command = "operserv/snline"; permission = "operserv/snline"; }
command { service = "OperServ"; name = "SQLINE"; command = "operserv/sqline"; permission = "operserv/sqline"; }
module { name = "os_update" }
command { service = "OperServ"; name = "UPDATE"; command = "operserv/update"; permission = "operserv/update"; }

132
data/services.conf Normal file
View File

@ -0,0 +1,132 @@
define {
name = "services.host"
value = "services.supernets.org"
}
uplink {
host = "REDACTED"
ipv6 = yes
ssl = yes
port = REDACTED
password = "REDACTED"
}
serverinfo {
name = "services.supernets.org"
description = "Services for SuperNETs"
pid = "data/services.pid"
motd = "conf/services.motd"
}
module {
name = "unreal4"
use_server_side_mlock = yes
use_server_side_topiclock = yes
}
networkinfo {
networkname = "SuperNETs"
nicklen = 20
userlen = 10
hostlen = 64
chanlen = 20
modelistsize = 100
vhost_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-"
allow_undotted_vhosts = true
disallow_start_or_end = ".-"
}
options {
casemap = "ascii"
seed = REDACTED
strictpasswords = yes
badpasslimit = 3
badpasstimeout = 1h
updatetimeout = 5m
expiretimeout = 1h
readtimeout = 5s
warningtimeout = 4h
timeoutcheck = 3s
hidestatso = yes
retrywait = 60s
hideprivilegedcommands = yes
hideregisteredcommands = yes
}
include {
type = "file"
name = "botserv.conf"
}
include {
type = "file"
name = "chanserv.conf"
}
include {
type = "file"
name = "global.conf"
}
include {
type = "file"
name = "hostserv.conf"
}
include{
type = "file"
name = "nickserv.conf"
}
include {
type = "file"
name = "operserv.conf"
}
log {
target = "#services"
bot = "Global"
admin = "*"
override = "*"
commands = "*"
servers = "*"
channels = "*"
users = "*"
other = "*"
rawio = no
debug = no
}
log {
bot = "Global"
target = "globops"
admin = "global/* operserv/chankill operserv/mode operserv/kick operserv/akill operserv/s*line operserv/noop operserv/jupe operserv/oline operserv/set operserv/svsnick operserv/svsjoin operserv/svspart nickserv/getpass */drop"
servers = "squit"
users = "oper"
other = "expire/* bados akill/*"
}
opertype {
name = "Services Root"
commands = "*"
privs = "*"
}
oper {
name = "acidvegas"
type = "Services Root"
require_oper = yes
certfp = "f42e0c30ff63484dde3284823829f9b08568259c0b0f2beb174595ee577a924a"
host = "*@big.dick.acid.vegas"
}
module {
name = "db_flatfile"
database = "anope.db"
keepbackups = 7
fork = no
}
module { name = "enc_sha256" }
module { name = "help" }
module { name = "m_sasl" }

1
docs/ASTYLE Normal file
View File

@ -0,0 +1 @@
astyle --style=java --indent=tab --brackets=break-closing --indent-switches --indent-cases --brackets=break

1
docs/BUGS Normal file
View File

@ -0,0 +1 @@
For all bug reports / updates please see https://bugs.anope.org/

111
docs/C++CASTING Normal file
View File

@ -0,0 +1,111 @@
C++-style Casting
=================
In C, you can cast in one of two ways:
(type)var
type(var)
The problem with C-style casting is that it allows a programmer to get away
with too much, and is also not designed to handle C++ classes.
C++ has 4 types of casting in addition to allowing C-style casting. They are:
static_cast
const_cast
dynamic_cast
reinterpret_cast
The syntax is usually *_cast<type>(var).
static_cast
-----------
From my experience, this cast is closest to C-style casting for non-pointer
types as well as between some (but not all) pointer types. This type of cast,
like C-style casting, is performed at compile-time. static_cast can also do
a downcast of a derived class to a base class, but only if the base class is
not a virtual base class. Sometimes the result of this cast can become
undefined. static_cast is a bit more strict that C-style casting, though. It
disallows certain class conversions that would've been allowed with a C-style
cast. static_cast also doesn't allow you to cast to an incomplete type. In
these cases, I would try either dynamic_cast or reinterpret_cast.
const_cast
----------
This cast is mainly to add or remove const-ness or volatile-ness from a
variable. This is safer than using a C-style cast to change the const-ness
of a variable. In most cases if you try to use one of the other casts and it
complains about const-ness, you will want to either use this cast instead or
wrap the other cast around this cast. An example:
const int *a;
static_cast<void *>(a); <-- This will fail.
To remedy the above, you would might try this:
const int *a;
const_cast<void *>(a); <-- But this will still fail.
The real solution is this:
const int *a;
static_cast<void *>(const_cast<int *>(a));
It is not recommended to use const_cast on the this variable within a member
function of a class that is declared const. Instead you should use the mutable
keyword on the variable in the class's definition.
dynamic_cast
------------
This cast can only be used on pointers or references to classes. It can cast a
derived class to a base class, a derived class to another derived class
(provided that both are children of the same base class), or a base class to a
derived class. You can also use this to cast a class to void *. This cast is
done at run-time as opposed to the other casts, and relies on C++'s RTTI to be
enabled. It is meant to be used on polymorphic classes, so use static_cast on
non-polymorphic classes.
derived-to-base conversions are actually done statically, so you use either
dynamic_cast or static_cast on them, regardless of if the classes are
polymorphic or not.
derived-to-derived or base-to-derived conversions, however, rely on run-time
type information, and this cast is used on those classes that are polymorphic.
This is safer than C-style casting in that an invalid pointer conversion will
return a NULL pointer, and an invalid reference conversion will throw a
Bad_cast exception.
Note that in Anope we prefer if Anope::debug_cast is used.
This uses dynamic_cast (and checks for a NULL pointer return) on debug builds
and static_cast on release builds, to speed up the program because of dynamic_cast's
reliance on RTTI.
reinterpret_cast
----------------
This cast I would use only as a last resort if static_cast isn't allowed on a
conversion. It allows for conversions between two unrelated types, such as
going from char * to int *. It can also be used to convert a pointer to an
integral type and vica versa. The sites I've read mention how the result is
non-portable, which I assume means the resulting object code is non-portable,
so since the code is compiled on many systems anyways, I don't see this as
being a huge issue. It is recommended to only use this if necessary, though.
Links
=====
The following links are web sites I've used to get this information, and might
describe some of the above a bit better than I have. :P
https://www.acm.org/crossroads/xrds3-1/ovp3-1.html
http://www.cplusplus.com/doc/tutorial/typecasting.html
http://www.codeguru.com/forum/showthread.php?t=312456
https://web.archive.org/web/20170810222238/http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/cast.html
https://www.microsoft.com/en-us/download/details.aspx?id=55984
https://en.wikibooks.org/wiki/C%2B%2B_Programming/Type_Casting
https://web.archive.org/web/20160510114447/http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=134
-- CyberBotX, Nov 23, 2008

15
docs/CMakeLists.txt Normal file
View File

@ -0,0 +1,15 @@
# We only need to install these docs on Windows as most Windows installations will be binary, not source
if(WIN32)
# Only install given files from this directory
# NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_BINARY_DIR}/README.txt)
if(IN_SOURCE)
# Add README.txt to list of files for CPack to ignore
add_to_cpack_ignored_files("README.txt$" TRUE)
endif(IN_SOURCE)
set(DOCS Changes Changes.conf DEFCON FAQ INSTALL LANGUAGE MODULES NEWS ${CMAKE_CURRENT_BINARY_DIR}/README.txt WIN32.txt)
install(FILES ${DOCS}
DESTINATION ${DOC_DIR}
)
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/README.txt")
endif(WIN32)

239
docs/CODING Normal file
View File

@ -0,0 +1,239 @@
Originally pulled from: https://wiki.inspircd.org/Coding_Guidelines
---
InspIRCd Coding Guidelines
The following are a set of guidelines for writing patches to InspIRCd, or for
creating modules for distribution with the official package. These guidelines
were written a time after InspIRCd development started, and so not all code
yet follows these. This will be rectified with time.
1. Comments
* Multi Line
Multiple line comments should follow the C-style comment, for example:
/*
* This is a multiple line comment, huzzah..
*/
* Single Line
Single line comments should also be in the C style, for example:
/* This is a boring one-line comment */
* Doxygen commenting
If you wish your comment to show in doxygen, the comment should be directly
above the item you are documenting (a class, function, enum, etc) and the
first line should be "/**". For example:
/** This is a doxygen multiline comment.
* Description of thingymebob here.
*/
The first line after the "**" is used as the short description of the item
(up to the full stop) and everything afterwards as the detailed description.
2. Indentation
Tabs. Tabs. ONLY TABS. Use a single tab for each level of indentation,
for example:
int main()
{
<tab>if (condition)
<tab>{
<tab><tab>code
<tab>}
}
3. Separation
Always put a space in between a keyword like if/while and the condition,
for example:
if (foo == bar)
NOT
if(foo == bar)
4. Braces
Always put braces opening and closing blocks on separate lines, see the
indentation example. For example, place braces like this:
if (apples == "green")
{
cout << "Apples are green" << endl;
}
and not:
if (apples == "green") {
cout << "Apples are green" << endl;
}
The one exception to this is if you are declaring a class method which is
only one line long, in that case the following is acceptable in most cases:
class foo : public bar
{
foo() { }
getrandomfoo() { return rand(); }
};
5. Templates
Where possible, use templates rather than #defines. Avoid use of RTTI.
6. Structs
Structs should be declared in the following fashion:
struct BodyPartBasket
{
int arms;
int legs;
int scrotalsacs;
};
and not like this:
typedef struct
{
int arms;
int legs;
int scrotalsacs;
} BodyPartBasket;
The second way is not required in C++ to be able to do this:
BodyPartBasket mybasket;
Plus, placing the name at the bottom of the declaration makes readability
more difficult (as you have to scroll down to the bottom of the struct to
find its name). (where possible, call them classes rather than structs.)
7. Variable naming
Class and struct names should be in camel case with a leading capital letter,
for example "MyBagOfBones" and not "my_bag_of_bones" or "mybagofbones".
Variable names can be in either camel case with a leading capital letter or
alternatively all lower case, so long as the same naming convention is
adhered to throughout the class. No classes or variables should be named in
capitals unless this makes sense for the name (for example "class DNS").
Constants and enum values should always be completely in CAPITALS and
underscores may be used, for example:
enum DecayState
{
DECAYED_MOULDY = 0,
DECAYED_SMELLY = 1,
DECAYED_MAGGOTS = 2
};
All value names in an enum should be started with the same text which should
be related in some way to the enum's use. For example "DNS_CNAME, DNS_A,
DNS_AAAA".
8. Use of references
Wherever possible, when dealing with any complex class, pass a const reference
rather than a copy of the class. For example:
MyThingy::MyThingy(const std::string &thingyvalue)
{
}
Of course, if you intended to change the string you can just omit the 'const'.
9. Use of char pointers
Whenever you use char pointers (char*, char**) try to use const equivalents.
This is much safer and avoids ugly and dangerous casts. For example:
MyThingy::Thingify(const char* const* wotsits)
{
}
If it is possible without performance loss, consider avoiding char pointers
altogether and using std::string instead.
10. Use of STL
For more information on use of STL in InspIRCd, please see the separate
STL FAQ.
11. Making copies of data
Never ever make a copy of a piece of data unless it is absolutely necessary.
For example, don't use strlcpy() to make a copy of the const char* string
returned by std::string::c_str(), if the change can be done to the std::string
itself. The same goes for unnecessary variable assignments, especially those
which assign large classes.
12. namespace std
Avoid the following:
using namespace std;
It might take a bit more typing, but things work better if you don't set
(then later assume) the namespace -- specify it explicitly when you want to
use it.
13. Linefeeds
Unix linefeeds only please. We do not like to see our screens covered in ^M.
14. Portability
Always make sure your code is portable to all supported operating systems,
remember of course that as of 1.1.8 this includes windows. Don't write code
that only works on windows, or only works on Linux. Test your code on all
platforms or ask for help from other developers who have the platforms you
want to test on.
* new() and delete(), malloc() and free()
Apart from the fact that using malloc() and free() is bad practice in C++
code, you must never use malloc() or free() in InspIRCd, within its modules
or within the core. This is because if you use malloc() or free() in windows,
the memory is claimed from the program's local heap.
In windows, each shared object (module, dll) has its own heap, which is
protected from other dlls and executables. To get around this issue and
allow more posix-like memory access from other dlls in the program (other
modules), InspIRCd overrides the operators new and delete to ensure that
memory allocated by them comes from the windows global heap. If you use
malloc() and free() for this, the ircd will segfault when another module
tries to access the memory you have allocated!
* strdup()
As with malloc(), above, strdup() should be avoided. Where strdup() is
absolutely necessary, use strnewdup() which is our strdup() implementation
that calls operator new instead of using malloc().
char arrays allocated by strnewdup() should be deleted with operator delete[].
* CoreExport and DllImport
Prefix all types you want to import or export to other modules with CoreExport
and DllImport macros. These do nothing in POSIX operating systems, however
in windows these are expanded to the instructions __declspec(dllimport) and
__declspec(dllexport) respectively depending on where they are used and how.
15. External Dependencies
If a module is compiled as standard, or the code is part of the core, you must
not use any dependencies that are not available as standard on all supported
operating systems beyond libstdc++, libc, and whatever else is currently
required to build the core. Modules which use nonstandard dependencies belong
in the modules/extra directory.
16. Profiling and Performance
It is one thing to assume that code performs bad, it is another thing to prove
that it actually is. A lot of experienced programmers talk about 'premature
optimisation', and here is what it means: if you have a piece of code called
once on startup that takes 10 seconds instead of one second to run, and a
piece of code that takes 0.05 seconds to run when it should take 0.01, and
it is called once per second, the second piece of code is the priority.
In other words, make sure that what you think is slow, and a performance
problem in Insp actually is.
To do this, use the callgrind tool from Valgrind (valgrind --tool=cachegrind
bin/inspircd -nofork -debug), and kcachegrind (or similar) to view the output
files.

347
docs/COPYING Normal file
View File

@ -0,0 +1,347 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the entire
whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years,
to give any third party, for a charge no more than your cost of
physically performing source distribution, a complete machine-readable
copy of the corresponding source code, to be distributed under the terms
of Sections 1 and 2 above on a medium customarily used for software
interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is allowed
only for noncommercial distribution and only if you received the program
in object code or executable form with such an offer, in accord with
Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent license
would not permit royalty-free redistribution of the Program by all those
who receive copies directly or indirectly through you, then the only way
you could satisfy both it and this License would be to refrain entirely
from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is implemented
by public license practices. Many people have made generous contributions
to the wide range of software distributed through that system in reliance
on consistent application of that system; it is up to the author/donor to
decide if he or she is willing to distribute software through any other
system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be
a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make
it free software which everyone can redistribute and change under
these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and an idea of what it does.>
Copyright (C) yyyy name of author
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
type `show w'. This is free software, and you are welcome
to redistribute it under certain conditions; type `show c'
for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

412
docs/Changes Normal file
View File

@ -0,0 +1,412 @@
Anope Version 2.0.12
--------------------
Added account confirmation to the web panel
Added the regex_pcre2 module which provides regex/pcre with PCRE2
Documented the cs_no_expire channel default
Fixed config validation mistakenly allowing spaces in some fields
Fixed the bahamut protocol module not knowing about halfops
Fixed writing a flatfile database not being atomic
Updated the hybrid protocol module for recent protocol changes
Anope Version 2.0.11
--------------------
Fixed ldap on OpenLDAP 2.5+
Fixed not using utf-8 encoding for outgoing email
Fixed ns_resetpass not returning a response for XMLRPC
Fixed some message params being sent as <middle> instead of <trailing>
Fixed unsetting vhosts on unreal4
Fixed username validity checking on ircd-hybrid
Send the oper mode for services pseudoclients on InspIRCd
Updated the pl_PL translation
Updated unreal4 for various protocol changes
Anope Version 2.0.10
--------------------
Add support for channel SQLines on InspIRCd
Change default protocol module from inspircd20 to inspircd3
Change the character set used by chanstats and irc2sql to utf8mb4
Fix a ton of typos in messages
Fix being able to override MAXLIST on InspIRCd
Fix blocking on boot when trying to upgrade SQL databases without account identifiers
Fix not flushing the ERROR message on squit
Fix using an invalidated iterator when deleting bots
Fix various harmless compiler warnings
Fix webcpanel not using the forwarded IP
Show the account name in nickserv/info
Anope Version 2.0.9
-------------------
Fix a regression from 2.0.8 that prevented serialising to MySQL
Send account identifiers to InspIRCd on SASL logins too
Fix a query bug in irc2sql
Anope Version 2.0.8
-------------------
Add +K channel mode for ircd-hybrid
Add immutable identifiers to user accounts
Fix build on systems that use musl libc
Fix help of global/global not showing the correct origin nick
Fix not removing vhosts when an nick is dropped
Fix parsing channel metadata on InspIRCd 3+
Fix parsing kicks on InspIRCd 3+
Fix parsing topic changes on InspIRCd 3+
Fix topiclock on InspIRCd
Modernize the ircd-hybrid protocol module
Anope Version 2.0.7
-------------------
Fix not sending login data on successful NickServ GROUP
Fix m_httpd to not consider headers to be case sensitive
Add InspIRCd 3 protocol support
Add 'n' email token for use in the email change template
Add logging for NickServ UNGROUP
Fix setting swhois on UnrealIRCd
Add nickserv/recover permission to allow opers to recover other users
Fix superadmin not being removed when deopering
Fix setting nickserv access list in webcpanel
Add support for post-handshake SASL in Unreal 4.2.2+
Add logging for channel memo deletionso
Anope Version 2.0.6
-------------------
Log client IP for web clients running commands via webcpanel
Fix log file path for the config file could not be opened log message
Allow nickserv/group to be used via XMLRPC
Fix logsearch without wildcards
Support cidr exempts in m_dnsbl
Add support for IPv6 dnsbls
Add +u and +L channel modes for ircd-hybrid
Set +x after hostserv/off on InspIRCd and UnrealIRCd
Fix chanserv/mode not being able to set extbans
Send CHGIDENT/CHGHOST on SVSLOGIN on InspIRCd
Fix escaping replies from commands in webcpanel
Enable require_oper for all opers added via operserv/oper
Advertise SASL mechanisms to UnrealIRCd servers
Anope Version 2.0.5
-------------------
Fix negative levels to not match users with negative access
Fix memo sender to always be the account name of the sender
Allow unregistered users to use the ChanServ seen command
Fix secureops to not be enforced on operators with the chanserv/administration privilege
Fix command name in HELP syntax messages to always be upper case
Show unconfirmed nickname messages on registration in webcpanel
Fix NickServ SET EMAIL to be executable via XMLRPC
Fix OperServ USERLIST/CHANLIST to accept regexes
Allow OperServ USERLIST to also match realname syntax (n!u@h#r)
Fix db_old importing languages to use the UTF-8 version
Fix m_dns to return REFUSED if no answers could be found
Fix ns_maxemail to be case insensitive
Add MemoServ READ ALL command
Add support for NickServ GROUP to be executed via XMLRPC
Add support for logging hostname/ip of SASL authentication attempts, if supported by IRCd
Anope Version 2.0.4
-------------------
Add notice rpc method to XMLRPC
Fix access check in cs_updown to not allow actions on users with equal access
Fix randomnews to work when there are more than 'newscount' random news
Fix crash from handling nick introduction collisions on unreal4
Add support for GCC6
Fix handling /join 0 on ratbox
Fix saset display to update the account of the proper user
Fix nickserv/confirm to send account and +r when appropriate
Fix chankill to not add duplicate akills
Allow nickserv/maxemail to disregard gmail style aliases when comparing emails
Fix chanserv/mode when setting listmodes with CIDR ranges
Fix reported expiry time when the time is divisible by 1 year
Clarify botserv repeat kicker help and allow setting repeat times to 1
Send vident/vhost with SASL login
Add support for SASL reauth
Fix log and database backup directories to be properly created by the installer
Anope Version 2.0.3
-------------------
Add support for UnrealIRCd 4
Fix cs_access to respect chanserv/access/list privilege
Fix cs_access to match level -1 as every user, not any level <0
Fix problems related to object destruction order when using db_sql_live
Show memo notify settings in ms_info
Fix some actions bumping channels last used time that shouldn't have
Add maxlogins configuration directive to limit the number of concurrent logins to one account
Fix race with auto svsnick on ghost sometimes causing nick collisions instead
Fix saset langauge reply
Show akill/sxlines ids in VIEW
Fix crash when an oper is configured in both the configuration and via os_oper
Fix m_ldap reconnect logic not properly setting protocol and network timeout settings
Fix crash from unloading regex modules when regex xlines exist
Fix irc2sql to store away messages
Add notice method to m_xmlrpc_main
Fix numerics on InspIRCd from being sent to user UID
Fix usermode +I on UnrealIRCd to be considered oper only
Fix crash in webcpanel when deleting your own access on a channel
Fix webcpanel allowing suspended users to login
Fix hs_off on InspIRCd to not desync active user host
Fix bs_bot to not allow colliding bots into users
Don't allow hostserv modules to load if there is no hostserv
Fix ns_register allowing bot nicks to be registered through webcpanel
Don't update chanserv keepmodes during inhabit
Fix build on cmake 2.4
Allow searching emails by wildcard in ns_getemail
Anope Version 2.0.2
-------------------
Fix keepmodes preventing the first user of a channel from being deopped
Fix SQlines that don't begin with # from matching channels
Made cs_clone behave like the help describes, copying many settings and lists by default
Allow cs_clone to clone levels, too
Update Hybrid protocol module for 8.2
Fix not unescaping all characters sent over XMLRPC
Fix crash when os_mode is used to destroy channels, like when unsetting permanent channel mode from an empty channel
Allow users with topic change privilege to change the topic instead of requiring them to use ChanServ's topic command
Fix negatively locking param modes in default mlock
Change entrymsg to check for the SET privilege, not real founder
Allow configuring characters allowed in nicknames
Fix crash when non users register channels externally (like XMLRPC)
Remove operserv/exception MOVE, it did not function correctly. Instead reorder the list by deleting/adding entries.
Allow flood ttb to be 0.
Enforce mlock when disabling defcon modes
Fix cs_mode not being able to apply mlock on register
Add log message when users send memos
Fix old collide timers from staying around after successful identify. Fixes being able to identify and logout and still being hit by the old timers.
Fix undefined behavior in cs_mode which usually crashes when clearing large list modes
Show all opertypes in operserv/info, even if no opers use them
Anope Version 2.0.1
-------------------
Fix access entries on accounts sometimes not updating when a user's display name changes
Fix ns_group to properly validate the account of the user against the target
Fix os_stats not saving max user count and time when using SQL
Fix nickalias's 'nc' field sometimes not being updated when using SQL
Fix several crashes on Windows related to being unable to load modules
Fix bs_bot change not properly reintroducing bots after changing their ident, host, or realname
Add English language file to allow users to easily modify language strings
Add configuring which mode cs_ban sets, and added a MUTE command to BotServ's fantasy
Allow SVSPART to take an optional reason
Allow cs_list to search channel topics and descriptions
Anope Version 2.0.0
-------------------
Added irc2sql stats module
Anope Version 1.9.9
-------------------
A Added a better webpanel template, removed the old one
A Added SQL logging support
A Added Redis database support
A Added ability to configure what privileges XOP commands give
U Updated Dutch language file, from Robby <robby@chat.be>
U Updated Spanish langauge file, from Isaac Fontal <i_fontal@hotmail.com>
F Fix build on Solaris and OSX
F Fixed setting BotServ's default settings in the config
F Fixed some names of config items, including NickServ's kill protect
Anope Version 1.9.8
-------------------
A Ability to configure fantasy commands in the config
A Add SVSJOIN and SVSPART commands
F Fix "leave" channel log level from not logging
F Fix users able to "resend" their registration mail with registration set to admin only
F Fix build on OpenBSD
F Fix not logging debug logs to the logfile when debug mode is enabled
F Fix defcon timeout timer
F Fix crash in os_forbid with expiring entries
F Fix several issues with db_sql_live
Anope Version 1.9.7
-------------------
A Added ability for using regex as patterns for various commands
A Extended ability of operserv/akill to also match against nick and realname
A Added chanserv:require configuration option
A Added nickserv:unregistered_notice and nickserv:registration configuration option
A Added options:casemap configuration option
A Added a web panel
A db_sql_live now allows all tables to be "live", not just a select few
Anope Version 1.9.6
-------------------
A Added ability to configure emails sent by services
A Added chanserv/up and chanserv/down
A Added m_proxyscan
A Added more configurability for what vhosts are valid
A Added chanserv/log
A Added ability to configure ChanServ privileges
A Added a new database format
A Added SQLite support
A Added more verbose messages on startup
A Added ability for chanserv/suspend and nickserv/suspend to take an expiry time
A Added no nickname ownership config option
A Added m_rewrite
A Added akill IDs
F Fixed crash in clearusers
F Fixed crash in /os oper info
F Fixed eventfd Config check to work properly on OpenVZ
Anope Version 1.9.5
-------------------
A Extended LDAP support
A Added os_oper, os_kill, os_forbid, m_statusupdate, cs_sync, and bs_autoassign
A Added a new configuration file format
A Added a new commands system
A Added a new access system, and cs_flags
F Fixed not logging debug logs to file
F Fixed the mail delay time
F Fixed sending account data for unconfirmed nicks
F Fixed poll() engine build on FreeBSD
F Fixed really large HELP replies being truncated
F Fixed sometimes appending !*@* to valid hosts on access lists
F Fixed m_ssl sometimes failing connecting for no reason
F Fixed crash in cs_entrymsg
F Fixed setting -P on channels with only a botserv bot in it
F Fixed modemanager complaining about prefixless modes on InspIRCd
Anope Version 1.9.4
-------------------
A Automatically set channel founder to the user with the highest access if there is no successor
A /chanserv clone command to copy settings from one channel to another.
A /chanserv mode command
A Ability for users to delete their own access in channels
A Added support for Plexus 3
A Readded in support for /cs op/deop/etc to op/deop you in all channels
A Added LDAP support
A Added live SQL support
A Added support for learning tracking/storing/locking all modes at runtime
A Added m_alias
A Added support for XMLRPC queries
A Added /botserv set msg
A Added /operserv config
A Added /ns cert
A Added /operserv login
F Changed the GHOST command to not allow ghosting unidentified users if the RECOVER command exists
F Some failed logic in /operserv exception that prevents proper exceptions from being added
F Fixed the anope_os_sxlines MySQL table and code to work after restarting
Anope Version 1.9.3
-------------------
A Added italics BotServ kicks support
A Tell users when their nicks expire in /ns glist and /ns info
A Added SSL support
A Prevent negative mode changes, kicks, bans, and autokicks from affecting people with the 'god' user mode (On UnrealIRCd, usermode +q)
A Added nickserv/auxpex permission
A Added nickserv ungroup command
A Renamed the SGLINE to be SNLINE
A Added /chanserv saset command
A Added threads for mail sending
A Added m_dnsbl and an asynchronous DNS system
A Added a new language system that uses gettext
A Added m_mysql which uses threads to execute queries
A Added many subcommand modules for some commands, eg ns_set_autoop, ns_set_email, etc
A Added a new logging system that is a bit more flexible
A Added cs_set_misc and ns_set_misc to add miscellaneous set commands
A Added os_modreload, which allows reloading some modules not normally unloadable, like the protocol module
A Added FOUNDER access level
A Made OperServ, Global, MemoServ, and ChanServ optional
F Shutting down if a config reload fails
F Autoid to live through restarts on Unreal
F Storing vhosts in MySQL
F Not flushing the anope_extra table before rewriting database
F Anoperc start/stop to send the globaloncycle global, and fixed anoperc rehash to really rehash
F Fixed a potential crash if HostServ or BotServ was disabled
Anope Version 1.9.2
-------------------
A K alias to chanserv kick command
A KB alias to chanserv ban command
A The ability to register empty nonregistered channels
A Flatfile plaintext databases and removed old binary ones
A Added in live updating SQL and the ability to execute commands through SQL (see docs/MYSQL)
A Added support for many more modes into Anope and the ability to have generic support for modes unknown to Anope
A Added a mode stacker to combine many mode changes into fewer
A Added in the CS SET PERSIST command which can be used to keep service bots in channels even when the channel is empty
A Added AUTOOWNER OWNER and OWNERME into CS LEVELS
A Added ns_resetpass module to the core
A CS ACCESS VIEW which shows who added the access and last time used
A Last used time to CS AKICK VIEW
A Added a sha_256 encryption module
A Added the ability to load multiple encryption modules, and the ability to seamlessly convert your database between different encryptions
A Added configuration options to allow Anope to reconnect if it disconnects from the uplink instead of dying
A Added support for linking with IPv6
F Unban command to accept an optional nick arg
F Some typos in services.conf
F Crash when users change their host that are identified to a group, but not a nick
F Host length checking in HS SET(ALL) and HS REQUEST
F Only show if a user is online in NS INFO if they are really identified for the group of the nick they are on
F Crash when using BSSmartJoin
F Converting access entries to access from xop when a users access is below voice
F A bad pointer passed to the OnDelEvent which could cause some 3rd party modules to crash
F CS FORBID allows to you forbid unregistered channels
F The -nothird command line option to work
F ms_rsend to really work
F SQUITing juped servers on InspIRCd1.2+
Anope Version 1.9.1
-------------------
F Don't enforce akick/forbidden/etc.-restrictions on clients on ulined servers.
F Remove modules_unload_all fini + hack that goes with it.
F Signal handling cleanup.
A Seamless fantasy support on all ChanServ commands, instead of requiring bs_fantasy_*.
F Allow fantasy to be disabled on some commands (e.g. FORBID).
F Some commands (e.g. !help) need to strip the pre-provided channelname from them.
D HelpServ removed
F Command parser cleanup: mod_current_buffer removed and replaced with proper parser. Commands now indicate how they want the buffer split.
F Make NS ENFORCE/RELEASE stuff more sane, redo timers.
A Opertypes (similar to InspIRCd's opertypes)
Provided by Ankit <ankit@nevitus.com> - 2009
F Segfault on shutdown
Provided by Adam <adam@anope.org> - 2009
F NickServ registration is sometimes denied.
F Applied patch from Adam to fix some potential screwups
F More fixes to bs_bot from Adam, plus an extra fix within DoAdd not covered in Adam's patch.
F Fix bs_bot to use the correct parameters, patch from Adam.
F Fix for bug #1004, based from second half of patch from Adam.
F Partial patch by Adam, commenting fix for #1006 for future reference.
F Forward-port r1946: Patch by Adam fixing #1006 (originally caused by #922): modes set by ChanServ are reversed. Thanks!
Provided by DukePyrolator <dukepyrolator@gmx.de> - 2009
F Patch converting all match calls to new method, thanks!
F Add 'w' and 'y' support to dotime(), also prevent an overflow.
F Allow NS STATUS from unregistered users, thanks DP!
F Wild pointers do not a happy Anope make. Thanks DP :)
F Allow NS REGISTER to unregistered nicks, silly oversight. Thanks DP! :)
F Fix call order, thanks to DP
F Pass the right array to do_umode(), fixes mode tracking on Unreal. Thanks to DukePyrolator (yet again :P)
F Fix bs_set help, thanks to DukePyrolator! :)
F Fix two segfaults, noted by DukePyrolator. Thanks!
F Fix part one of #1010, reported by DukePyrolator. (Language settings are not respected in message sending.) Thanks!
F Memory leak on +beI modes.
Provided by Liber <Liber@jasonirc.net> - 2009
F Support operoverride and such things (stop reversing changes from nonopped people where unnecessary)
Anope Version 1.9.0
-------------------
F Modified compile to use g++
F Improve protocol modules support (classes, virtual methods, etc)
F Move core services to use BotInfo
F Move BotInfo and related methods into a class
F Move modules into a class
F Fixed ns resending of passcode issue
F Modules now delete themselves
F additional field where users' masked host can be stored so both masked IP and vhost are available instead of just one.
F No struct Uid, ugly, and, unnecessary that we store UID in BotInfo.
F Prevent deletion of core services via /bs bot
F Module subsystem cleanup ('modules' branch)
F Move modules to use classes somewhat (AnopeInit, AnopeFini)
F Change MODULE_INIT to return a pointer
F Remove duplicate module creation.. have loadModule return a pointer rather than creating one
F Remove buffered loading/unloading, this makes os_modunload perm, but who cares
F Remove 'delayed' loading, this is necessary because of before/after connected to ircd (ircd is before, rest after), I'm sure this can be done better.
A Remove old config, replace with insp-inspired (albeit bind format) config (CBX)
F Clean up protocol modules a bit
A InspIRCd 1.2 support
F Remove old (prior to 1.8.0) db compat
F Establish a proper base for services pseudoclients
F Add ss_main StatServ Hal9000 to play with :)
F Burn automake with fire (CBX)
Provided by mooncup <mooncup@anonnet.org> - 2009
F Automatically reapply vhost on hs off for unreal.

220
docs/Changes.conf Normal file
View File

@ -0,0 +1,220 @@
Anope Version 2.0.12
--------------------
Added the regex_pcre2 module
Anope Version 2.0.11
--------------------
No significant changes.
Anope Version 2.0.10
--------------------
No significant changes.
Anope Version 2.0.9
-------------------
No significant changes.
Anope Version 2.0.8
-------------------
Fix ns_register:unconfirmedexpire not being used
Anope Version 2.0.7
-------------------
Add nickserv/recover permission
Add inspircd3 protocol module
Add default permission for chanstats saset chanstats command
Anope Version 2.0.6
-------------------
Mark enc_md5 and enc_sha1 as deprecated. Their use has been discouraged for years, and they will be removed in a future release.
Exempt all of 127.0.0.0/8 from m_dnsbl by default
Load m_sasl by default
Fix documentation for nickserv default option ns_keep_modes
Anope Version 2.0.5
-------------------
No significant changes.
Anope Version 2.0.4
-------------------
Removed m_sasl_dh-aes and m_sasl_dh-blowfish
Anope Version 2.0.3
-------------------
Add operserv/chankill to default globops log
Add ns_identify:maxlogins to limit the max number of concurrent logins per account
Document ns_no_expire nickserv default
Remove default session exception expiry time
Anope Version 2.0.2
-------------------
Add an operserv/oper/modify privilege, required to use oper add and oper del
Add a chanserv/access/list privilege, which allow readonly access to ChanServ access and akick lists
Changed m_dnsbl's result configuration to be more extensible
Add 'max' setting to cs_mode
Add 'nickchars' setting to networkinfo
Add 'botserv/fantasy', 'chanserv/access/list', and 'operserv/oper/modify' oper privileges
Fix 'emailchange_message' to include the proper email address
Set a default permission on operserv/defcon
Anope Version 2.0.1
-------------------
Add MUTE command to BotServ fantasy configuration
Document memo_mail option in nickserv.conf
Add 'show' setting to ns_info and cs_info to control which fields are shown to non opers
Anope Version 2.0.0
-------------------
options:passlen, enforceruser, enforcerhost, releasetimeout, and guestnickprefix moved to nickserv's module configuration
options:hideregisteredcommands added
m_ssl renamed to m_ssl_openssl
mail:restrict removed
Anope Version 1.9.9
-------------------
There is not many config changes between 1.9.8 and 1.9.9, however many of the
options have been moved around to make more sense, too many to list here,
so get a new config.
Anope Version 1.9.8
-------------------
networkinfo:chanlen added
options:user and options:group added
nickserv:modesonid added to set modes on everyone who identifies
nickserv:kill and nickserv:killquick added to configure NickServ's kill timeout
nickserv:restoreonrecover added to try to restore a user's session after a ghost
command:group added
fantasy block added
dns block has been moved to modules.conf as a part of m_dns
Anope Version 1.9.7
-------------------
operserv:notifications removed in favor of log{} blocks
options:regexengine added
options:casemap added
chanserv:require added
nickserv:registration added, emailregistration removed.
nickserv:unregistered_notice added
Anope Version 1.9.6
-------------------
service:channels added to join services to channels
mail block modified to allow configuring of email messages
oper:host and oper:vhost added
oper:require_oper added
options:nonicknameownership added
operserv:akillids added
nickserv/access oper privilege added
Anope Version 1.9.5
-------------------
Don't even try it, get a new config and start over.
Anope Version 1.9.4
-------------------
** ADDED CONFIGURATION DIRECTIVES **
memoserv:modules added ms_ignore
chanserv:modules added cs_clone and cs_mode
nickserv:suspendexpire and nickserv:forbidexpire added
chanserv:suspendexpire and chanserv:forbidexpire added
module added cs_entrymsg
nickserv:modules added ns_ajoin, ns_cert
options:nomlock added
log:target added globops
nickserv:confirmemailchanges added
operserv:modules added os_config, os_login
** MODIFIED CONFIGURATION DIRECTIVES **
operserv:notifications removed osglobal, osmode, oskick, osakill, ossnline, ossqline, osszline, osnoop, osjupe, getpass, setpass, forbid, drop
renamed nickserv:preregexpire to nickserv:unconfirmedexpire
** DELETED CONFIGURATION DIRECTIVES **
opertype:commands removed operserv/umode
operserv:modules removed os_umode
Anope Version 1.9.3
-------------------
** ADDED CONFIGURATION DIRECTIVES **
nickserv/auspex privilege added
SSL module added for SSL support
opertype:inherits added to allow opertypes to inherit commands and privs from other opertypes
Various nickserv/saset/* and chanserv/saset/* opertype command privileges added
nickserv:modules added many new ns_set_command modules
chanserv:modules added many new cs_set_command modules
opertype:commands added nickserv/saset/* and chanserv/saset/*
options:socketengine added to choose what socket engine to use
module:cs_set_misc and module:ns_set_misc added to replace the old set url/icq/email modules
options:hideprivilegedcommands added to hide privileged commands from normal users
log block added to customize logging
dns block added to configure dns settings
m_dnsbl added
mysql configuration block added
** MODIFIED CONFIGURATION DIRECTIVES **
opertype:commands changed operserv/sgline to opserv/snline
operserv:modules changed os_sgline to os_snline
operserv:modules added os_modreload
operserv:sglineexpiry changed to operserv:snlineexpiry
operserv:killonsgline changed to operserv:killonsnline
operserv:notifications ossgline changed ossnline
memoserv was made optional
moved operserv:global configuration into its own global block
chanserv was made optional
** DELETED CONFIGURATION DIRECTIVES **
serverinfo:helpchannel removed because it has been readded in m_helpchan
networkinfo:logchannel, logbot, logusers, logmaxusers, logchannel, and options:keeplogs removed because of the log block
dumpcore because it really didn't do anything
Anope Version 1.9.2
-------------------
** ADDED CONFIGURATION DIRECTIVES **
options:enablelogchannel added to auto turn on the logchannel on startup
options:mlock added to configure the default mlock modes on new channels
options:database added for the database modules
options:botmodes added to configure modes BotServ bots should use
options:userlen added to configure maximum ident length
options:hostlen added to configure maximum hostname length
options:database added to configure what database modules to use
options:passlen added to specify the maximum length of passwords
uplink:ipv6 added to enable IPv6 connectivity
options:maxretries added to specify the number of reconnect attempts allowed
options:retrywait added to specify how long to wait between reconnect attempts
opertype command chanserv/aop/list removed as it was unnecessary, use chanserv/access/list instead
** MODIFIED CONFIGURATION DIRECTIVES **
options:encryption added enc_sha256
chanserv:modules added cs_unban
nickserv:modules added ns_resetpass
** DELETED CONFIGURATION DIRECTIVES **
nickserv:database deleted because of new database system
nickserv:prenickdatabase deleted because of new database system
chanserv:database deleted because of the new database system
botserv:database deleted because of the new database system
hostserv:database deleted because of the new database system
operserv:database deleted because of the new database system
operserv:newsdatabase deleted because of the new database system
operserv:exceptiondatabase deleted because of the new database system
hs_request:database deleted because of the new database system
os_ignore:database deleted because of the new database system
serverinfo:localport deleted
Anope Version 1.9.1
-------------------
** ADDED CONFIGURATION DIRECTIVES **
Opertypes have been added, through the opertype blocks.
Services Operators are now specified in the oper blocks.
** MODIFIED CONFIGURATION DIRECTIVES **
botserv:modules no longer contains bs_fantasy* modules, fantasy is now seamless.
operserv:modules has replaced os_logonnews, os_opernews, and os_randomnews with os_news.
operserv:modules no longer contains os_admin and os_oper modules, removed in favor of oper blocks.
operserv:notifications no longer contains osraw due to removal of OS RAW.
** DELETED CONFIGURATION DIRECTIVES **
Nick tracking has been removed as an option.
Restricting of NS GETPASS and CS GETPASS removed in favor of opertypes.
Host Setters were removed in favor of opertypes.
HelpServ has been removed entirely.
operserv:disableraw removed due to removal of OS RAW.

93
docs/DEFCON Normal file
View File

@ -0,0 +1,93 @@
Anope DefCon
------------
1) Introduction
2) Installation
3) Configuration
4) Usage
5) Usage Example
6) Support
1) Introduction
Anope 1.6 onwards supports a unique protection mechanism based on the
military "Defense Readiness Condition" (DefCon) system. It is based on
5 levels of defense readiness defined as:
DEFCON5 Normal peacetime readiness
DEFCON4 Increased intelligence and security readiness
DEFCON3 Increase in force readiness
DEFCON2 Further increase in force readiness
DEFCON1 Maximum force readiness.
These are configurable levels that mandates what actions Anope should
take in case of emergency and change in readiness status.
It is used to prevent abuse to both Services, and the ircd on which they
are running. Also to protect the users, primarily in the event of Clones
and/or FloodBOT attacks.
2) Installation
The DefCon system is part of Anope's core,
The DefCon system has to be configured on your operserv.conf file to
be enabled. Defcon will be disabled if "defaultlevel" in the defcon
block is left commented, or set to 0. Look for the defcon block
on your operserv.conf file for more information on enabling and
configuring it.
Make sure you restart Anope after changing the DefCon configuration
directives.
3) Configuration
Pre-defined DefCon actions:
No new channel registrations
No New Nick Registrations
No Mode Lock changes
Force Chan Mode
Use Reduced Session Limit
KILL any new clients trying to connect
Services will ignore everyone but opers
Services will silently ignore everyone but opers
AKILL all new clients trying to connect
No new memos sent to block MemoServ attacks
Information regarding how to enable this for specific defcon levels can
be found in operserv.conf
4) Usage
Anope starts up in DEFCON5 (normal readiness). To change the Defcon level
in action use:
/msg OperServ DEFCON 1|2|3|4|5
5) Usage Example
Place the network on DEFCON4:
/msg OperServ DEFCON 4
-OperServ- Services are now at DEFCON 4
-OperServ- * No new channel registrations
-OperServ- * No new nick registrations
-OperServ- * No mode lock changes
-OperServ- * Use the reduced session limit of 5
-Global- The Defcon Level is now at: 4
Restore normal readiness:
/msg OperServ DEFCON 5
-OperServ- Services are now at DEFCON 5
-Global- Services are now back to normal, sorry for any inconvenience
6) Support
You might get DefCon support by posting on our online forum, or maybe on
our #anope channel at /server irc.anope.org.

34
docs/EVENTS Normal file
View File

@ -0,0 +1,34 @@
Anope Internal Events
---------------------
1) Intro
2) Using Events
1) Introduction to Internal Events
Internal Events are setup to give module developers more information
about what the core is doing at different times. This information can
be as complex as data we are feeding to the uplink, to simple triggered
events such as the databases being saved.
Additionally there is a module included with the core
which can provide some clue as to how to use the code in your modules.
The rest of this document assumes that you are used to writing modules.
2) Using Events
Each Event in Anope calls a function.
You must override these functions in your main modules class.
The full list of functions and parameters are in modules.h. In this
case, you would be overriding OnJoinChannel() and OnPartChannel() like so:
void OnJoinChannel(User *u, Channel *c) anope_override { }
void OnPartChannel(User *u, Channel *c) anope_override { }
Some of these event overrides can be used to prevent or allow things to
happen that would normally not be allowed or denied. You can also use
ModuleManager (not explained here) to set control which order the modules
are queried (when multiple modules hook to the same event).
The "anope_override" identifier is for compatibility with C++11.
Its usage is highly recommended.

10
docs/FAQ Normal file
View File

@ -0,0 +1,10 @@
Frequently Asked Questions (FAQ) concerning Anope
-------------------------------------------------
The information in the 2.0 FAQ is subject to change at any
moment due to new developments. Please visit our website
for the most up to date information.
An updated version of the FAQ can be found here:
https://wiki.anope.org/index.php/2.0/FAQ

135
docs/INSTALL Normal file
View File

@ -0,0 +1,135 @@
Anope Installation Instructions
-------------------------------
1) Installing Anope
2) Upgrading Anope
3) Setting up the IRCd
4) Starting Anope
5) Setting up a crontab
Note: You should also read the README and FAQ files!
1) Installing Anope
IMPORTANT NOTE: it is not recommended to use (and therefore install)
Anope as root. Use an unprivileged user instead -- the
one you're using for the ircd or a dedicated one will
be good enough.
The very first thing you need to do is to get the Anope package (if not
already done). You can find it at:
https://www.anope.org/
Anope requires cmake to build. You can check if CMake is already
installed on your system using the command:
cmake --version
If it's installed, you will get a line that says something similar to
"cmake version 2.8.12.2". If the version is less than 2.4 or you get
an error saying the command was not found, you will not be able to use
CMake unless you install it yourself into your home directory. CMake
can be downloaded from:
https://cmake.org/download/
Next, unpack the package in your home directory, and go into the created
directory.
If there are any extra modules you want to enable, such as m_mysql, run
the 'extras' script to enable them. If you do not know you can come back
later and enable them.
Now type ./Config to start the configuration script. It will ask you a
few questions, and figure out how to compile Anope on your system. If
you are unsure about the answer to a question, use the default value.
Now cd build and type make and make install. This will install
all the needed files in the paths you specified with the configure
script, and setup file permissions. You should ensure that the data
directory is not accessible by other users, as malicious users may
cause trouble on your network if passwords are not encrypted, or read
the memos of any user.
Now go into the conf directory (by default, ~/services/conf). Copy the example
configuration file (example.conf) to services.conf, and open the latter
with your favorite text editor. It contains all the configuration
directives Anope will use at startup. Read the instructions contained in
the file carefully. Using the default values is NOT a good idea, and will
most likely not work!
If you need help, you should visit https://forum.anope.org/ or #anope on
irc.anope.org. Provide *complete* error output, along with other relevant
information eg. OS, compiler and C++ library versions.
See the README file for more information.
2) Upgrading Anope
To upgrade Anope, just follow the installation instructions described in
section 1. There are however a few specific guidelines:
* IMPORTANT: Back up your old databases!
* If you are upgrading to a new major release, ALWAYS restart a
fresh configuration file from example.conf.
3) Setting up the IRCd
Services acts as an IRC server with pseudo-clients on it. To link them to
your network, you'll need to configure your IRCd to allow services to link.
The configuration varies depending on the IRCd, but you will probably need
a link block (also called connect block, or C line), a U line (also called
a shared block), and be sure that the IRCd is listening on the given port
in the link block.
Example link configurations can be found in example.conf for some of the
popular IRCds.
Don't forget to /rehash your IRCd to apply changes.
You may also try our interactive link maker, which is located at:
https://www.anope.org/ilm.php
4) Starting Anope
Go into the directory where binaries were installed (by default, this is
~/services/bin). Type ./services to launch Anope.
If there are syntax errors in the configuration file they will be
displayed on the screen. Correct them until there are no errors anymore.
A successful startup won't generate any message.
Give Services at least one minute to link to your network, as certain
IRCds on some OSes may be really slow for the link process. If nothing
happens after about a minute, it is probably a configuration problem. Try
to launch Anope with ./services -debug -nofork to see any errors that it
encounters, and try to correct them.
If you need help to solve errors, feel free to subscribe to the Anope
mailing list and ask there. See the README file for details.
5) Setting up a crontab
A crontab entry will allow you to check periodically whether Anope is
still running, and restart it if not.
First rename the example.chk script that is in Anope path (by default,
this is ~/services/conf) to services.chk and edit it. You'll need to
modify the CONFIGURATION part of the file. Then ensure that the file is
marked as executable by typing chmod +x services.chk, and try to launch the
script to see if it works (Anope must not be running when you do this ;))
When this is done, you'll have to add the crontab entry. Type crontab -e.
This will open the default text editor with the crontab file. Enter the
following (with correct path):
*/5 * * * * /home/ircd/services/conf/services.chk >/dev/null 2>&1
The */5 at the beginning means "check every 5 minutes". You may replace
the 5 with other another number if you want (but less than 60). Consult
your system's manual pages for more details on the syntax of the crontab
file. Interesting manpages are crontab(5), crontab(1) and cron(8).
Save and exit, and it's installed.

149
docs/INSTALL.fr Normal file
View File

@ -0,0 +1,149 @@
Instructions d'installation d'Anope
-----------------------------------
1) Installation d'Anope
2) Mettre à jour Anope
3) Configuration de l'IRCd
4) Mettre en route Anope
5) Mettre en place un crontab
Note : Vous devrez également lire les fichiers README et FAQ !
1) Installation d'Anope
NOTE IMPORTANTE : il est déconseillé d'utiliser (et même d'installer)
Anope en tant que root. Utilisez un utilisateur non
privilégié. Celui que vous utilisez pour l'IRCd ou
un utilisateur dédié suffira.
La première chose que vous devez faire est d'obtenir le package Anope
(si ce n'est déjà fait). Vous pouvez le trouver ici :
https://www.anope.org/
Anope nécessite cmake pour être compilé. Vous pouvez vérifier si CMake
est déjà installé sur votre système avec la commande :
cmake --version
Si CMake est installé, vous aurez une ligne qui dit quelque chose comme
"cmake version 2.8.12.2". Si la version est inférieure à 2.4 ou si vous
obtenez une erreur disant que la commande n'a pas été trouvée, vous ne
pourrez pas utiliser CMake à moins de l'installer vous-même dans votre
répertoire home. CMake peut être téléchargé ici :
https://cmake.org/download/
Ensuite, décompressez le package dans votre répertoire home, et allez
dans le répértoire qui vient d'être créé.
Si il y a des modules facultatifs que vous voulez activer comme m_mysql,
exécuter le script 'extras' pour les activer. Si vous ne savez pas, vous
pouvez les activer plus tard.
Maintenant, tapez ./Config pour lancer le script de configuration. Il
va vous poser quelques questions, et déterminer comment compiler Anope
sur votre système. Si vous ne savez pas comment répondre à une question,
utilisez la valeur par défaut.
Allez dans le dossier build (cd build) et tapez make et make install.
Ceci va installer tous les fichiers nécessaires dans les dossiers que
vous avez indiqués avec le script Config et régler les permissions des
fichiers. Vous devez vous assurer que le répertoire data n'est pas
accessible par les autres utilisateurs, car des utilisateurs
malveillants pourraient causer des problèmes sur votre réseau, si les
mots de passe ne sont pas chiffrés, ou lire les mémos de tous les
utilisateurs.
Allez maintenant dans le répertoire conf (par défaut, ~/services/conf).
Copiez l'exemple de fichier de configuration (example.conf) en
services.conf et ouvrez ce dernier avec votre éditeur de texte favori.
Il contient toutes les directives de configuration qu'Anope va utiliser
en démarrant. Lisez attentivement les instructions contenues dans le
fichier. L'utilisation des valeurs par défaut n'est pas toujours
recommandée, et Anope ne fonctionnera probablement pas !
Si vous avez besoin d'aide, vous pouvez aller sur le site
https://forum.anope.org/ ou le canal #anope sur irc.anope.org.
Fournissez *l'essemble* des erreurs qui apparaîssent, en plus de
toutes informations utiles, comme les versions de votre OS, du
compilateur utilisé et de la librairie C++. Lisez le fichier README
pour plus d'informations.
2) Mettre à jour Anope
Pour mettre à jour Anope, suivez simplement les instructions
d'installation décrites dans la section 1. Prenez garde cependant :
* IMPORTANT : Sauvegardez vos anciennes bases de données !
* Si vous mettez à jour vers une nouvelle version majeure,
recommencez *toujours* toute votre configuration à partir du
fichier example.conf.
3) Configuration de l'IRCd
Les Services agissent comme un serveur IRC avec des pseudo-clients.
Pour les relier à votre réseau, vous aurez besoin de configurer votre
IRCd pour permettre aux services de se connecter.
La configuration dépend de l'IRCd utilisé, mais vous aurez probablement
besoin d'un bloc link (aussi appelé connect block, ou C:line) et un
U:line (aussi appelé shared block). Assurez-vous que l'IRCd écoute
sur le port donné dans le bloc link.
Des exemples de configurations de bloc link peuvent être trouvés dans
le fichier example.conf pour certains des IRCd les plus populaires.
Souvenez-vous de /rehash votre IRCd pour appliquer les changements.
Vous pouvez également essayer notre créateur de bloc link interactif
situé ici :
https://www.anope.org/ilm.php
4) Mettre en route Anope
Allez dans le répertoire où les fichiers binaires ont été installés
(par défaut, ~/services/bin). Tapez ./services pour lancer Anope.
S'il y a des erreurs de syntaxe dans le fichier de configuration, elles
seront affichées à l'écran. Corrigez-les jusqu'à ce qu'il n'y en ait
plus. Un démarrage réussi ne générera pas de message.
Donnez aux services au moins une minute pour se connecter à votre
réseau, car certains IRCds sur certains systèmes peuvent être très
lents pour le processus de liaison. Si rien ne se passe après environ
une minute, il y a probablement un problème de configuration. Essayez
de lancer Anope en mode debug avec ./services -debug -nofork pour voir
toutes les erreurs rencontrées et essayez de les corriger.
Si vous avez besoin d'aide pour résoudre des erreurs, n'hésitez pas à
vous abonner à la liste de diffusion Anope et d'y poser vos question.
Voir le fichier README pour plus de détails.
5) Mettre en place un crontab
Une entrée crontab vous permettra de vérifier périodiquement si Anope
est toujours en cours d'exécution et de le redémarrer s'il n'est pas.
D'abord renommez le script example.chk qui est dans les dossiers
d'Anope (par défaut, ~/services/conf) en services.chk et modifiez-le.
Vous aurez besoin de modifier la partie CONFIGURATION du fichier.
Assurez-vous ensuite que le fichier est marqué comme exécutable en
tapant chmod +x services.chk et essayez de lancer le script pour voir
si cela fonctionne (Anope ne doit pas être en marche lorsque vous
testez cela ;))
Lorsque c'est fait, vous devrez ajouter l'entrée crontab. Entrez
crontab -e. Cela va ouvrir l'éditeur de texte par défaut avec le
fichier crontab. Entrez la ligne suivante (avec le chemin correct) :
*/5 * * * * /home/ircd/services/conf/services.chk > /dev/null 2>&1
Le */5 au début signifie "vérifier toutes les 5 minutes". Vous pouvez
remplacer le 5 par un autre numéro si vous voulez (mais moins de 60).
Consultez les pages de manuel de votre système pour plus de détails sur
la syntaxe du fichier crontab. Les pages de manuel intéressantes sont
crontab(5), crontab(1) et cron(8).
Sauvegardez, quittez, et c'est installé !

53
docs/LANGUAGE Normal file
View File

@ -0,0 +1,53 @@
Anope Multi Language Support
----------------------------
1) Building Anope with gettext support
2) Adding a new language
3) Using languages with modules
1) Building Anope with gettext 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 Ubuntu run locale-gen for each language you want to enable.
For example:
locale-gen es_ES.UTF-8
Then execute:
dpkg-reconfigure locales
Building Anope on Windows with gettext support is explained in docs/WIN32.txt
2) Adding a new language
Anope uses gettext (https://www.gnu.org/software/gettext/) to translate messages for users. To add a new language
install gettext and run `msginit -l language -o anope.language.po -i anope.pot`. For example if I was translating to
Spanish I could run `msginit -l es_ES -o anope.es_ES.po -i anope.pot`. Open the newly generating .po file and start
translating. Once you are done simply rerun ./Config; make && make install and add the language to your services.conf.
Note that on Windows it is not quite this simple, windows.cpp must be edited and Anope recompiled and restarted.
Poedit (https://poedit.net/) is a popular po file editor, and we recommend using it or another editor designed to edit
po files (especially on Windows).
If you have finished a language file translation and you want others to use it, please send it to team@anope.org
(don't forget to mention clearly your (nick)name, your e-mail and the language name). You'll of course get full credit for it.
NOTE: There is no guarantee we will use your work so please do not be offended if we say no thanks.
3) Using languages with modules
Module authors can easily add the ability to have their modules translated by adding _() around the strings they
want translated (messages to the user, etc).
If you want to translate a module someone has made, first generate a .pot file if there isn't one already using
`xgettext -s -d modulename -o modulename.pot --from-code=utf-8 --keyword --keyword=_ modulename.cpp`.
The .pot file is a template of all of the language strings extracted from the source file.
Next, run msginit on the .pot file with
`msginit -l language -o modulename.language.po -i modulename.pot`.
Translate the new .po file and rerun ./Config; make && make install.
All .po and .pot files should be placed in modules/third/language. Additionally an update script is provided there
that will create .pot files and merge any changes to it with existing .po files.

128
docs/MODULES Normal file
View File

@ -0,0 +1,128 @@
Anope Modules
-------------
1) Introduction
2) Installation
3) Usage
4) Usage Example
5) More Modules
6) Support
7) Information for Developers
8) Modules Repository
1) Introduction
Anope 1.6 onwards supports external modules. External modules are pieces
of code that can be attached to a running Anope process dynamically. These
modules can serve several purposes, and perform all kind of operations to
enhance your network.
2) Installation
1. If modules are supported by your system, they will be configured
automatically when you run ./Config. The modules will be installed
to the modules directory in your data path (by default this will
be ~/services/data/modules).
2. Compile Anope as usual using ./Config. The "make" process will now
compile module support into Anope, and compile the default sample
modules, and any other module located in the modules folder or any
of its sub-directories, eg. modules/extra.
3. Install Anope as usual. The "make install" process will place the
compiled modules in their runtime location, making them available
for loading.
4. Start or restart services to make use of the new Anope executable.
Note that you do not need to restart to load new or changed modules,
only to make use of a new Anope executable.
3) Usage
All module manipulation commands are done through OperServ. These are:
MODLOAD Load a module
MODRELOAD Reload a module
MODUNLOAD Un-Load a module
MODLIST List loaded modules
MODINFO Info about a loaded module
Access to the above commands require the operserv/modload and modlist
permissions. Refer to operserv.example.conf.
You can also load (and pre-load) Modules automatically by loading them
on startup. To do so, edit any one of the configuration files (you may
want to use modules.conf for third-party/extra modules, or a config
file relevant to the *Serv your module operates on, eg. hostserv.conf),
and use the following method to load a module on startup or reload:
module { name="hs_modname" }
4) Usage Example
/msg OperServ modload ns_identify
-OperServ- Module ns_identify loaded
/msg OperServ modinfo ns_identify
-OperServ- Module: ns_identify Version: 1.9.7 Author: Anope loaded: Jun 17 18:43:08 2012 BST (2 minutes ago)
-OperServ- Providing service: nickserv/identify
-OperServ- Command ID on NickServ is linked to nickserv/identify
-OperServ- Command IDENTIFY on NickServ is linked to nickserv/identify
/msg OperServ modreload ns_identify
-OperServ- Module ns_identify reloaded
/msg OperServ modunload ns_identify
-OperServ- Module ns_identify unloaded
/msg NickServ IDENTIFY
-NickServ- Unknown command identify. "/msg NickServ HELP" for help.
NOTE: Doing the above, with the command still existing in a config file,
will result in a log message, similar to the following:
<@NickServ> Command IDENTIFY exists on me, but its service nickserv/identify was not found!
* Note that the name of the module source file is "ns_identify.cpp", yet we
load and reference the module as "ns_identify" only. By naming convention
modules have an abbreviated service name they attach to (hs_ for
HostServ, cs_ for ChanServ, etc) followed by a descriptive keyword.
5) More Modules
You can download more useful modules from https://modules.anope.org/. Just
grab the module file (usually with a .cpp extension). Place the module
file in your modules (anope-1.9.x/modules/third) folder; although any of
the other folders within the modules directory will work.
The new modules need to be compiled and installed before you can make
use of them:
1. Make sure you're in the main source directory. (usually anope-1.X.XX/)
2. Run ./Config to find and configure modules, then `cd build`.
3. Run `make` to compile Anope, and any modules.
4. Run `make install` to copy the compiled binaries to the ~/services/
directory.
You can now use /msg OperServ MODLOAD to load the new modules.
6) Support
The Anope team is not responsible or liable for any unofficial module
(i.e. anything other than what was released with the Anope package).
Use modules at your own risk, and make sure you get them from a
reputable source. You might get module support by contacting the module
author, posting on our online forum, or maybe on our #anope channel
at /server irc.anope.org.
7) Information for Developers
There are a number of useful documents on the Anope Wiki. The Anope Wiki
can be reached at:
* https://wiki.anope.org/
8) Modules Repository
You can find modules at https://modules.anope.org/
These modules are 3rd party and as such are not supported by the Anope Team.
Contact the Module Author directly with problems, not the Anope Team.

6
docs/NEWS Normal file
View File

@ -0,0 +1,6 @@
Highlighted News in Anope 1.9
=============================
* Added in live updating SQL and the ability to execute commands through SQL
* Re-designed configuration file
* Code refresh / rewrite into C++

258
docs/README Normal file
View File

@ -0,0 +1,258 @@
Anope -- a set of IRC services for IRC networks
-----------------------------------------------
Anope is 2003-2022 Anope Team <team@anope.org>.
Based on Epona 2000-2002 PegSoft <epona@pegsoft.net>.
Based on Services 1996-1999 Andrew Church <achurch@achurch.org>.
This program is free but copyrighted software; see the file COPYING for
details.
Information about Anope may be found at https://www.anope.org/
Table of Contents
-----------------
1) Credits
2) Presentation
3) Installation
4) Command Line Options
5) Messages Translation
6) Contact
1) Credits
Anope is based on Lara's Epona version 1.4.14.
Epona is based on Andy Church's IRC Services version 4.3.3.
The original credits:
* Mauritz Antunes
Portuguese translation
* Jose R. Holzmann, Raul S. Villarreal
Spanish translation
* Andrew Kempe <theshadow@shadowfire.org>
News system
* <d.duca@eurcom.net>
Italian translation
* <mikado@holyfire.com>
Turkish translation
* Andrew Kempe <theshadow@shadowfire.org>
Session limiting
Epona credits:
* lara <lara@pegsoft.net>
Main coding
* CafeiN <oytuny@yahoo.com>
Turkish translation
* Sylvain Cresto aka tost <scresto@netsante.fr>
FreeBSD 5 patch
* Marcelo Conde Foscarini aka Bras <ircadmin@brmarket.net>
Portuguese translation
* Alvaro Toledo aka POLLITO <atoledo@keldon.org>
Spanish translation
* chemical <chemical@musicplay.de>
German translation
* shine <dh@shinewelt.de>
German translation
* Guven Guzelbey aka MeShGuL <guzelbey@cs.utk.edu>
Turkish translation
* Jordi Pujol <jordi.pujol@aujac.org>
Catalan translation
* Eva Dachs <evadachs@terra.es>
Catalan translation
* Toni Perez <toni.perez@aujac.org>
Catalan translation
* Sergios Karalis <sergios_k@hotmail.com>
Greek translation
* Thomas J. Stensas aka ShadowMaster <shadowmaster@shadow-realm.org>
Ultimate 3.x support
Anope credits:
* Adam Kramer <ribosome@anope.org>
* Adam <adam@anope.org>
* Alvaro Toledo <atoledo@keldon.org>
* Amanda Folson <amanda@anope.org>
* Andrew Berquist <vash@anope.org>
* Björn Stiddien <keeper@anope.org>
* Charles Kingsley <chaz@anope.org>
* Chris Hogben <heinz@anope.org>
* Daniel Engel <dane@zero.org>
* David <dv@diboo.net>
* David Narayan <jester@phrixus.net>
* David Robson <rob@anope.org>
* Daniele Nicolucci <jollino@sogno.net>
* Florian Schulze <certus@anope.org>
* Gabriel Acevedo H. <drstein@anope.org>
* Jan Milants <viper@anope.org>
* Jens Voss <dukepyrolator@anope.org>
* JH <jh@irc-chat.net>
* Joris Vink <joris@anope.org>
* Lee Holmes <lethality@anope.org>
* Lucas Nussbaum <lucas@lucas-nussbaum.net>
* Mark Summers <mark@goopler.net>
* Matthew Beeching <jobe@mdbnet.co.uk>
* Naram Qashat <cyberbotx@anope.org>
* Phil Lavin <phil@anope.org>
* Pieter Bootsma <geniusdex@anope.org>
* Robin Burchell <w00t@inspircd.org>
* Sean Roe <therock247uk@anope.org>
* Sebastian V <hal9000@anope.org>
* Thomas Juberg Stensås <ShadowMaster@Shadow-Realm.org>
* Trystan .S Lee <trystan@nomadirc.net>
* openglx <openglx@brasnerd.com.br>
Anope Translations:
* Robby <robby@chatbelgie.be> (nl_NL)
* Kein <kein-of@yandex.ru> (ru_RU)
* Maik Funke <Han@mefalcon.org> (de_DE)
* Isaac Fontal <i_fontal@hotmail.com> (es_ES)
* Janos Kapitany <sarkanyka@cjbchat.hu> (hu_HU)
* Szymon S'wierkosz <szymek@adres.pl> (pl_PL)
* Christopher N. <saka@epiknet.org> (fr_FR)
* Yusuf Kurekci <ysfm.20@gmail.com> (tr_TR)
Anope Web panel:
* Denis M. (Phr33d0m) <god@politeia.in>
2) Presentation
Anope is a set of Services for IRC networks that allows users to manage
their nicks and channels in a secure and efficient way, and administrators
to manage their network with powerful tools.
Currently available services are:
* NickServ, a powerful nickname manager that users can use to protect
themselves against nick stealing. Each user has its own nickname
group, that allows the user to register as many nicks as needed
while still being able to take profit of his privileges and to
modify the nick configuration. NickServ also has an optional
password retrieval feature.
* ChanServ, a powerful channel manager that helps users to administer
their channels in a totally customizable way. ChanServ has an
internal list of privileged users and banned users that controls
accesses on a per-channel basis. It eliminates all takeover
problems, because of its powerful op/unban/invite and even mass
deop and mass kick functions.
* MemoServ, an helpful companion that allows sending short messages
to offline users, that they can then read when they come online
later.
* BotServ, an original service that allows users to get a permanent,
friendly bot on their channels in an easy way. Each bot can be
configured to monitor the channels against floods, repetitions,
caps writing, and swearing, and to take appropriate actions. It
also can handle user-friendly commands (like !op, !deop, !voice,
!devoice, !kick, and many others), say a short greet message when
an user joins a channel, and even "take over" ChanServ actions such
as auto-opping users, saying the entry notice, and so on. This
service can be disabled if you want to save some bandwidth.
* OperServ, the IRCops' and IRC admins' black box, that allows them
to manage the list of network bans (also known as AKILL (DALnet) or
GLINE (Undernet)), to configure messages displayed to users when
they log on, to set modes and to kick users from any channel, to
send notices quickly to the entire network, and much more!
* HostServ, a neat service that allows users to show custom vHosts
(virtual hosts) instead of their real IP address; this only works
on daemons supporting ip cloaking, such as UnrealIRCd.
Anope currently works with:
* Bahamut 1.4.27 or later (including 1.8)
* Charybdis 3.4 or later
* ircd-hybrid 8.2.23 or later
* InspIRCd 1.2 or later
* ngIRCd 19.2 or later
* Plexus 3 or later
* Ratbox 2.0.6 or later
* UnrealIRCd 3.2 or later
Anope could also work with some of the daemons derived by the ones listed
above, but there's no support for them if they work or don't work.
3) Installation
See the INSTALL file for instruction on installing Anope.
4) Command Line Options
Normally, Anope can be run simply by invoking the "services" executable.
Any of the following command-line options can be specified to change
the behavior of Anope:
--debug Enable debugging mode; more info sent to log (give
option more times for more info)
--readonly Enable read-only mode; no changes to databases
allowed
--nofork Do not fork after startup; log messages will be
written to terminal
--noexpire Expiration routines won't be run at all
--version Display the version of Anope
--nothird Do not load the non-core modules specified
--protocoldebug Debug each incoming message after protocol parsing
--support Used for support, same as --debug --nofork --nothird
Upon starting, Anope will parse its command-line parameters then
(assuming the --nofork option is not given) detach itself and run in the
background. If Anope encounters a problem reading the database files or
cannot connect to its uplink server, it will terminate immediately;
otherwise, it will run until the connection is terminated (or a QUIT,
SHUTDOWN, or RESTART command is sent; see OperServ's help).
In the case of an error, an appropriate error message will be written to
the log file.
If Anope is run with the "--readonly" command-line option, it can serve as
a "backup" to the full version of services. A "full" version of services
(run without --readonly) will automatically reintroduce its pseudo-clients
(NickServ, ChanServ, etc.), while a "backup" services will not, thus
allowing full services to be brought up at any time without disrupting
the network (and without having to take backup services down beforehand).
The "--debug" option is useful if you find or suspect a problem in Anope.
Giving it once on the command line will cause all traffic to and from
services as well as some other debugging information to be recorded in
the log file; if you send a bug report, PLEASE include an excerpt from
the log file WITH DEBUGGING ACTIVE; we cannot emphasize enough how
important this is to tracking down problems. (You can also enable
debugging while Services is running using OperServ's SET DEBUG command.)
If you repeat use --debug=<level>, the debugging level will be increased,
which provides more detailed information but may also slow Anope down
considerably and make the log file grow dramatically faster. In general,
a debug level of 1 is sufficient for the coding team to be able to trace
a problem, because all network traffic is included and we can usually
reproduce the problem.
5) Messages Translations
Please see LANGUAGE for this information
6) Contact
For announcements and discussions about Anope, please visit our
Portal and Forums at https://www.anope.org/ -- make sure you register
yourself to get full benefits.
If you read the documentation carefully, and didn't find the answer to
your question, feel free to post on the website forums or join our irc
channel (irc.anope.org #anope). Once you join our Support channel be as
precise as possible when asking a question, because we have no extraordinary
powers and can't guess things if they aren't provided.
The more precise you are the sooner you'll be likely to get an answer.
If you think you found a bug, add it to the bug tracking system
(https://bugs.anope.org/) and - again - be as precise as possible. Also say
whether the bug happens always or under what circumstances, and anything
that could be useful to track your bug down. If you wrote a patch, send
it over. :)

160
docs/REDIS Normal file
View File

@ -0,0 +1,160 @@
Starting in Anope 1.9.9, Anope has Redis database support (https://redis.io/).
This document explains the data structure used by Anope, and explains how
keyspace notification works.
This is not a tutorial on how to use Redis, see https://redis.io/documentation
for that.
Table of Contents
-----------------
1) Data structure
2) Keyspace notifications
3) Examples of modifying, deleting, and creating objects
1) Data structure
There are 4 key namespaces in Anope, they are:
id - The keys in id are used to atomically create object ids for new
objects. For example, if I were to create a new BotInfo I would first:
redis 127.0.0.1:6379> INCR id:BotInfo
To get the object ID of the new object.
ids - The keys in ids contain a set of all object ids of the given type.
For example:
redis 127.0.0.1:6379> SMEMBERS ids:BotInfo
Returns "1", "2", "3", "4", "5", "6", "7", "8" because I have 8 bots that
have IDs 1, 2, 3, 4, 5, 6, 7, and 8, respectively.
hash - The keys in hash are the actual objects, stored as hashes. For
example, if I had just looked up all BotInfo ids and wanted to iterate
over all of them, I would start by:
redis 127.0.0.1:6379> HGETALL hash:BotInfo:1
Which gets all keys and values from the hash of type BotInfo with id 1.
This may return:
"nick" -> "BotServ"
"user" -> "services"
"host" -> "services.anope.org"
"created" -> "1368704765"
value - The keys in value only exist to aid looking up object IDs. They
are sets of object IDs and are used to map key+value pairs to objects.
For example:
redis 127.0.0.1:6379> SMEMBERS value:NickAlias:nick:Adam
Returns a set of object ids of NickAlias objects that have the key
'nick' set to the value 'Adam' in its hash. Clearly this can only
ever contain at most one object, since it is not possible to have
more than one registered nick with the same name, but other keys
will contain more than one, such as:
redis 127.0.0.1:6379> SMEMBERS value:NickCore:email:adam@anope.org
Which would return all accounts with the email "adam@anope.org".
redis 127.0.0.1:6379> SMEMBERS value:ChanAccess:mask:Adam
Which would return all access entries set on the account "Adam".
Behavior similar to SQL's AND, can be achieved using the
SINTER command, which does set intersection on one or more sets.
2) Keyspace notifications
Redis 2.7 (unstable) and 2.8 (stable) and newer support keyspace notifications
(https://redis.io/topics/notifications). This allows Redis to notify Anope of
any external changes to objects in the database. Once notified, Anope will
immediately update the object. Otherwise, Anope keeps all objects in memory
and will not regularly read from the database once started.
You can use this to modify objects in Redis and have them immediately reflected
back into Anope. Additionally you can use this feature to run multiple Anope
instances simultaneously from the same database (see also, Redis database
replication).
To use keyspace notifications you MUST execute
redis 127.0.0.1:6379> CONFIG SET notify-keyspace-events KA
OK
or set notify-keyspace-events in redis.conf properly. Anope always executes
CONFIG SET when it first connects.
If you do not enable keyspace events properly Anope will be UNABLE to see any
object modifications you do.
The key space ids and value are managed entirely by Anope, you do
not (and should not) modify them. Once you modify the object (hash), Anope will
update them for you to correctly reflect any changes made to the object.
Finally, always use atomic operations. If you are inserting a new object with
multiple commands, or inserting multiple objects at once, specifically if the
objects depend on each other, you MUST use a transaction.
3) Examples of modifying, deleting, and creating objects
These examples will ONLY work if you meet the criteria in section 2.
If I want to change the email account 'Adam' to 'Adam@anope.org', I would execute the following:
redis 127.0.0.1:6379> SMEMBERS value:NickCore:display:Adam
Which returns a value of "1", which is the object id I want to modify.
Now to change the email:
redis 127.0.0.1:6379> HSET hash:NickCore:1 email Adam@anope.org
You can now see this in NickServ's INFO command:
-NickServ- Email address: Adam@anope.org
If I want to drop the account "Adam", I would execute the following:
redis 127.0.0.1:6379> SMEMBERS value:NickCore:display:Adam
Which returns a value of "1". I would then check:
redis 127.0.0.1:6379> SMEMBERS value:NickAlias:nc:Adam
To see what nicknames depend on this account to exist, as I will
have to remove those too. This returns the values "2", and "3".
Finally, I can drop the nick using a transaction via:
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> DEL hash:NickAlias:2
QUEUED
redis 127.0.0.1:6379> DEL hash:NickAlias:3
QUEUED
redis 127.0.0.1:6379> DEL hash:NickCore:1
QUEUED
redis 127.0.0.1:6379> EXEC
Or alternatively simply:
redis 127.0.0.1:6379> DEL hash:NickAlias:2 hash:NickAlias:3 hash:NickCore:1
If I wanted to create a BotServ bot, I would execute the following:
redis 127.0.0.1:6379> INCR id:BotInfo
Which returns a new object ID for me, in this example it will be "8".
Now I can create the object:
HMSET hash:BotInfo:8 nick redis user redis host services.anope.org realname "Services for IRC Networks"
Note if you are using HSET instead of HMSET you will need to use a transaction, as shown in the above example.
If you are watching your services logs you will immediately see:
USERS: redis!redis@services.anope.org (Services for IRC Networks) connected to the network (services.anope.org)
And the bot redis will be in BotServ's bot list.
Notice how ids:BotInfo and the value keys are updated automatically.

25
docs/TOOLS Normal file
View File

@ -0,0 +1,25 @@
Anope Bundled Tools
-------------------
1) Anope SMTP Client
Provided with Anope is a simple SMTP client which can be used instead of
programs like SendMail in some cases.
The SMTP client can be used instead of sendmail for use with Anope's mail
options. To use the SMTP client instead of sendmail, find the line in your
services configuration file (services.conf) that defines sendmailpath. On
that line, change the path to your services installation directory, then
followed by "bin/anopesmtp" and the IP address of a valid SMTP server. It
should look like this:
sendmailpath = "/home/anope/services/bin/anopesmtp 127.0.0.1"
If the SMTP client doesn't send mail, or if there's an other problem with
it, you can enable debug mode by passing the --debug flag after the server
address. This should generate a log file of what happened when it tried
to connect to the SMTP server.
Credits:
Originally written by Dominick Meglio <codemastr@unrealircd.com>
Ported to *nix by Trystan Scott Lee <trystan@nomadirc.net>

161
docs/WIN32.txt Normal file
View File

@ -0,0 +1,161 @@
Anope for Windows
-----------------
1) Building the Source
2) Installation
3) Compiling Modules
4) Other compile options
5) Credits
1) Building the Source
NOTE: If you have downloaded one of the pre-compiled installers, you do
NOT need to complete this step, and you can proceed to step 2.
If you want to build Anope from source on a Win32 system, you will need
to follow this instructions:
1) Download the required files:
* Current Anope source:
https://github.com/anope/anope/releases
* CMake:
https://cmake.org/download/
(NOTE: When installing, tell CMake to add itself to the PATH.)
If you have Visual C++ 10 or 11 (2010/2012) skip ahead to step 2, else you
need to download and install the following free component from Microsoft.
* Microsoft Visual C++ 2010 Express Edition:
http://www.microsoft.com/visualstudio/eng/downloads#d-2010-express
2) Unpack the Anope tarball with your favorite uncompression program
(WinZip or WinRAR, etc).
3) Bring up the Visual C++ Command Prompt; This will launch a
DOS Command Prompt like window, which will set the environment
properties needed to make Anope.
Create a new directory, which will be used to hold the build files. You can make it
be a directory under the source directory unpacked in step 2, or somewhere else entirely.
Change directories to this new folder, by typing:
cd <path to build directory>
e.g.
cd c:\anope-build
4) You now need to configure Anope to your requirements. At the prompt type:
<path to source directory>\Config.exe
NOTE: If you run an Anti-Virus program such as McAfee or Norton, you may
be unable to run this command due to the protection in place. Some Anti-
Virus programs may detect the Anope Configuration Tool as a worm, however
this is not the case. If you are prompted to allow or deny execution of
the script, you should choose allow. If the script fails to run, and no
notice is displayed, please check your Anti-Virus settings before seeking
assistance.
An interactive configuration program should guide you through the install
options. You will be given a choice to use NMake or not. NMake will compile
inside the command prompt window you are in. If you want to build within
the Visual C++ IDE, say no to that option, and it'll create a Solution for
you to open up.
If you cannot find whats causing the error, please visit our forums or
our IRC Support channel for assistance.
Some Anope modules require third party libraries, such as m_mysql and
the SSL modules. If these libraries are installed in nonstandard
locations, cmake will probably not find them and should be told where
they are by passing their location to Config.
The libraries used to build the 'extra' modules are available at
https://github.com/Adam-/windows-scripts.
5) You are now ready to compile. If you said you wanted to use NMake in step 4,
at the prompt type:
nmake
Once you are back at the command prompt again, if there have been no
errors, you are ready to go.
If instead you decided to use the Visual C++ IDE, open up the Anope.sln
file. After the IDE has fully loaded, hit F7 to build everything.
Should you encounter errors with the installation process, check the
messages displayed for advice on resolving them. If you are unable to
resolve the issues yourself, seek assistance on our forums or in our
IRC Support channel.
6) Finally you will need to install Anope. If you said you wanted to use NMake
in step 4, at the prompt type:
nmake install
Otherwise, if you decided to use the Visual C++ IDE, find the project called
INSTALL within the Solution Explorer. Right-click on INSTALL and choose Build.
When you have done this, all the files will be installed to where they belong.
The only thing you need to do is rename "data/example.conf" to be "data/services.conf",
and then follow the steps to set up Anope.
You have now completed the building phase of Anope for Windows. You can
now move on to the next section, which is related to setting up Anope.
2) Installation
Since Anope for Windows does not use a visual interface, you must do the
configuration with a text editor before proceeding with running Anope
itself.
NOTE: You may need to open the configuration file with Wordpad, or a text
editor which supports UNIX line endings. Opening the configuration file in
Notepad will cause strange characters to appear, and you may not be able to
edit the file correctly.
Open services.conf, and read through it carefully and adjust the settings
you think you need to adjust.
If you are unsure of the settings, you can go to the dos command prompt
and run "anope.exe --nofork --debug" and watch the information as it
attempts to connect.
You can launch services in two ways. If you are sure that the entered
configuration information is correct, simply double clicking the Anope
executable will cause it to start; no window will pop up. If you'd rather
have a more textual output, you can start at the dos prompt and type in
"anope.exe". If services are successfully started up the dos prompt will
seem to hang; at this point you can safely close the dos window.
3) Compiling Modules
If you want to build other modules than the ones shipped by default, you
will need to rerun Config.exe
4) Other compile options
A) If you have trouble recompiling Anope, you should delete all files and folders
within the build folder you created in step 3 of section 1. Afterwards, follow
the directions from step 4 of section 1 down.
5) Credits
Anope is based on Epona and IRCServices. See CREDITS for more credits and
a complete list of all developers.
Anope's Windows-specific code is provided by:
* Dominick Meglio <codemastr@unrealircd.com>
* Trystan Scott Lee <trystan@nomadirc.net>
* Chris Hogben <heinz@anope.org>
Anope's Windows Installer was made using:
* NSIS 2.20 <http://nsis.sourceforge.net>

29
docs/XMLRPC/XMLRPC Normal file
View File

@ -0,0 +1,29 @@
Starting with Anope 1.9.4 XMLRPC using PHP's xmlrpc_encode_request and xmlrpc_decode functions is supported.
This allows external applications, such as websites, to execute remote procedure calls to Anope in real time.
Currently there are 5 supported XMLRPC calls, provided by m_xmlrpc_main:
checkAuthentication - Takes two parameters, an account name and a password. Checks if the account name is valid and the password
is correct for the account name, useful for making login pages on websites.
command - Takes three parameters, a service name (BotServ, ChanServ, NickServ), a user name (whether online or not), and the command
to execute. This will execute the given command to Anope using the given service name. If the user given is online, the
command reply will go to them, if not it is returned by XMLRPC.
stats - Takes no parameters, returns miscellaneous stats that can be found in the /operserv stats command.
channel - Takes one parameter, a channel name, and returns real time information regarding that channel, such as users, modes
(ban lists and such), topic etc.
user - Takes one parameter, a user name, and returns real time information regarding that user.
opers - Takes no parameters, returns opertypes, their privileges and commands.
notice - Takes three parameters, source user, target user, and message. Sends a message to the user.
XMLRPC was designed to be used with db_sql, and will not return any information that can be pulled from the SQL
database, such as accounts and registered channel information. It is instead used for pulling realtime data such
as users and channels currently online. For examples on how to use these calls in PHP, see xmlrpc.php in docs/XMLRPC.
Also note that the parameter named "id" is reserved for query ID. If you pass a query to Anope containing a value for id. it will
be stored by Anope and the same id will be passed back in the result.

145
docs/XMLRPC/xmlrpc.php Normal file
View File

@ -0,0 +1,145 @@
<?php
/**
* XMLRPC Functions
*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*/
class AnopeXMLRPC
{
/**
* The XMLRPC host
*
* @var string
*/
private $host;
/**
* Initiate a new AnopeXMLRPC instance
*
* @param $host
*/
public function __construct($host)
{
$this->host = $host;
}
/**
* Run an XMLRPC command. Name should be a query name and params an array of parameters, eg:
* $this->raw("checkAuthentication", ["adam", "qwerty"]);
* If successful returns back an array of useful information.
*
* Note that $params["id"] is reserved for query ID, you may set it to something if you wish.
* If you do, the same ID will be passed back with the reply from Anope.
*
* @param $name
* @param $params
* @return array|null
*/
public function run($name, $params)
{
$xmlquery = xmlrpc_encode_request($name, $params);
$context = stream_context_create(["http" => [
"method" => "POST",
"header" => "Content-Type: text/xml",
"content" => $xmlquery]]);
$inbuf = file_get_contents($this->host, false, $context);
$response = xmlrpc_decode($inbuf);
if ($response) {
return $response;
}
return null;
}
/**
* Do Command on Service as User, eg:
* $anope->command("ChanServ", "Adam", "REGISTER #adam");
* Returns an array of information regarding the command execution, if
* If 'online' is set to yes, then the reply to the command was sent to the user on IRC.
* If 'online' is set to no, then the reply to the command is in the array member 'return'
*
* @param $service
* @param $user
* @param $command
* @return array|null
*/
public function command($service, $user, $command)
{
return $this->run("command", [$service, $user, $command]);
}
/**
* Check an account/nick name and password to see if they are valid
* Returns the account display name if valid
*
* @param $account
* @param $pass
* @return string|null
*/
public function auth($account, $pass)
{
$ret = $this->run("checkAuthentication", [$account, $pass]);
if ($ret && $ret["result"] == "Success") {
return $ret["account"];
}
return null;
}
/**
* Returns an array of misc stats regarding Anope
*
* @return array|null
*/
public function stats()
{
return $this->run("stats", null);
}
/**
* Look up data for a channel
* Returns an array containing channel information, or an array of size one
* (just containing the name) if the channel does not exist
*
* @param $channel
* @return array|null
*/
public function channel($channel)
{
return $this->run("channel", [$channel]);
}
/**
* Sent a notice to a user.
* Returns an array containing channel information, or an array of size one
* (just containing the name) if the channel does not exist
*
* @param $source
* @param $target
* @param $message
* @return array|null
*/
public function notice($source, $target, $message)
{
return $this->run("notice", [$source, $target, $message]);
}
/**
* Like channel(), but different.
*
* @param $user
* @return array|null
*/
public function user($user)
{
return $this->run("user", [$user]);
}
}
$anope = new AnopeXMLRPC("http://127.0.0.1:8080/xmlrpc");

168
extras Executable file
View File

@ -0,0 +1,168 @@
#!/usr/bin/env perl
#
# Script taken from InspIRCd, https://www.inspircd.org/
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
BEGIN { require 5.8.0; }
use strict;
use warnings FATAL => qw(all);
use File::Copy ();
use Cwd;
sub list_extras ();
sub enable_extras (@);
sub disable_extras (@);
# Routine to list out the extra/ modules that have been enabled.
# Note: when getting any filenames out and comparing, it's important to lc it if the
# file system is not case-sensitive (== Epoc, MacOS, OS/2 (incl DOS/DJGPP), VMS, Win32
# (incl NetWare, Symbian)). Cygwin may or may not be case-sensitive, depending on
# configuration, however, File::Spec does not currently tell us (it assumes Unix behavior).
sub list_extras () {
use File::Spec;
# @_ not used
my $srcdir = File::Spec->catdir("modules");
my $abs_srcdir = File::Spec->rel2abs($srcdir);
local $_;
my $dd;
opendir $dd, File::Spec->catdir($abs_srcdir, "extra") or die (File::Spec->catdir($abs_srcdir, "extra") . ": $!\n");
my @extras = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
closedir $dd;
undef $dd;
opendir $dd, $abs_srcdir or die "$abs_srcdir: $!\n";
my @sources = map { File::Spec->case_tolerant() ? lc($_) : $_ } (readdir($dd));
closedir $dd;
undef $dd;
my $maxlen = (sort { $b <=> $a } (map {length($_)} (@extras)))[0];
my %extras = ();
EXTRA: for my $extra (@extras) {
next if (File::Spec->curdir() eq $extra || File::Spec->updir() eq $extra);
my $abs_extra = File::Spec->catfile($abs_srcdir, "extra", $extra);
my $abs_source = File::Spec->catfile($abs_srcdir, $extra);
next unless ($extra =~ m/\.(cpp|h)$/ || (-d $abs_extra)); # C++ Source/Header, or directory
if (-l $abs_source) {
# Symlink, is it in the right place?
my $targ = readlink($abs_source);
my $abs_targ = File::Spec->rel2abs($targ, $abs_srcdir);
if ($abs_targ eq $abs_extra) {
$extras{$extra} = "\e[32;1menabled\e[0m";
} else {
$extras{$extra} = sprintf("\e[31;1mwrong symlink target (%s)\e[0m", $abs_targ);
}
} elsif (-e $abs_source) {
my ($devext, $inoext) = stat($abs_extra);
my ($devsrc, $inosrc, undef, $lnksrc) = stat($abs_source);
if ($lnksrc > 1) {
if ($devsrc == $devext && $inosrc == $inoext) {
$extras{$extra} = "\e[32;1menabled\e[0m";
} else {
$extras{$extra} = sprintf("\e[31;1mwrong hardlink target (%d:%d)\e[0m", $devsrc, $inosrc);
}
} else {
open my $extfd, "<", $abs_extra;
open my $srcfd, "<", $abs_source;
local $/ = undef;
if (scalar(<$extfd>) eq scalar(<$srcfd>)) {
$extras{$extra} = "\e[32;1menabled\e[0m";
} else {
$extras{$extra} = sprintf("\e[31;1mout of synch (re-copy)\e[0m");
}
}
} else {
$extras{$extra} = "\e[33;1mdisabled\e[0m";
}
}
for my $extra (sort {$a cmp $b} keys(%extras)) {
my $text = $extras{$extra};
if ($text =~ m/needed by/ && $text !~ m/enabled/) {
printf "\e[31;1;5m%-*s = %s%s\e[0m\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? ")" : "");
} else {
printf "%-*s = %s%s\n", $maxlen, $extra, $text, ($text =~ m/needed by/ ? "\e[0m)" : "");
}
}
return keys(%extras) if wantarray; # Can be used by manage_extras.
}
sub enable_extras (@) {
my (@extras) = @_;
for my $extra (@extras) {
my $extrapath = "modules/extra/$extra";
if (!-e $extrapath) {
print STDERR "Cannot enable \e[32;1m$extra\e[0m : No such file or directory in modules/extra\n";
next;
}
my $source = "modules/$extra";
if (-e $source) {
print STDERR "Cannot enable \e[32;1m$extra\e[0m : destination in modules exists (might already be enabled?)\n";
next;
}
print "Enabling $extra ... \n";
symlink "extra/$extra", $source or print STDERR "$source: Cannot link to 'extra/$extra': $!\n";
}
}
sub disable_extras (@)
{
opendir my $dd, "modules/extra/";
my @files = readdir($dd);
closedir $dd;
my (@extras) = @_;
EXTRA: for my $extra (@extras) {
my $extrapath = "modules/extra/$extra";
my $source = "modules/$extra";
if (!-e $extrapath) {
print STDERR "Cannot disable \e[32;1m$extra\e[0m : Is not an extra\n";
next;
}
if ((! -l $source) || readlink($source) ne "extra/$extra") {
print STDERR "Cannot disable \e[32;1m$extra\e[0m : Source is not a link or doesn't refer to the right file. Remove manually if this is in error.\n";
next;
}
# Now remove.
print "Disabling $extra ... \n";
unlink "modules/$extra" or print STDERR "Cannot disable \e[32;1m$extra\e[0m : $!\n";
}
}
my $clearscreen = `clear`;
print $clearscreen;
while (1)
{
list_extras; # print the module list
print "\nPlease enter the name of the module or type 'q' to quit.: ";
my $input = <STDIN>;
chop($input); # remove the trailing \n from the user input
if ($input eq "q") {
if (-e "build/CMakeFiles") {
system("cmake", "build/.");
print "\nNow cd build, then run make to build Anope.\n\n";
} else {
print "\nBuild directory not found. You should run ./Config now.\n\n"
}
exit 0;
}
print $clearscreen;
if ($input eq "") {
next;
}
if (-e "modules/$input") {
disable_extras($input)
} else {
enable_extras($input)
}
}

64
include/CMakeLists.txt Normal file
View File

@ -0,0 +1,64 @@
# Set version.cpp to use C++ as well as set its compile flags
set_source_files_properties(version.cpp PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
# Generate version-bin executable to modify version.h, setting it's linker flags as well
add_executable(version-bin version.cpp)
set_target_properties(version-bin PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}")
get_target_property(version_BINARY version-bin LOCATION)
# Modify version.h from the above executable, with dependencies to version.cpp
# and all of the source files in the main build
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version_build
COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h
DEPENDS version-bin ${SRC_SRCS}
)
# Add version-bin to list of files for CPack to ignore
get_filename_component(version_BINARY ${version_BINARY} NAME)
add_to_cpack_ignored_files("${version_BINARY}$" TRUE)
if(NOT WIN32)
add_to_cpack_ignored_files("version.h$" TRUE)
add_to_cpack_ignored_files("build.h$" TRUE)
endif(NOT WIN32)
set(PCH_SOURCES_GCH "")
if(USE_PCH AND CMAKE_COMPILER_IS_GNUCXX)
string(REPLACE " " ";" PCH_CXXFLAGS "${CXXFLAGS} ${CMAKE_CXX_FLAGS}")
file(GLOB PCH_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
sort_list(PCH_SOURCES)
foreach(PCH_SOURCE ${PCH_SOURCES})
find_includes(${PCH_SOURCE} INCLUDES)
set(INCLUDES_LIST)
append_to_list(INCLUDES_LIST ${PCH_SOURCE})
foreach(INCLUDE ${INCLUDES})
# Extract the filename from the #include line
extract_include_filename(${INCLUDE} FILENAME QUOTE_TYPE)
if(QUOTE_TYPE STREQUAL "quotes")
find_in_list(PCH_SOURCES "${FILENAME}" FOUND)
if(NOT FOUND EQUAL -1)
append_to_list(INCLUDES_LIST ${FILENAME})
endif(NOT FOUND EQUAL -1)
endif(QUOTE_TYPE STREQUAL "quotes")
endforeach(INCLUDE)
set(PCH_EXTRAFLAGS "")
if(DEBUG_BUILD)
set(PCH_EXTRAFLAGS "-g")
endif(DEBUG_BUILD)
if(PCH_SOURCE STREQUAL "module.h")
set(PCH_EXTRAFLAGS ${PCH_EXTRAFLAGS} -fPIC)
endif(PCH_SOURCE STREQUAL "module.h")
if(GETTEXT_INCLUDE)
set(PCH_GETTEXT_INCLUDE "-I${GETTEXT_INCLUDE}")
endif(GETTEXT_INCLUDE)
set(PCH_SOURCES_GCH "${PCH_SOURCES_GCH};${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch")
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch
COMMAND ${CMAKE_CXX_COMPILER} ARGS ${PCH_CXXFLAGS} ${PCH_EXTRAFLAGS}
${PCH_GETTEXT_INCLUDE} -I${CMAKE_CURRENT_BINARY_DIR} -I${Anope_SOURCE_DIR}/modules/pseudoclients ${CMAKE_CURRENT_SOURCE_DIR}/${PCH_SOURCE} -o ${CMAKE_CURRENT_BINARY_DIR}/${PCH_SOURCE}.gch
DEPENDS ${INCLUDES_LIST} VERBATIM
)
endforeach(PCH_SOURCE ${PCH_SOURCES})
endif(USE_PCH AND CMAKE_COMPILER_IS_GNUCXX)
# Add a custom target to the above file
add_custom_target(headers DEPENDS version-bin ${CMAKE_CURRENT_BINARY_DIR}/version_build ${PCH_SOURCES_GCH})

174
include/access.h Normal file
View File

@ -0,0 +1,174 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef ACCESS_H
#define ACCESS_H
#include "services.h"
#include "anope.h"
#include "serialize.h"
#include "service.h"
enum
{
ACCESS_INVALID = -10000,
ACCESS_FOUNDER = 10001
};
/* A privilege, probably configured using a privilege{} block. Most
* commands require specific privileges to be executed. The AccessProvider
* backing each ChanAccess determines whether that ChanAccess has a given
* privilege.
*/
struct CoreExport Privilege
{
Anope::string name;
Anope::string desc;
/* Rank relative to other privileges */
int rank;
Privilege(const Anope::string &name, const Anope::string &desc, int rank);
bool operator==(const Privilege &other) const;
};
class CoreExport PrivilegeManager
{
static std::vector<Privilege> Privileges;
public:
static void AddPrivilege(Privilege p);
static void RemovePrivilege(Privilege &p);
static Privilege *FindPrivilege(const Anope::string &name);
static std::vector<Privilege> &GetPrivileges();
static void ClearPrivileges();
};
/* A provider of access. Only used for creating ChanAccesses, as
* they contain pure virtual functions.
*/
class CoreExport AccessProvider : public Service
{
public:
AccessProvider(Module *owner, const Anope::string &name);
virtual ~AccessProvider();
/** Creates a new ChanAccess entry using this provider.
* @return The new entry
*/
virtual ChanAccess *Create() = 0;
private:
static std::list<AccessProvider *> Providers;
public:
static const std::list<AccessProvider *>& GetProviders();
};
/* Represents one entry of an access list on a channel. */
class CoreExport ChanAccess : public Serializable
{
Anope::string mask;
/* account this access entry is for, if any */
Serialize::Reference<NickCore> nc;
public:
typedef std::vector<ChanAccess *> Path;
/* The provider that created this access entry */
AccessProvider *provider;
/* Channel this access entry is on */
Serialize::Reference<ChannelInfo> ci;
Anope::string creator;
time_t last_seen;
time_t created;
ChanAccess(AccessProvider *p);
virtual ~ChanAccess();
void SetMask(const Anope::string &mask, ChannelInfo *ci);
const Anope::string &Mask() const;
NickCore *GetAccount() const;
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
static const unsigned int MAX_DEPTH = 4;
/** Check if this access entry matches the given user or account
* @param u The user
* @param nc The account
* @param next Next channel to check if any
*/
virtual bool Matches(const User *u, const NickCore *nc, ChannelInfo* &next) const;
/** Check if this access entry has the given privilege.
* @param name The privilege name
*/
virtual bool HasPriv(const Anope::string &name) const = 0;
/** Serialize the access given by this access entry into a human
* readable form. chanserv/access will return a number, chanserv/xop
* will be AOP, SOP, etc.
*/
virtual Anope::string AccessSerialize() const = 0;
/** Unserialize this access entry from the given data. This data
* will be fetched from AccessSerialize.
*/
virtual void AccessUnserialize(const Anope::string &data) = 0;
/* Comparison operators to other Access entries */
virtual bool operator>(const ChanAccess &other) const;
virtual bool operator<(const ChanAccess &other) const;
bool operator>=(const ChanAccess &other) const;
bool operator<=(const ChanAccess &other) const;
};
/* A group of access entries. This is used commonly, for example with ChannelInfo::AccessFor,
* to show what access a user has on a channel because users can match multiple access entries.
*/
class CoreExport AccessGroup
{
public:
/* access entries + paths */
std::vector<ChanAccess::Path> paths;
/* Channel these access entries are on */
const ChannelInfo *ci;
/* Account these entries affect, if any */
const NickCore *nc;
/* super_admin always gets all privs. founder is a special case where ci->founder == nc */
bool super_admin, founder;
AccessGroup();
/** Check if this access group has a certain privilege. Eg, it
* will check every ChanAccess entry of this group for any that
* has the given privilege.
* @param priv The privilege
* @return true if any entry has the given privilege
*/
bool HasPriv(const Anope::string &priv) const;
/** Get the "highest" access entry from this group of entries.
* The highest entry is determined by the entry that has the privilege
* with the highest rank (see Privilege::rank).
* @return The "highest" entry
*/
const ChanAccess *Highest() const;
/* Comparison operators to other AccessGroups */
bool operator>(const AccessGroup &other) const;
bool operator<(const AccessGroup &other) const;
bool operator>=(const AccessGroup &other) const;
bool operator<=(const AccessGroup &other) const;
inline bool empty() const { return paths.empty(); }
};
#endif

290
include/account.h Normal file
View File

@ -0,0 +1,290 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef ACCOUNT_H
#define ACCOUNT_H
#include "extensible.h"
#include "serialize.h"
#include "anope.h"
#include "memo.h"
#include "base.h"
typedef Anope::hash_map<NickAlias *> nickalias_map;
typedef Anope::hash_map<NickCore *> nickcore_map;
typedef TR1NS::unordered_map<uint64_t, NickCore *> nickcoreid_map;
extern CoreExport Serialize::Checker<nickalias_map> NickAliasList;
extern CoreExport Serialize::Checker<nickcore_map> NickCoreList;
extern CoreExport nickcoreid_map NickCoreIdList;
/* A registered nickname.
* It matters that Base is here before Extensible (it is inherited by Serializable)
*/
class CoreExport NickAlias : public Serializable, public Extensible
{
Anope::string vhost_ident, vhost_host, vhost_creator;
time_t vhost_created;
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;
time_t time_registered;
time_t last_seen;
/* Account this nick is tied to. Multiple nicks can be tied to a single account. */
Serialize::Reference<NickCore> nc;
/** Constructor
* @param nickname The nick
* @param nickcore The nickcore for this nick
*/
NickAlias(const Anope::string &nickname, NickCore *nickcore);
~NickAlias();
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
/** Set a vhost for the user
* @param ident The ident
* @param host The host
* @param creator Who created the vhost
* @param time When the vhost was created
*/
void SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created = Anope::CurTime);
/** Remove a users vhost
**/
void RemoveVhost();
/** Check if the user has a vhost
* @return true or false
*/
bool HasVhost() const;
/** Retrieve the vhost ident
* @return the ident
*/
const Anope::string &GetVhostIdent() const;
/** Retrieve the vhost host
* @return the host
*/
const Anope::string &GetVhostHost() const;
/** Retrieve the vhost creator
* @return the creator
*/
const Anope::string &GetVhostCreator() const;
/** Retrieve when the vhost was created
* @return the time it was created
*/
time_t GetVhostCreated() const;
/** Finds a registered nick
* @param nick The nick to lookup
* @return the nick, if found
*/
static NickAlias *Find(const Anope::string &nick);
};
/* A registered account. Each account must have a NickAlias with the same nick as the
* account's display.
* It matters that Base is here before Extensible (it is inherited by Serializable)
*/
class CoreExport NickCore : public Serializable, public Extensible
{
/* Channels which reference this core in some way (this is on their access list, akick list, is founder, successor, etc) */
Serialize::Checker<std::map<ChannelInfo *, int> > chanaccess;
/* Unique identifier for the account. */
uint64_t id;
public:
/* Name of the account. Find(display)->nc == this. */
Anope::string display;
/* User password in form of hashm:data */
Anope::string pass;
Anope::string email;
/* Locale name of the language of the user. Empty means default language */
Anope::string language;
/* Access list, contains user@host masks of users who get certain privileges based
* on if NI_SECURE is set and what (if any) kill protection is enabled. */
std::vector<Anope::string> access;
MemoInfo memos;
std::map<Anope::string, Anope::string> last_modes;
/* Nicknames registered that are grouped to this account.
* for n in aliases, n->nc == this.
*/
Serialize::Checker<std::vector<NickAlias *> > aliases;
/* Set if this user is a services operator. o->ot must exist. */
Oper *o;
/* Unsaved data */
/* Number of channels registered by this account */
uint16_t channelcount;
/* Last time an email was sent to this user */
time_t lastmail;
/* Users online now logged into this account */
std::list<User *> users;
/** Constructor
* @param display The display nick
* @param id The account id
*/
NickCore(const Anope::string &nickdisplay, uint64_t nickid = 0);
~NickCore();
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
/** Changes the display for this account
* @param na The new display, must be grouped to this account.
*/
void SetDisplay(const NickAlias *na);
/** 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;
/** Add an entry to the nick's access list
*
* @param entry The nick!ident@host entry to add to the access list
*
* Adds a new entry into the access list.
*/
void AddAccess(const Anope::string &entry);
/** Get an entry from the nick's access list by index
*
* @param entry Index in the access list vector to retrieve
* @return The access list entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds
*
* Retrieves an entry from the access list corresponding to the given index.
*/
Anope::string GetAccess(unsigned entry) const;
/** Get the number of entries on the access list for this account.
*/
unsigned GetAccessCount() const;
/** Retrieves the account id for this user */
uint64_t GetId();
/** Find an entry in the nick's access list
*
* @param entry The nick!ident@host entry to search for
* @return True if the entry is found in the access list, false otherwise
*
* Search for an entry within the access list.
*/
bool FindAccess(const Anope::string &entry);
/** Erase an entry from the nick's access list
*
* @param entry The nick!ident@host entry to remove
*
* Removes the specified access list entry from the access list.
*/
void EraseAccess(const Anope::string &entry);
/** Clears the entire nick's access list
*
* Deletes all the memory allocated in the access list vector and then clears the vector.
*/
void ClearAccess();
/** Is the given user on this accounts access list?
*
* @param u The user
*
* @return true if the user is on the access list
*/
bool IsOnAccess(const User *u) const;
/** Finds an account
* @param nick The account name to find
* @return The account, if it exists
*/
static NickCore* Find(const Anope::string &nick);
void AddChannelReference(ChannelInfo *ci);
void RemoveChannelReference(ChannelInfo *ci);
void GetChannelReferences(std::deque<ChannelInfo *> &queue);
};
/* A request to check if an account/password is valid. These can exist for
* extended periods due to the time some authentication modules take.
*/
class CoreExport IdentifyRequest
{
/* Owner of this request, used to cleanup requests if a module is unloaded
* while a request us pending */
Module *owner;
Anope::string account;
Anope::string password;
std::set<Module *> holds;
bool dispatched;
bool success;
static std::set<IdentifyRequest *> Requests;
protected:
IdentifyRequest(Module *o, const Anope::string &acc, const Anope::string &pass);
virtual ~IdentifyRequest();
public:
/* One of these is called when the request goes through */
virtual void OnSuccess() = 0;
virtual void OnFail() = 0;
Module *GetOwner() const { return owner; }
const Anope::string &GetAccount() const { return account; }
const Anope::string &GetPassword() const { return password; }
/* Holds this request. When a request is held it must be Released later
* for the request to complete. Multiple modules may hold a request at any time,
* but the request is not complete until every module has released it. If you do not
* require holding this (eg, your password check is done in this thread and immediately)
* then you don't need to hold the request before calling `Success()`.
* @param m The module holding this request
*/
void Hold(Module *m);
/** Releases a held request
* @param m The module releasing the hold
*/
void Release(Module *m);
/** Called by modules when this IdentifyRequest has succeeded.
* If this request is behind held it must still be Released after calling this.
* @param m The module confirming authentication
*/
void Success(Module *m);
/** Used to either finalize this request or marks
* it as dispatched and begins waiting for the module(s)
* that have holds to finish.
*/
void Dispatch();
static void ModuleUnload(Module *m);
};
#endif // ACCOUNT_H

791
include/anope.h Normal file
View File

@ -0,0 +1,791 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef ANOPE_H
#define ANOPE_H
#include <signal.h>
#include "hashcomp.h"
namespace Anope
{
/**
* A wrapper string class around all the other string classes, this class will
* allow us to only require one type of string everywhere that can be converted
* at any time to a specific type of string.
*/
class CoreExport string
{
private:
/**
* The actual string is stored in an std::string as it can be converted to
* ci::string, or a C-style string at any time.
*/
std::string _string;
public:
/**
* Extras.
*/
typedef std::string::iterator iterator;
typedef std::string::const_iterator const_iterator;
typedef std::string::reverse_iterator reverse_iterator;
typedef std::string::const_reverse_iterator const_reverse_iterator;
typedef std::string::size_type size_type;
static const size_type npos = static_cast<size_type>(-1);
/**
* Constructors that can take in any type of string.
*/
string() : _string("") { }
string(char chr) : _string() { _string = chr; }
string(size_type n, char chr) : _string(n, chr) { }
string(const char *_str) : _string(_str) { }
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 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) { }
#if __cplusplus >= 201103L
string(const string &) = default;
#endif
/**
* Assignment operators, so any type of string can be assigned to this class.
*/
inline string &operator=(char chr) { this->_string = chr; return *this; }
inline string &operator=(const char *_str) { this->_string = _str; return *this; }
inline string &operator=(const std::string &_str) { this->_string = _str; return *this; }
inline string &operator=(const string &_str) { if (this != &_str) this->_string = _str._string; return *this; }
/**
* Equality operators, to compare to any type of string.
*/
inline bool operator==(const char *_str) const { return this->_string == _str; }
inline bool operator==(const std::string &_str) const { return this->_string == _str; }
inline bool operator==(const string &_str) const { return this->_string == _str._string; }
inline bool equals_cs(const char *_str) const { return this->_string == _str; }
inline bool equals_cs(const std::string &_str) const { return this->_string == _str; }
inline bool equals_cs(const string &_str) const { return this->_string == _str._string; }
inline bool equals_ci(const char *_str) const { return ci::string(this->_string.c_str()) == _str; }
inline bool equals_ci(const std::string &_str) const { return ci::string(this->_string.c_str()) == _str.c_str(); }
inline bool equals_ci(const string &_str) const { return ci::string(this->_string.c_str()) == _str._string.c_str(); }
/**
* Inequality operators, exact opposites of the above.
*/
inline bool operator!=(const char *_str) const { return !operator==(_str); }
inline bool operator!=(const std::string &_str) const { return !operator==(_str); }
inline bool operator!=(const string &_str) const { return !operator==(_str); }
/**
* Compound addition operators, overloaded to do concatenation.
*/
inline string &operator+=(char chr) { this->_string += chr; return *this; }
inline string &operator+=(const char *_str) { this->_string += _str; return *this; }
inline string &operator+=(const std::string &_str) { this->_string += _str; return *this; }
inline string &operator+=(const string &_str) { if (this != &_str) this->_string += _str._string; return *this; }
/**
* Addition operators, overloaded to do concatenation.
*/
inline const string operator+(char chr) const { return string(*this) += chr; }
inline const string operator+(const char *_str) const { return string(*this) += _str; }
inline const string operator+(const std::string &_str) const { return string(*this) += _str; }
inline const string operator+(const string &_str) const { return string(*this) += _str; }
friend const string operator+(char chr, const string &str);
friend const string operator+(const char *_str, const string &str);
friend const string operator+(const std::string &_str, const string &str);
/**
* Less-than operator.
*/
inline bool operator<(const string &_str) const { return this->_string < _str._string; }
/**
* The following functions return the various types of strings.
*/
inline const char *c_str() const { return this->_string.c_str(); }
inline const char *data() const { return this->_string.data(); }
inline std::string &str() { return this->_string; }
inline const std::string &str() const { return this->_string; }
inline ci::string ci_str() const { return ci::string(this->_string.c_str()); }
/**
* Returns if the string is empty or not.
*/
inline bool empty() const { return this->_string.empty(); }
/**
* Returns the string's length.
*/
inline size_type length() const { return this->_string.length(); }
/**
* Returns the size of the currently allocated storage space in the string object.
* This can be equal or greater than the length of the string.
*/
inline size_type capacity() const { return this->_string.capacity(); }
/**
* Add a char to the end of the string.
*/
inline void push_back(char c) { return this->_string.push_back(c); }
inline string& append(const string &s) { this->_string.append(s.str()); return *this; }
inline string& append(const char *s, size_t n) { this->_string.append(s, n); return *this; }
/**
* Resizes the string content to n characters.
*/
inline void resize(size_type n) { return this->_string.resize(n); }
/**
* Erases characters from the string.
*/
inline iterator erase(const iterator &i) { return this->_string.erase(i); }
inline iterator erase(const iterator &first, const iterator &last) { return this->_string.erase(first, last); }
inline void erase(size_type pos = 0, size_type n = std::string::npos) { this->_string.erase(pos, n); }
/**
* Trim leading and trailing white spaces from the string.
*/
inline string& ltrim(const Anope::string &what = " \t\r\n")
{
while (!this->_string.empty() && what.find(this->_string[0]) != Anope::string::npos)
this->_string.erase(this->_string.begin());
return *this;
}
inline string& rtrim(const Anope::string &what = " \t\r\n")
{
while (!this->_string.empty() && what.find(this->_string[this->_string.length() - 1]) != Anope::string::npos)
this->_string.erase(this->_string.length() - 1);
return *this;
}
inline string& trim(const Anope::string &what = " \t\r\n")
{
this->ltrim(what);
this->rtrim(what);
return *this;
}
/**
* Clears the string.
*/
inline void clear() { this->_string.clear(); }
/**
* Find substrings of the string.
*/
inline size_type find(const string &_str, size_type pos = 0) const { return this->_string.find(_str._string, pos); }
inline size_type find(char chr, size_type pos = 0) const { return this->_string.find(chr, pos); }
inline size_type find_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find(ci::string(_str._string.c_str()), pos); }
inline size_type find_ci(char chr, size_type pos = 0) const { return ci::string(this->_string.c_str()).find(chr, pos); }
inline size_type rfind(const string &_str, size_type pos = npos) const { return this->_string.rfind(_str._string, pos); }
inline size_type rfind(char chr, size_type pos = npos) const { return this->_string.rfind(chr, pos); }
inline size_type rfind_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).rfind(ci::string(_str._string.c_str()), pos); }
inline size_type rfind_ci(char chr, size_type pos = npos) const { return ci::string(this->_string.c_str()).rfind(chr, pos); }
inline size_type find_first_of(const string &_str, size_type pos = 0) const { return this->_string.find_first_of(_str._string, pos); }
inline size_type find_first_of_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find_first_of(ci::string(_str._string.c_str()), pos); }
inline size_type find_first_not_of(const string &_str, size_type pos = 0) const { return this->_string.find_first_not_of(_str._string, pos); }
inline size_type find_first_not_of_ci(const string &_str, size_type pos = 0) const { return ci::string(this->_string.c_str()).find_first_not_of(ci::string(_str._string.c_str()), pos); }
inline size_type find_last_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_of(_str._string, pos); }
inline size_type find_last_of_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).find_last_of(ci::string(_str._string.c_str()), pos); }
inline size_type find_last_not_of(const string &_str, size_type pos = npos) const { return this->_string.find_last_not_of(_str._string, pos); }
inline size_type find_last_not_of_ci(const string &_str, size_type pos = npos) const { return ci::string(this->_string.c_str()).find_last_not_of(ci::string(_str._string.c_str()), pos); }
/**
* Determine if string consists of only numbers.
*/
inline bool is_number_only() const { return this->find_first_not_of("0123456789.-") == npos; }
inline bool is_pos_number_only() const { return this->find_first_not_of("0123456789.") == npos; }
/**
* Replace parts of the string.
*/
inline string replace(size_type pos, size_type n, const string &_str) { return string(this->_string.replace(pos, n, _str._string)); }
inline string replace(size_type pos, size_type n, const string &_str, size_type pos1, size_type n1) { return string(this->_string.replace(pos, n, _str._string, pos1, n1)); }
inline string replace(size_type pos, size_type n, size_type n1, char chr) { return string(this->_string.replace(pos, n, n1, chr)); }
inline string replace(iterator first, iterator last, const string &_str) { return string(this->_string.replace(first, last, _str._string)); }
inline string replace(iterator first, iterator last, size_type n, char chr) { return string(this->_string.replace(first, last, n, chr)); }
template <class InputIterator> inline string replace(iterator first, iterator last, InputIterator f, InputIterator l) { return string(this->_string.replace(first, last, f, l)); }
inline string replace_all_cs(const string &_orig, const string &_repl) const
{
Anope::string new_string = *this;
size_type pos = new_string.find(_orig), orig_length = _orig.length(), repl_length = _repl.length();
while (pos != npos)
{
new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length);
pos = new_string.find(_orig, pos + repl_length);
}
return new_string;
}
inline string replace_all_ci(const string &_orig, const string &_repl) const
{
Anope::string new_string = *this;
size_type pos = new_string.find_ci(_orig), orig_length = _orig.length(), repl_length = _repl.length();
while (pos != npos)
{
new_string = new_string.substr(0, pos) + _repl + new_string.substr(pos + orig_length);
pos = new_string.find_ci(_orig, pos + repl_length);
}
return new_string;
}
/**
* Get the string in lowercase.
*/
inline string lower() const
{
Anope::string new_string = *this;
for (size_type i = 0; i < new_string.length(); ++i)
new_string[i] = Anope::tolower(new_string[i]);
return new_string;
}
/**
* Get the string in uppercase.
*/
inline string upper() const
{
Anope::string new_string = *this;
for (size_type i = 0; i < new_string.length(); ++i)
new_string[i] = Anope::toupper(new_string[i]);
return new_string;
}
/**
* Get a substring of the string.
*/
inline string substr(size_type pos = 0, size_type n = npos) const { return string(this->_string.substr(pos, n)); }
/**
* Iterators to the string.
*/
inline iterator begin() { return this->_string.begin(); }
inline const_iterator begin() const { return this->_string.begin(); }
inline iterator end() { return this->_string.end(); }
inline const_iterator end() const { return this->_string.end(); }
inline reverse_iterator rbegin() { return this->_string.rbegin(); }
inline const_reverse_iterator rbegin() const { return this->_string.rbegin(); }
inline reverse_iterator rend() { return this->_string.rend(); }
inline const_reverse_iterator rend() const { return this->_string.rend(); }
/**
* Subscript operator, to access individual characters of the string.
*/
inline char &operator[](size_type n) { return this->_string[n]; }
inline const char &operator[](size_type n) const { return this->_string[n]; }
/**
* Stream insertion operator, must be friend because they cannot be inside the class.
*/
friend std::ostream &operator<<(std::ostream &os, const string &_str);
friend std::istream &operator>>(std::istream &is, string &_str);
};
inline std::ostream &operator<<(std::ostream &os, const string &_str) { return os << _str._string; }
/* This is not standard to make operator>> behave like operator<< in that it will allow extracting a whole line, not just one word */
inline std::istream &operator>>(std::istream &is, string &_str) { return std::getline(is, _str._string); }
inline const string operator+(char chr, const string &str) { string tmp(chr); tmp += str; return tmp; }
inline const string operator+(const char *_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
inline const string operator+(const std::string &_str, const string &str) { string tmp(_str); tmp += str; return tmp; }
struct hash_ci
{
inline size_t operator()(const string &s) const
{
return TR1NS::hash<std::string>()(s.lower().str());
}
};
struct hash_cs
{
inline size_t operator()(const string &s) const
{
return TR1NS::hash<std::string>()(s.str());
}
};
struct compare
{
inline bool operator()(const string &s1, const string &s2) const
{
return s1.equals_ci(s2);
}
};
template<typename T> class map : public std::map<string, T, ci::less> { };
template<typename T> class multimap : public std::multimap<string, T, ci::less> { };
template<typename T> class hash_map : public TR1NS::unordered_map<string, T, hash_ci, compare> { };
#ifndef REPRODUCIBLE_BUILD
static const char *const compiled = __TIME__ " " __DATE__;
#endif
/** The time Anope started.
*/
extern CoreExport time_t StartTime;
/** The value to return from main()
*/
extern int ReturnValue;
extern sig_atomic_t Signal;
extern CoreExport bool Quitting;
extern CoreExport bool Restarting;
extern CoreExport Anope::string QuitReason;
/** The current system time, which is pretty close to being accurate.
* Use this unless you need very specific time checks
*/
extern CoreExport time_t CurTime;
/** The debug level we are running at.
*/
extern CoreExport int Debug;
/** Other command line options.
*/
extern CoreExport bool ReadOnly, NoFork, NoThird, NoExpire, ProtocolDebug;
/** The root of the services installation. Usually ~/services
*/
extern CoreExport Anope::string ServicesDir;
/** Services binary name (eg services)
*/
extern CoreExport Anope::string ServicesBin;
/** Various directory paths. These can be set at runtime by command line args
*/
extern CoreExport Anope::string ConfigDir;
extern CoreExport Anope::string DataDir;
extern CoreExport Anope::string ModuleDir;
extern CoreExport Anope::string LocaleDir;
extern CoreExport Anope::string LogDir;
/** The uplink we are currently connected to
*/
extern CoreExport int CurrentUplink;
/** Various methods to determine the Anope version running
*/
extern CoreExport string Version();
extern CoreExport string VersionShort();
extern CoreExport string VersionBuildString();
extern CoreExport int VersionMajor();
extern CoreExport int VersionMinor();
extern CoreExport int VersionPatch();
/** Determines if we are still attached to the terminal, and can print
* messages to the user via stderr/stdout.
* @return true if still attached
*/
extern bool AtTerm();
/** Used to "fork" the process and go into the background during initial startup
* while we are AtTerm(). The actual fork is not done here, but earlier, and this
* simply notifies the parent via kill() to exit().
*/
extern void Fork();
/** Does something with the signal in Anope::Signal
*/
extern void HandleSignal();
/** One of the first functions called, does general initialization such as reading
* command line args, loading the configuration, doing the initial fork() if necessary,
* initializing language support, loading modules, and loading databases.
* @throws CoreException if something bad went wrong
*/
extern void Init(int ac, char **av);
/** Calls the save database event
*/
extern CoreExport void SaveDatabases();
/** Check whether two strings match.
* @param str The string to check against the pattern (e.g. foobar)
* @param mask The pattern to check (e.g. foo*bar)
* @param case_sensitive Whether or not the match is case sensitive, default false.
* @param use_regex Whether or not to try regex. case_sensitive is not used in regex.
*/
extern CoreExport bool Match(const string &str, const string &mask, bool case_sensitive = false, bool use_regex = false);
/** Converts a string to hex
* @param the data to be converted
* @return a anope::string containing the hex value
*/
extern CoreExport string Hex(const string &data);
extern CoreExport string Hex(const char *data, unsigned len);
/** Converts a string from hex
* @param src The data to be converted
* @param dest The destination string
*/
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 void Encrypt(const Anope::string &src, Anope::string &dest);
/** Decrypts what is in 'src' to 'dest'.
* @param src The source string to decrypt
* @param dest The destination where the decrypted string is placed
* @return true if decryption was successful. This is usually not the case
* as most encryption methods we use are one way.
*/
extern CoreExport bool Decrypt(const Anope::string &src, Anope::string &dest);
/** Hashes a buffer with SipHash-2-4
* @param src The start of the buffer to hash
* @param src_sz The total number of bytes in the buffer
* @param key A 16 byte key to hash the buffer with.
*/
extern CoreExport uint64_t SipHash24(const void *src, unsigned long src_sz, const char key[16]);
/** 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, ...);
/** Return the last error code
* @return The error code
*/
extern CoreExport int LastErrorCode();
/** Return the last error, uses errno/GetLastError() to determine this
* @return An error message
*/
extern CoreExport const string LastError();
/** Determines if a path is a file
*/
extern CoreExport bool IsFile(const Anope::string &file);
/** Converts a string into seconds
* @param s The string, eg 3d
* @return The time represented by the string, eg 259,200
*/
extern CoreExport time_t DoTime(const Anope::string &s);
/** 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
* @return A human readable string, eg "1 minute"
*/
extern CoreExport Anope::string Duration(time_t seconds, const NickCore *nc = NULL);
/** Generates a human readable string of type "expires in ..."
* @param expires time in seconds
* @param nc The account to use language settings for to translate this string, if applicable
* @return A human readable string, eg "expires in 5 days"
*/
extern CoreExport Anope::string Expires(time_t seconds, const NickCore *nc = NULL);
/** Converts a time in seconds (epoch) to a human readable format.
* @param t The time
* @param nc The account to use language settings for to translate this string, if applicable
* @param short_output If true, the output is just a date (eg, "Apr 12 20:18:22 2009 MSD"), else it includes the date and how long ago/from now that date is, (eg "Apr 12 20:18:22 2009 MSD (1313 days, 9 hours, 32 minutes ago)"
*/
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 &);
/** Main processing routine. Parses the message and takes the appropriate action.
* @param Raw message from the uplink
*/
extern void Process(const Anope::string &);
/** Does a blocking dns query and returns the first IP.
* @param host host to look up
* @param type inet addr type
* @return the IP if it was found, else the host
*/
extern Anope::string Resolve(const Anope::string &host, int type);
/** Generate a string of random letters and numbers
* @param len The length of the string returned
*/
extern CoreExport Anope::string Random(size_t len);
}
/** sepstream allows for splitting token separated lists.
* Each successive call to sepstream::GetToken() returns
* the next token, until none remain, at which point the method returns
* an empty string.
*/
class CoreExport sepstream
{
private:
/** Original string.
*/
Anope::string tokens;
/** Seperator value
*/
char sep;
/** Current string position
*/
size_t pos;
/** If set then GetToken() can return an empty string
*/
bool allow_empty;
public:
/** Create a sepstream and fill it with the provided data
*/
sepstream(const Anope::string &source, char separator, bool allowempty = false);
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
*/
bool GetToken(Anope::string &token);
/** Gets token number 'num' from the stream
* @param token The token is placed here
* @param num The token number to fetch
* @return True if the token was able to be fetched
*/
bool GetToken(Anope::string &token, int num);
/** Gets every token from this stream
* @param token Tokens are pushed back here
*/
template<typename T> void GetTokens(T& token)
{
token.clear();
Anope::string t;
while (this->GetToken(t))
token.push_back(t);
}
/** Gets token number 'num' from the stream and all remaining tokens.
* @param token The token is placed here
* @param num The token number to fetch
* @return True if the token was able to be fetched
*/
bool GetTokenRemainder(Anope::string &token, int num);
/** Determines the number of tokens in this stream.
* @return The number of tokens in this stream
*/
int NumTokens();
/** Fetch the entire remaining stream, without tokenizing
* @return The remaining part of the stream
*/
const Anope::string GetRemaining();
/** Returns true if the end of the stream has been reached
* @return True if the end of the stream has been reached, otherwise false
*/
bool StreamEnd();
};
/** A derived form of sepstream, which separates on commas
*/
class commasepstream : public sepstream
{
public:
/** Initialize with comma separator
*/
commasepstream(const Anope::string &source, bool allowempty = false) : sepstream(source, ',', allowempty) { }
};
/** A derived form of sepstream, which separates on spaces
*/
class spacesepstream : public sepstream
{
public:
/** Initialize with space separator
*/
spacesepstream(const Anope::string &source) : sepstream(source, ' ') { }
};
/** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
* When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or
* a class derived from ModuleException. If a module throws an exception during its constructor, the module will not
* be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
* attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
*/
class CoreException : public std::exception
{
protected:
/** Holds the error message to be displayed
*/
Anope::string err;
/** Source of the exception
*/
Anope::string source;
public:
/** Default constructor, just uses the error message 'Core threw an exception'.
*/
CoreException() : err("Core threw an exception"), source("The core") { }
/** This constructor can be used to specify an error message before throwing.
*/
CoreException(const Anope::string &message) : err(message), source("The core") { }
/** This constructor can be used to specify an error message before throwing,
* and to specify the source of the exception.
*/
CoreException(const Anope::string &message, const Anope::string &src) : err(message), source(src) { }
/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
* Actually no, it does nothing. Never mind.
* @throws Nothing!
*/
virtual ~CoreException() throw() { }
/** Returns the reason for the exception.
* The module should probably put something informative here as the user will see this upon failure.
*/
virtual const Anope::string &GetReason() const
{
return err;
}
virtual const Anope::string &GetSource() const
{
return source;
}
};
class ModuleException : public CoreException
{
public:
/** Default constructor, just uses the error message 'Module threw an exception'.
*/
ModuleException() : CoreException("Module threw an exception", "A Module") { }
/** This constructor can be used to specify an error message before throwing.
*/
ModuleException(const Anope::string &message) : CoreException(message, "A Module") { }
/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
* Actually no, it does nothing. Never mind.
* @throws Nothing!
*/
virtual ~ModuleException() throw() { }
};
class ConvertException : public CoreException
{
public:
ConvertException(const Anope::string &reason = "") : CoreException(reason) { }
virtual ~ConvertException() throw() { }
};
/** Convert something to a string
*/
template<typename T> inline Anope::string stringify(const T &x)
{
std::ostringstream stream;
if (!(stream << x))
throw ConvertException("Stringify fail");
return stream.str();
}
template<typename T> inline void convert(const Anope::string &s, T &x, Anope::string &leftover, bool failIfLeftoverChars = true)
{
leftover.clear();
std::istringstream i(s.str());
char c;
if (!(i >> x))
throw ConvertException("Convert fail");
if (failIfLeftoverChars)
{
if (i.get(c))
throw ConvertException("Convert fail");
}
else
{
std::string left;
getline(i, left);
leftover = left;
}
}
template<typename T> inline void convert(const Anope::string &s, T &x, bool failIfLeftoverChars = true)
{
Anope::string Unused;
convert(s, x, Unused, failIfLeftoverChars);
}
template<typename T> inline T convertTo(const Anope::string &s, Anope::string &leftover, bool failIfLeftoverChars = true)
{
T x;
convert(s, x, leftover, failIfLeftoverChars);
return x;
}
template<typename T> inline T convertTo(const Anope::string &s, bool failIfLeftoverChars = true)
{
T x;
convert(s, x, failIfLeftoverChars);
return x;
}
/** Casts to be used instead of dynamic_cast, this uses dynamic_cast
* for debug builds and static_cast on release builds
* to speed up the program because dynamic_cast relies on RTTI.
*/
#ifdef DEBUG_BUILD
# include <typeinfo>
template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
{
T ret = dynamic_cast<T>(ptr);
if (ptr != NULL && ret == NULL)
throw CoreException(Anope::string("anope_dynamic_static_cast<") + typeid(T).name() + ">(" + typeid(O).name() + ") fail");
return ret;
}
#else
template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
{
return static_cast<T>(ptr);
}
#endif
#endif // ANOPE_H

143
include/base.h Normal file
View File

@ -0,0 +1,143 @@
/*
*
* (C) 2008-2011 Adam <Adam@anope.org>
* (C) 2008-2022 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
#ifndef BASE_H
#define BASE_H
#include "services.h"
/** The base class that most classes in Anope inherit from
*/
class CoreExport Base
{
/* References to this base class */
std::set<ReferenceBase *> *references;
public:
Base();
virtual ~Base();
/** Adds a reference to this object. Eg, when a Reference
* is created referring to this object this is called. It is used to
* cleanup references when this object is destructed.
*/
void AddReference(ReferenceBase *r);
void DelReference(ReferenceBase *r);
};
class ReferenceBase
{
protected:
bool invalid;
public:
ReferenceBase() : invalid(false) { }
ReferenceBase(const ReferenceBase &other) : invalid(other.invalid) { }
virtual ~ReferenceBase() { }
inline void Invalidate() { this->invalid = true; }
};
/** Used to hold pointers to objects that may be deleted. A Reference will
* no longer be valid once the object it refers is destructed.
*/
template<typename T>
class Reference : public ReferenceBase
{
protected:
T *ref;
public:
Reference() : ref(NULL)
{
}
Reference(T *obj) : ref(obj)
{
if (ref)
ref->AddReference(this);
}
Reference(const Reference<T> &other) : ReferenceBase(other), ref(other.ref)
{
if (operator bool())
ref->AddReference(this);
}
virtual ~Reference()
{
if (operator bool())
ref->DelReference(this);
}
inline Reference<T>& operator=(const Reference<T> &other)
{
if (this != &other)
{
if (*this)
this->ref->DelReference(this);
this->ref = other.ref;
this->invalid = other.invalid;
if (*this)
this->ref->AddReference(this);
}
return *this;
}
/* We explicitly call operator bool here in several places to prevent other
* operators, such operator T*, from being called instead, which will mess
* with any class inheriting from this that overloads this operator.
*/
virtual operator bool()
{
if (!this->invalid)
return this->ref != NULL;
return false;
}
inline operator T*()
{
if (operator bool())
return this->ref;
return NULL;
}
inline T* operator->()
{
if (operator bool())
return this->ref;
return NULL;
}
inline T* operator*()
{
if (operator bool())
return this->ref;
return NULL;
}
/** Note that we can't have an operator< that returns this->ref < other.ref
* because this function is used to sort objects in containers (such as set
* or map), and if the references themselves can change if the object they
* refer to is invalidated or changed, then this screws with the order that
* the objects would be in the container without properly adjusting the
* container, resulting in weird stuff.
*
* As such, we don't allow storing references in containers that require
* operator<, because they would not be able to compare what the references
* actually referred to.
*/
inline bool operator==(const Reference<T> &other)
{
if (!this->invalid)
return this->ref == other;
return false;
}
};
#endif // BASE_H

135
include/bots.h Normal file
View File

@ -0,0 +1,135 @@
/*
*
* (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
* (C) 2008-2022 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
#ifndef BOTS_H
#define BOTS_H
#include "users.h"
#include "anope.h"
#include "serialize.h"
#include "commands.h"
typedef Anope::map<BotInfo *> botinfo_map;
extern CoreExport Serialize::Checker<botinfo_map> BotListByNick, BotListByUID;
/* A service bot (NickServ, ChanServ, a BotServ bot, etc). */
class CoreExport BotInfo : public User, public Serializable
{
/* Channels this bot is assigned to */
Serialize::Checker<std::set<ChannelInfo *> > channels;
public:
time_t created;
/* Last time this bot said something (via privmsg) */
time_t lastmsg;
/* Map of actual command names -> service name/permission required */
CommandInfo::map commands;
/* Modes the bot should have as configured in service:modes */
Anope::string botmodes;
/* Channels the bot should be in as configured in service:channels */
std::vector<Anope::string> botchannels;
/* Whether or not this bot is introduced to the network */
bool introduced;
/* Bot can only be assigned by irc ops */
bool oper_only;
/* Bot is defined in the configuration file */
bool conf;
/** Create a new bot.
* @param nick The nickname to assign to the bot.
* @param user The ident to give the bot.
* @param host The hostname to give the bot.
* @param real The realname to give the bot.
* @param bmodes The modes to give the bot.
*/
BotInfo(const Anope::string &nick, const Anope::string &user = "", const Anope::string &host = "", const Anope::string &real = "", const Anope::string &bmodes = "");
/** Destroy a bot, clearing up appropriately.
*/
virtual ~BotInfo();
void Serialize(Serialize::Data &data) const;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
void GenerateUID();
void OnKill();
/** Change the nickname for the bot.
* @param newnick The nick to change to
*/
void SetNewNick(const Anope::string &newnick);
/** Return the channels this bot is assigned to
*/
const std::set<ChannelInfo *> &GetChannels() const;
/** Assign this bot to a given channel, removing the existing assigned bot if one exists.
* @param u The user assigning the bot, or NULL
* @param ci The channel registration to assign the bot to.
*/
void Assign(User *u, ChannelInfo *ci);
/** Remove this bot from a given channel.
* @param u The user requesting the unassign, or NULL.
* @param ci The channel registration to remove the bot from.
*/
void UnAssign(User *u, ChannelInfo *ci);
/** Get the number of channels this bot is assigned to
*/
unsigned GetChannelCount() const;
/** Join this bot to a channel
* @param c The channel
* @param status The status the bot should have on the channel
*/
void Join(Channel *c, ChannelStatus *status = NULL);
/** Join this bot to a channel
* @param chname The channel name
* @param status The status the bot should have on the channel
*/
void Join(const Anope::string &chname, ChannelStatus *status = NULL);
/** Part this bot from a channel
* @param c The channel
* @param reason The reason we're parting
*/
void Part(Channel *c, const Anope::string &reason = "");
/** Called when a user messages this bot
* @param u The user
* @param message The users' message
*/
virtual void OnMessage(User *u, const Anope::string &message);
/** Link a command name to a command in services
* @param cname The command name
* @param sname The service name
* @param permission Permission required to execute the command, if any
* @return The commandinfo for the newly created command
*/
CommandInfo& SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission = "");
/** Get command info for a command
* @param cname The command name
* @return A struct containing service name and permission
*/
CommandInfo *GetCommand(const Anope::string &cname);
/** Find a bot by nick
* @param nick The nick
* @param nick_only True to only look by nick, and not by UID
* @return The bot, if it exists
*/
static BotInfo* Find(const Anope::string &nick, bool nick_only = false);
};
#endif // BOTS_H

310
include/channels.h Normal file
View File

@ -0,0 +1,310 @@
/* Channel support
*
* (C) 2008-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef CHANNELS_H
#define CHANNELS_H
#include "anope.h"
#include "extensible.h"
#include "modes.h"
#include "serialize.h"
typedef Anope::hash_map<Channel *> channel_map;
extern CoreExport channel_map ChannelList;
/* A user container, there is one of these per user per channel. */
struct ChanUserContainer : public Extensible
{
User *user;
Channel *chan;
/* Status the user has in the channel */
ChannelStatus status;
ChanUserContainer(User *u, Channel *c) : user(u), chan(c) { }
};
class CoreExport Channel : public Base, public Extensible
{
static std::vector<Channel *> deleting;
public:
typedef std::multimap<Anope::string, Anope::string> ModeList;
private:
/** A map of channel modes with their parameters set on this channel
*/
ModeList modes;
public:
/* Channel name */
Anope::string name;
/* Set if this channel is registered. ci->c == this. Contains information relevant to the registered channel */
Serialize::Reference<ChannelInfo> ci;
/* When the channel was created */
time_t creation_time;
/* If the channel has just been created in a netjoin */
bool syncing;
/* Is configured in the conf as a channel bots should be in */
bool botchannel;
/* Users in the channel */
typedef std::map<User *, ChanUserContainer *> ChanUserList;
ChanUserList users;
/* Current topic of the channel */
Anope::string topic;
/* Who set the topic */
Anope::string topic_setter;
/* The timestamp associated with the topic. Not necessarily anywhere close to Anope::CurTime.
* This is the time the topic was *originally set*. When we restore the topic we want to change the TS back
* to this, but we can only do this on certain IRCds.
*/
time_t topic_ts;
/* The actual time the topic was set, probably close to Anope::CurTime */
time_t topic_time;
time_t server_modetime; /* Time of last server MODE */
time_t chanserv_modetime; /* Time of last check_modes() */
int16_t server_modecount; /* Number of server MODEs this second */
int16_t chanserv_modecount; /* Number of check_mode()'s this sec */
int16_t bouncy_modes; /* Did we fail to set modes here? */
private:
/** Constructor
* @param name The channel name
* @param ts The time the channel was created
*/
Channel(const Anope::string &nname, time_t ts = Anope::CurTime);
public:
/** Destructor
*/
~Channel();
/** Call if we need to unset all modes and clear all user status (internally).
* Only useful if we get a SJOIN with a TS older than what we have here
*/
void Reset();
/** Restore the channel topic, set mlock (key), set stickied bans, etc
*/
void Sync();
/** Check if a channels modes are correct.
*/
void CheckModes();
/** Check if this channel should be deleted
*/
bool CheckDelete();
/** Join a user internally to the channel
* @param u The user
* @param status The status to give the user, if any
* @return The UserContainer for the user
*/
ChanUserContainer* JoinUser(User *u, const ChannelStatus *status);
/** Remove a user internally from the channel
* @param u The user
*/
void DeleteUser(User *u);
/** Check if the user is on the channel
* @param u The user
* @return A user container if found, else NULL
*/
ChanUserContainer *FindUser(User *u) const;
/** Check if a user has a status on a channel
* @param u The user
* @param cms The status mode, or NULL to represent no status
* @return true or false
*/
bool HasUserStatus(User *u, ChannelModeStatus *cms);
/** Check if a user has a status on a channel
* Use the overloaded function for ChannelModeStatus* to check for no status
* @param u The user
* @param name The mode name, eg CMODE_OP, CMODE_VOICE
* @return true or false
*/
bool HasUserStatus(User *u, const Anope::string &name);
/** See if a channel has a mode
* @param name The mode name
* @return The number of modes set
* @param param The optional mode param
*/
size_t HasMode(const Anope::string &name, const Anope::string &param = "");
/** Set a mode internally on a channel, this is not sent out to the IRCd
* @param setter The setter
* @param cm The mode
* @param param The param
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
*/
void SetModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string &param = "", bool enforce_mlock = true);
/** Remove a mode internally on a channel, this is not sent out to the IRCd
* @param setter The Setter
* @param cm The mode
* @param param The param
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
*/
void RemoveModeInternal(MessageSource &source, ChannelMode *cm, const Anope::string &param = "", bool enforce_mlock = true);
/** Set a mode on a channel
* @param bi The client setting the modes
* @param cm The mode
* @param param Optional param arg for the mode
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
*/
void SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param = "", bool enforce_mlock = true);
/**
* Set a mode on a channel
* @param bi The client setting the modes
* @param name The mode name
* @param param Optional param arg for the mode
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
*/
void SetMode(BotInfo *bi, const Anope::string &name, const Anope::string &param = "", bool enforce_mlock = true);
/** Remove a mode from a channel
* @param bi The client setting the modes
* @param cm The mode
* @param param Optional param arg for the mode
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
*/
void RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param = "", bool enforce_mlock = true);
/**
* Remove a mode from a channel
* @param bi The client setting the modes
* @param name The mode name
* @param param Optional param arg for the mode
* @param enforce_mlock true if mlocks should be enforced, false to override mlock
*/
void RemoveMode(BotInfo *bi, const Anope::string &name, const Anope::string &param = "", bool enforce_mlock = true);
/** Get a modes parameter for the channel
* @param name The mode
* @param target a string to put the param into
* @return true if the parameter was fetched, false if on error (mode not set) etc.
*/
bool GetParam(const Anope::string &name, Anope::string &target) const;
/** Set a string of modes on the channel
* @param bi The client setting the modes
* @param enforce_mlock Should mlock be enforced on this mode change
* @param cmodes The modes to set
*/
void SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...);
/** Set a string of modes internally on a channel
* @param source The setter
* @param mode the modes
* @param enforce_mlock true to enforce mlock
*/
void SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts = 0, bool enforce_mlock = true);
/** Does the given user match the given list? (CMODE_BAN, CMODE_EXCEPT, etc, a list mode)
* @param u The user
* @param list The mode of the list to check (eg CMODE_BAN)
* @return true if the user matches the list
*/
bool MatchesList(User *u, const Anope::string &list);
/** Kick a user from a channel internally
* @param source The sender of the kick
* @param nick The nick being kicked
* @param reason The reason for the kick
*/
void KickInternal(const MessageSource &source, const Anope::string &nick, const Anope::string &reason);
/** Kick a user from the channel
* @param bi The sender, can be NULL for the service bot for this channel
* @param u The user being kicked
* @param reason The reason for the kick
* @return true if the kick was successful, false if a module blocked the kick
*/
bool Kick(BotInfo *bi, User *u, const char *reason = NULL, ...);
/** Get all modes set on this channel, excluding status modes.
* @return a map of modes and their optional parameters.
*/
const ModeList &GetModes() const;
/** Get a list of modes on a channel
* @param name A mode name to get the list of
* @return a vector of the list mode entries
*/
std::vector<Anope::string> GetModeList(const Anope::string &name);
/** Get a string of the modes set on this channel
* @param complete Include mode parameters
* @param plus If set to false (with complete), mode parameters will not be given for modes requiring no parameters to be unset
* @return A mode string
*/
Anope::string GetModes(bool complete, bool plus);
/** Update the topic of the channel internally, and reset it if topiclock etc says to
* @param user The user setting the new topic
* @param newtopic The new topic
* @param ts The time the new topic is being set
*/
void ChangeTopicInternal(User *u, const Anope::string &user, const Anope::string &newtopic, time_t ts = Anope::CurTime);
/** Update the topic of the channel, and reset it if topiclock etc says to
* @param user The user setting the topic
* @param newtopic The new topic
* @param ts The time when the new topic is being set
*/
void ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts = Anope::CurTime);
/** Set the correct modes, or remove the ones granted without permission,
* for the specified user.
* @param user The user to give/remove modes to/from
* @param give_modes if true modes may be given to the user
*/
void SetCorrectModes(User *u, bool give_modes);
/** Unbans a user from this channel.
* @param u The user to unban
* @param mode The mode to unban
* @param full Whether or not to match using the user's real host and IP
* @return whether or not a ban was removed
*/
bool Unban(User *u, const Anope::string &mode, bool full = false);
/** Check whether a user is permitted to be on this channel
* @param u The user
* @return true if they are allowed, false if they aren't and were kicked
*/
bool CheckKick(User *user);
/** Finds a channel
* @param name The channel to find
* @return The channel, if found
*/
static Channel* Find(const Anope::string &name);
/** Finds or creates a channel
* @param name The channel name
* @param created Set to true if the channel was just created
* @param ts The time the channel was created
*/
static Channel *FindOrCreate(const Anope::string &name, bool &created, time_t ts = Anope::CurTime);
void QueueForDeletion();
static void DeleteChannels();
};
#endif // CHANNELS_H

187
include/commands.h Normal file
View File

@ -0,0 +1,187 @@
/* Declarations for command data.
*
* (C) 2003-2022 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.
*/
#ifndef COMMAND_H
#define COMMAND_H
#include "service.h"
#include "anope.h"
#include "channels.h"
struct CommandGroup
{
Anope::string name, description;
};
/* Used in BotInfo::commands */
struct CommandInfo
{
typedef Anope::map<CommandInfo> map;
CommandInfo() : hide(false), prepend_channel(false) { }
/* Service name of the command */
Anope::string name;
/* Permission required to execute the command */
Anope::string permission;
/* Group this command is in */
Anope::string group;
/* whether or not to hide this command in help output */
bool hide;
/* Only used with fantasy */
bool prepend_channel;
};
/* Where the replies from commands go to. User inherits from this and is the normal
* source of a CommandReply
*/
struct CoreExport CommandReply
{
virtual ~CommandReply() { }
virtual void SendMessage(BotInfo *source, const Anope::string &msg) = 0;
};
/* The source for a command */
class CoreExport CommandSource
{
/* The nick executing the command */
Anope::string nick;
/* User executing the command, may be NULL */
Reference<User> u;
public:
/* The account executing the command */
Reference<NickCore> nc;
/* for web clients */
Anope::string ip;
/* Where the reply should go */
CommandReply *reply;
/* Channel the command was executed on (fantasy) */
Reference<Channel> c;
/* The service this command is on */
Reference<BotInfo> service;
/* The actual name of the command being executed */
Anope::string command;
/* The permission of the command being executed */
Anope::string permission;
CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *reply, BotInfo *bi);
const Anope::string &GetNick() const;
User *GetUser();
NickCore *GetAccount();
AccessGroup AccessFor(ChannelInfo *ci);
bool IsFounder(ChannelInfo *ci);
void Reply(const char *message, ...);
void Reply(const Anope::string &message);
bool HasCommand(const Anope::string &cmd);
bool HasPriv(const Anope::string &cmd);
bool IsServicesOper();
bool IsOper();
};
/** Every services command is a class, inheriting from Command.
*/
class CoreExport Command : public Service
{
Anope::string desc;
std::vector<Anope::string> syntax;
/* Allow unregistered users to use this command */
bool allow_unregistered;
/* Command requires that a user is executing it */
bool require_user;
public:
/* Maximum parameters accepted by this command */
size_t max_params;
/* Minimum parameters required to use this command */
size_t min_params;
/* Module which owns us */
Module *module;
protected:
/** Create a new command.
* @param owner The owner of the command
* @param sname The command name
* @param min_params The minimum number of parameters the parser will require to execute this command
* @param max_params The maximum number of parameters the parser will create, after max_params, all will be combined into the last argument.
* NOTE: If max_params is not set (default), there is no limit to the max number of params.
*/
Command(Module *owner, const Anope::string &sname, size_t min_params, size_t max_params = 0);
public:
virtual ~Command();
protected:
void SetDesc(const Anope::string &d);
void ClearSyntax();
void SetSyntax(const Anope::string &s);
void SendSyntax(CommandSource &);
void AllowUnregistered(bool b);
void RequireUser(bool b);
public:
bool AllowUnregistered() const;
bool RequireUser() const;
/** Get the command description
* @param source The source wanting the command description
* @return The commands description
*/
virtual const Anope::string GetDesc(CommandSource &source) const;
/** Execute this command.
* @param source The source
* @param params Command parameters
*/
virtual void Execute(CommandSource &source, const std::vector<Anope::string> &params) = 0;
/** Called when HELP is requested for the client this command is on.
* @param source The source
*/
virtual void OnServHelp(CommandSource &source);
/** Requested when the user is requesting help on this command. Help on this command should be sent to the user.
* @param source The source
* @param subcommand The subcommand the user is requesting help on, or an empty string. (e.g. /ns help set foo bar lol gives a subcommand of "FOO BAR LOL")
* @return true if help was provided to the user, false otherwise.
*/
virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand);
/** Requested when the user provides bad syntax to this command (not enough params, etc).
* @param source The source
* @param subcommand The subcommand the user tried to use
*/
virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand);
/** Runs a command
* @param source The source of the command
* @param message The full message to run, the command is at the beginning of the message
*/
static void Run(CommandSource &source, const Anope::string &message);
void Run(CommandSource &source, const Anope::string &, const CommandInfo &, std::vector<Anope::string> &params);
/** Looks up a command name from the service name.
* Note that if the same command exists multiple places this will return the first one encountered
* @param command_service The command service to lookup, eg, nickserv/register
* @param bot If found, is set to the bot the command is on, eg NickServ
* @param name If found, is set to the command name, eg REGISTER
* @return true if the given command service exists
*/
static bool FindCommandFromService(const Anope::string &command_service, BotInfo* &bi, Anope::string &name);
};
#endif // COMMANDS_H

184
include/config.h Normal file
View File

@ -0,0 +1,184 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef CONFIG_H
#define CONFIG_H
#include "account.h"
#include "regchannel.h"
#include "users.h"
#include "opertype.h"
#include <stack>
namespace Configuration
{
class CoreExport Block
{
friend struct Conf;
public:
typedef Anope::map<Anope::string> item_map;
typedef Anope::multimap<Block> block_map;
private:
Anope::string name;
item_map items;
block_map blocks;
int linenum;
public:
Block(const Anope::string &);
const Anope::string &GetName() const;
int CountBlock(const Anope::string &name);
Block* GetBlock(const Anope::string &name, int num = 0);
template<typename T> inline T Get(const Anope::string &tag)
{
return this->Get<T>(tag, "");
}
/* VS 2008 has an issue with having a default argument here (def = ""), which is why the above
* function exists.
*/
template<typename T> T Get(const Anope::string &tag, const Anope::string &def) const
{
const Anope::string &value = this->Get<const Anope::string>(tag, def);
if (!value.empty())
try
{
return convertTo<T>(value);
}
catch (const ConvertException &) { }
return T();
}
bool Set(const Anope::string &tag, const Anope::string &value);
const item_map* GetItems() const;
};
template<> CoreExport const Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const;
template<> CoreExport time_t Block::Get(const Anope::string &tag, const Anope::string &def) const;
template<> CoreExport bool Block::Get(const Anope::string &tag, const Anope::string &def) const;
/** Represents a configuration file
*/
class File
{
Anope::string name;
bool executable;
FILE *fp;
public:
File(const Anope::string &, bool);
~File();
const Anope::string &GetName() const;
Anope::string GetPath() const;
bool IsOpen() const;
bool Open();
void Close();
bool End() const;
Anope::string Read();
};
struct Uplink;
struct CoreExport Conf : Block
{
/* options:readtimeout */
time_t ReadTimeout;
/* options:useprivmsg */
bool UsePrivmsg;
/* If we should default to privmsging clients */
bool DefPrivmsg;
/* Default language */
Anope::string DefLanguage;
/* options:timeoutcheck */
time_t TimeoutCheck;
/* options:usestrictprivmsg */
bool UseStrictPrivmsg;
/* networkinfo:nickchars */
Anope::string NickChars;
/* either "/msg " or "/" */
Anope::string StrictPrivmsg;
/* List of uplink servers to try and connect to */
std::vector<Uplink> Uplinks;
/* A vector of our logfile options */
std::vector<LogInfo> LogInfos;
/* Array of ulined servers */
std::vector<Anope::string> Ulines;
/* List of available opertypes */
std::vector<OperType *> MyOperTypes;
/* List of pairs of opers and their opertype from the config */
std::vector<Oper *> Opers;
/* Map of fantasy commands */
CommandInfo::map Fantasy;
/* Command groups */
std::vector<CommandGroup> CommandGroups;
/* List of modules to autoload */
std::vector<Anope::string> ModulesAutoLoad;
/* module configuration blocks */
std::map<Anope::string, Block *> modules;
Anope::map<Anope::string> bots;
Conf();
~Conf();
void LoadConf(File &file);
void Post(Conf *old);
Block *GetModule(Module *);
Block *GetModule(const Anope::string &name);
BotInfo *GetClient(const Anope::string &name);
Block *GetCommand(CommandSource &);
};
struct Uplink
{
Anope::string host;
unsigned port;
Anope::string password;
bool ipv6;
Uplink(const Anope::string &_host, int _port, const Anope::string &_password, bool _ipv6) : host(_host), port(_port), password(_password), ipv6(_ipv6) { }
inline bool operator==(const Uplink &other) const { return host == other.host && port == other.port && password == other.password && ipv6 == other.ipv6; }
inline bool operator!=(const Uplink &other) const { return !(*this == other); }
};
}
/** This class can be used on its own to represent an exception, or derived to represent a module-specific exception.
* When a module whishes to abort, e.g. within a constructor, it should throw an exception using ModuleException or
* a class derived from ModuleException. If a module throws an exception during its constructor, the module will not
* be loaded. If this happens, the error message returned by ModuleException::GetReason will be displayed to the user
* attempting to load the module, or dumped to the console if the ircd is currently loading for the first time.
*/
class ConfigException : public CoreException
{
public:
/** Default constructor, just uses the error message 'Config threw an exception'.
*/
ConfigException() : CoreException("Config threw an exception", "Config Parser") { }
/** This constructor can be used to specify an error message before throwing.
*/
ConfigException(const Anope::string &message) : CoreException(message, "Config Parser") { }
/** This destructor solves world hunger, cancels the world debt, and causes the world to end.
* Actually no, it does nothing. Never mind.
* @throws Nothing!
*/
virtual ~ConfigException() throw() { }
};
extern Configuration::File ServicesConf;
extern CoreExport Configuration::Conf *Config;
#endif // CONFIG_H

53
include/defs.h Normal file
View File

@ -0,0 +1,53 @@
/*
*
* (C) 2003-2022 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.
*/
class AccessGroup;
class AutoKick;
class BotInfo;
class CallBack;
class ChanAccess;
class Channel;
class ChannelInfo;
class ChannelStatus;
struct ChanUserContainer;
class ClientSocket;
class Command;
class CommandSource;
namespace Configuration { struct Conf; }
class ConnectionSocket;
namespace DNS { struct Query; }
class Entry;
class IdentifyRequest;
class InfoFormatter;
class IRCDProto;
class ListenSocket;
class Log;
class Memo;
class MessageSource;
class Module;
class NickAlias;
class NickCore;
class OperType;
class ReferenceBase;
class Regex;
class Serializable;
class Server;
class Socket;
class Thread;
class User;
class XLine;
class XLineManager;
struct BadWord;
struct Exception;
struct MemoInfo;
struct ModeLock;
struct Oper;
namespace SASL { struct Message; }

263
include/extensible.h Normal file
View File

@ -0,0 +1,263 @@
/*
*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef EXTENSIBLE_H
#define EXTENSIBLE_H
#include "anope.h"
#include "serialize.h"
#include "service.h"
#include "logger.h"
class Extensible;
class CoreExport ExtensibleBase : public Service
{
protected:
std::map<Extensible *, void *> items;
ExtensibleBase(Module *m, const Anope::string &n);
~ExtensibleBase();
public:
virtual void Unset(Extensible *obj) = 0;
/* called when an object we are keep track of is serializing */
virtual void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &) const { }
virtual void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &) { }
};
class CoreExport Extensible
{
public:
std::set<ExtensibleBase *> extension_items;
virtual ~Extensible();
void UnsetExtensibles();
template<typename T> T* GetExt(const Anope::string &name) const;
bool HasExt(const Anope::string &name) const;
template<typename T> T* Extend(const Anope::string &name, const T &what);
template<typename T> T* Extend(const Anope::string &name);
template<typename T> T* Require(const Anope::string &name);
template<typename T> void Shrink(const Anope::string &name);
static void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &data);
static void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &data);
};
template<typename T>
class BaseExtensibleItem : public ExtensibleBase
{
protected:
virtual T *Create(Extensible *) = 0;
public:
BaseExtensibleItem(Module *m, const Anope::string &n) : ExtensibleBase(m, n) { }
~BaseExtensibleItem()
{
while (!items.empty())
{
std::map<Extensible *, void *>::iterator it = items.begin();
Extensible *obj = it->first;
T *value = static_cast<T *>(it->second);
obj->extension_items.erase(this);
items.erase(it);
delete value;
}
}
T* Set(Extensible *obj, const T &value)
{
T* t = Set(obj);
if (t)
*t = value;
return t;
}
T* Set(Extensible *obj)
{
T* t = Create(obj);
Unset(obj);
items[obj] = t;
obj->extension_items.insert(this);
return t;
}
void Unset(Extensible *obj) anope_override
{
T *value = Get(obj);
items.erase(obj);
obj->extension_items.erase(this);
delete value;
}
T* Get(const Extensible *obj) const
{
std::map<Extensible *, void *>::const_iterator it = items.find(const_cast<Extensible *>(obj));
if (it != items.end())
return static_cast<T *>(it->second);
return NULL;
}
bool HasExt(const Extensible *obj) const
{
return items.find(const_cast<Extensible *>(obj)) != items.end();
}
T* Require(Extensible *obj)
{
T* t = Get(obj);
if (t)
return t;
return Set(obj);
}
};
template<typename T>
class ExtensibleItem : public BaseExtensibleItem<T>
{
protected:
T* Create(Extensible *obj) anope_override
{
return new T(obj);
}
public:
ExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { }
};
template<typename T>
class PrimitiveExtensibleItem : public BaseExtensibleItem<T>
{
protected:
T* Create(Extensible *obj) anope_override
{
return new T();
}
public:
PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { }
};
template<>
class PrimitiveExtensibleItem<bool> : public BaseExtensibleItem<bool>
{
protected:
bool* Create(Extensible *) anope_override
{
return NULL;
}
public:
PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<bool>(m, n) { }
};
template<typename T>
class SerializableExtensibleItem : public PrimitiveExtensibleItem<T>
{
public:
SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<T>(m, n) { }
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
{
T* t = this->Get(e);
data[this->name] << *t;
}
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
{
T t;
if (data[this->name] >> t)
this->Set(e, t);
else
this->Unset(e);
}
};
template<>
class SerializableExtensibleItem<bool> : public PrimitiveExtensibleItem<bool>
{
public:
SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<bool>(m, n) { }
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
{
data[this->name] << true;
}
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
{
bool b = false;
data[this->name] >> b;
if (b)
this->Set(e);
else
this->Unset(e);
}
};
template<typename T>
struct ExtensibleRef : ServiceReference<BaseExtensibleItem<T> >
{
ExtensibleRef(const Anope::string &n) : ServiceReference<BaseExtensibleItem<T> >("Extensible", n) { }
};
template<typename T>
T* Extensible::GetExt(const Anope::string &name) const
{
ExtensibleRef<T> ref(name);
if (ref)
return ref->Get(this);
Log(LOG_DEBUG) << "GetExt for nonexistent type " << name << " on " << static_cast<const void *>(this);
return NULL;
}
template<typename T>
T* Extensible::Extend(const Anope::string &name, const T &what)
{
T* t = Extend<T>(name);
if (t)
*t = what;
return t;
}
template<typename T>
T* Extensible::Extend(const Anope::string &name)
{
ExtensibleRef<T> ref(name);
if (ref)
return ref->Set(this);
Log(LOG_DEBUG) << "Extend for nonexistent type " << name << " on " << static_cast<void *>(this);
return NULL;
}
template<typename T>
T* Extensible::Require(const Anope::string &name)
{
if (HasExt(name))
return GetExt<T>(name);
else
return Extend<T>(name);
}
template<typename T>
void Extensible::Shrink(const Anope::string &name)
{
ExtensibleRef<T> ref(name);
if (ref)
ref->Unset(this);
else
Log(LOG_DEBUG) << "Shrink for nonexistent type " << name << " on " << static_cast<void *>(this);
}
#endif // EXTENSIBLE_H

199
include/hashcomp.h Normal file
View File

@ -0,0 +1,199 @@
/*
*
* (C) 2002-2011 InspIRCd Development Team
* (C) 2009-2022 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
#ifndef HASHCOMP_H
#define HASHCOMP_H
#include <string>
#include <locale>
#if defined _LIBCPP_VERSION || defined _WIN32
#include <unordered_map>
#define TR1NS std
#else
#include <tr1/unordered_map>
#define TR1NS std::tr1
#endif
#include "services.h"
namespace Anope
{
class string;
/* Casemap in use by Anope. ci::string's comparison functions use this (and thus Anope::string) */
extern std::locale casemap;
extern void CaseMapRebuild();
extern unsigned char tolower(unsigned char);
extern unsigned char toupper(unsigned char);
/* ASCII case insensitive ctype. */
template<typename char_type>
class ascii_ctype : public std::ctype<char_type>
{
public:
char_type do_toupper(char_type c) const anope_override
{
if (c >= 'a' && c <= 'z')
return c - 32;
else
return c;
}
char_type do_tolower(char_type c) const anope_override
{
if (c >= 'A' && c <= 'Z')
return c + 32;
else
return c;
}
};
/* rfc1459 case insensitive ctype, { = [, } = ], and | = \ */
template<typename char_type>
class rfc1459_ctype : public ascii_ctype<char_type>
{
public:
char_type do_toupper(char_type c) const anope_override
{
if (c == '{' || c == '}' || c == '|')
return c - 32;
else
return ascii_ctype<char_type>::do_toupper(c);
}
char_type do_tolower(char_type c) const anope_override
{
if (c == '[' || c == ']' || c == '\\')
return c + 32;
else
return ascii_ctype<char_type>::do_tolower(c);
}
};
}
/** The ci namespace contains a number of helper classes relevant to case insensitive strings.
*/
namespace ci
{
/** The ci_char_traits class is used for ASCII-style comparison of strings.
* This class is used to implement ci::string, a case-insensitive, ASCII-
* comparing string class.
*/
struct CoreExport ci_char_traits : std::char_traits<char>
{
/** Check if two chars match.
* @param c1st First character
* @param c2nd Second character
* @return true if the characters are equal
*/
static bool eq(char c1st, char c2nd);
/** Check if two chars do NOT match.
* @param c1st First character
* @param c2nd Second character
* @return true if the characters are unequal
*/
static bool ne(char c1st, char c2nd);
/** Check if one char is less than another.
* @param c1st First character
* @param c2nd Second character
* @return true if c1st is less than c2nd
*/
static bool lt(char c1st, char c2nd);
/** Compare two strings of size n.
* @param str1 First string
* @param str2 Second string
* @param n Length to compare to
* @return similar to strcmp, zero for equal, less than zero for str1
* being less and greater than zero for str1 being greater than str2.
*/
static int compare(const char *str1, const char *str2, size_t n);
/** Find a char within a string up to position n.
* @param s1 String to find in
* @param n Position to search up to
* @param c Character to search for
* @return Pointer to the first occurrence of c in s1
*/
static const char *find(const char *s1, int n, char c);
};
/** This typedef declares ci::string based upon ci_char_traits.
*/
typedef std::basic_string<char, ci_char_traits, std::allocator<char> > string;
struct CoreExport less
{
/** Compare two Anope::strings as ci::strings and find which one is less
* @param s1 The first string
* @param s2 The second string
* @return true if s1 < s2, else false
*/
bool operator()(const Anope::string &s1, const Anope::string &s2) const;
};
}
/* Define operators for + and == with ci::string to std::string for easy assignment
* and comparison
*
* Operator +
*/
inline std::string operator+(std::string &leftval, ci::string &rightval)
{
return leftval + std::string(rightval.c_str());
}
/* Define operators for + and == with ci::string to std::string for easy assignment
* and comparison
*
* Operator +
*/
inline ci::string operator+(ci::string &leftval, std::string &rightval)
{
return leftval + ci::string(rightval.c_str());
}
/* Define operators for + and == with ci::string to std::string for easy assignment
* and comparison
*
* Operator ==
*/
inline bool operator==(const std::string &leftval, const ci::string &rightval)
{
return leftval.c_str() == rightval;
}
/* Define operators for + and == with ci::string to std::string for easy assignment
* and comparison
*
* Operator ==
*/
inline bool operator==(const ci::string &leftval, const std::string &rightval)
{
return leftval == rightval.c_str();
}
/* Define operators != for ci::string to std::string for easy comparison
*/
inline bool operator!=(const ci::string &leftval, const std::string &rightval)
{
return !(leftval == rightval.c_str());
}
/* Define operators != for std::string to ci::string for easy comparison
*/
inline bool operator!=(const std::string &leftval, const ci::string &rightval)
{
return !(leftval.c_str() == rightval);
}
#endif // HASHCOMP_H

127
include/language.h Normal file
View File

@ -0,0 +1,127 @@
/*
*
* (C) 2008-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#include "anope.h"
namespace Language
{
/* Languages we support as configured in services.conf. They are
* added to this list if we detect a language exists in the correct
* location for each language.
*/
extern CoreExport std::vector<Anope::string> Languages;
/* Domains to search when looking for translations other than the
* default "anope domain. This is used by modules who add their own
* language files (and thus domains) to Anope. If a module is loaded
* and we detect a language file exists for at least one of the supported
* languages for the module, then we add the module's domain (its name)
* here.
*
* When strings are translated they are checked against all domains.
*/
extern std::vector<Anope::string> Domains;
/** Initialize the language system. Finds valid language files and
* populates the Languages list.
*/
extern void InitLanguages();
/** Translates a string to the default language.
* @param string A string to translate
* @return The translated string if found, else the original string.
*/
extern CoreExport const char *Translate(const char *string);
/** Translates a string to the language of the given user.
* @param u The user to translate the string for
* @param string A string to translate
* @return The translated string if found, else the original string.
*/
extern CoreExport const char *Translate(User *u, const char *string);
/** Translates a string to the language of the given account.
* @param nc The account to translate the string for
* @param string A string to translate
* @return The translated string if count, else the original string
*/
extern CoreExport const char *Translate(const NickCore *nc, const char *string);
/** Translatesa string to the given language.
* @param lang The language to translate to
* @param string The string to translate
* @return The translated string if found, else the original string.
*/
extern CoreExport const char *Translate(const char *lang, const char *string);
} // namespace Language
/* Commonly used language strings */
#define MORE_INFO _("\002%s%s HELP %s\002 for more information.")
#define BAD_USERHOST_MASK _("Mask must be in the form \037user\037@\037host\037.")
#define BAD_EXPIRY_TIME _("Invalid expiry time.")
#define USERHOST_MASK_TOO_WIDE _("%s coverage is too wide; Please use a more specific mask.")
#define READ_ONLY_MODE _("Services are in read-only mode!")
#define PASSWORD_INCORRECT _("Password incorrect.")
#define ACCESS_DENIED _("Access denied.")
#define MORE_OBSCURE_PASSWORD _("Please try again with a more obscure password. Passwords should be at least\n" \
"five characters long, should not be something easily guessed\n" \
"(e.g. your real name or your nick), and cannot contain the space or tab characters.")
#define PASSWORD_TOO_LONG _("Your password is too long. It must not exceed %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.")
#define NICK_X_SUSPENDED _("Nick %s is currently suspended.")
#define CHAN_X_SUSPENDED _("Channel %s is currently suspended.")
#define CHAN_X_NOT_REGISTERED _("Channel \002%s\002 isn't registered.")
#define CHAN_X_NOT_IN_USE _("Channel \002%s\002 doesn't exist.")
#define NICK_IDENTIFY_REQUIRED _("You must be logged into an account to use that command.")
#define MAIL_X_INVALID _("\002%s\002 is not a valid e-mail address.")
#define 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_REGISTERED _("This nick is owned by someone else. Please choose another.\n" \
"(If this is your nick, type \002%s%s IDENTIFY \037password\037\002.)")
#define NICK_IS_SECURE _("This nickname is registered and protected. If it is your\n" \
"nick, type \002%s%s IDENTIFY \037password\037\002. Otherwise,\n" \
"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.")
#define NICK_CONFIRM_INVALID _("Invalid passcode has been entered, please check the e-mail again, and retry.")
#define CHAN_NOT_ALLOWED_TO_JOIN _("You are not permitted to be on this channel.")
#define CHAN_X_INVALID _("Channel %s is not a valid channel.")
#define CHAN_REACHED_CHANNEL_LIMIT _("Sorry, you have already reached your limit of \002%d\002 channels.")
#define CHAN_EXCEEDED_CHANNEL_LIMIT _("Sorry, you have already exceeded your limit of \002%d\002 channels.")
#define CHAN_SYMBOL_REQUIRED _("Please use the symbol of \002#\002 when attempting to register.")
#define CHAN_SETTING_CHANGED _("%s for %s set to %s.")
#define CHAN_SETTING_UNSET _("%s for %s unset.")
#define CHAN_ACCESS_LEVEL_RANGE _("Access level must be between %d and %d inclusive.")
#define CHAN_INFO_HEADER _("Information for channel \002%s\002:")
#define CHAN_EXCEPTED _("\002%s\002 matches an except on %s and cannot be banned until the except has been removed.")
#define MEMO_NEW_X_MEMO_ARRIVED _("There is a new memo on channel %s.\n" \
"Type \002%s%s READ %s %d\002 to read it.")
#define MEMO_NEW_MEMO_ARRIVED _("You have a new memo from %s.\n" \
"Type \002%s%s READ %d\002 to read it.")
#define MEMO_HAVE_NO_MEMOS _("You have no memos.")
#define MEMO_X_HAS_NO_MEMOS _("%s has no memos.")
#define MEMO_SEND_DISABLED _("Sorry, memo sending is temporarily disabled.")
#define MEMO_HAVE_NO_NEW_MEMOS _("You have no new memos.")
#define MEMO_X_HAS_NO_NEW_MEMOS _("%s has no new memos.")
#define BOT_DOES_NOT_EXIST _("Bot \002%s\002 does not exist.")
#define BOT_NOT_ASSIGNED _("You must assign a bot to the channel before using this command.")
#define BOT_NOT_ON_CHANNEL _("Bot is not on channel \002%s\002.")
#define HOST_SET_ERROR _("A vHost must be in the format of a valid hostname.")
#define HOST_SET_IDENT_ERROR _("A vHost ident must be in the format of a valid ident.")
#define HOST_SET_TOOLONG _("Error! The vHost is too long, please use a hostname shorter than %d characters.")
#define HOST_SET_IDENTTOOLONG _("Error! The vHost ident is too long, please use an ident shorter than %d characters.")
#define HOST_NOT_ASSIGNED _("Please contact an Operator to get a vHost assigned to this nick.")
#define HOST_NO_VIDENT _("Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug")

94
include/lists.h Normal file
View File

@ -0,0 +1,94 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef LISTS_H
#define LISTS_H
#include "services.h"
#include "anope.h"
/** A class to process numbered lists (passed to most DEL/LIST/VIEW commands).
* The function HandleNumber is called for every number in the list. Note that
* if descending is true it gets called in descending order. This is so deleting
* the index passed to the function from an array will not cause the other indexes
* passed to the function to be incorrect. This keeps us from having to have an
* 'in use' flag on everything.
*/
class CoreExport NumberList
{
private:
bool is_valid;
std::set<unsigned> numbers;
bool desc;
public:
/** Processes a numbered list
* @param list The list
* @param descending True to make HandleNumber get called with numbers in descending order
*/
NumberList(const Anope::string &list, bool descending);
/** Destructor, does nothing
*/
virtual ~NumberList();
/** Should be called after the constructors are done running. This calls the callbacks.
*/
void Process();
/** Called with a number from the list
* @param number The number
*/
virtual void HandleNumber(unsigned number);
/** Called when there is an error with the numbered list
* Return false to immediately stop processing the list and return
* This is all done before we start calling HandleNumber, so no numbers will have been processed yet
* @param list The list
* @return false to stop processing
*/
virtual bool InvalidRange(const Anope::string &list);
};
/** This class handles formatting LIST/VIEW replies.
*/
class CoreExport ListFormatter
{
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
{
NickCore *nc;
std::vector<std::pair<Anope::string, Anope::string> > replies;
unsigned longest;
public:
InfoFormatter(NickCore *nc);
void Process(std::vector<Anope::string> &);
Anope::string &operator[](const Anope::string &key);
void AddOption(const Anope::string &opt);
};
#endif // LISTS_H

144
include/logger.h Normal file
View File

@ -0,0 +1,144 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef LOGGER_H
#define LOGGER_H
#include "anope.h"
#include "defs.h"
enum LogType
{
/* Used whenever an administrator uses an administrative command */
LOG_ADMIN,
/* Used whenever an administrator overrides something, such as adding
* access to a channel where they don't have permission to.
*/
LOG_OVERRIDE,
/* Any other command usage */
LOG_COMMAND,
LOG_SERVER,
LOG_CHANNEL,
LOG_USER,
LOG_MODULE,
LOG_NORMAL,
LOG_TERMINAL,
LOG_RAWIO,
LOG_DEBUG,
LOG_DEBUG_2,
LOG_DEBUG_3,
LOG_DEBUG_4
};
struct LogFile
{
Anope::string filename;
std::ofstream stream;
LogFile(const Anope::string &name);
~LogFile();
const Anope::string &GetName() const;
};
/* Represents a single log message */
class CoreExport Log
{
public:
/* Bot that should log this message */
BotInfo *bi;
/* For commands, the user executing the command, but might not always exist */
User *u;
/* For commands, the account executing the command, but will not always exist */
NickCore *nc;
/* For commands, the command being executed */
Command *c;
/* For commands, the command source */
CommandSource *source;
/* Used for LOG_CHANNEL */
Channel *chan;
/* For commands, the channel the command was executed on, will not always exist */
const ChannelInfo *ci;
/* For LOG_SERVER */
Server *s;
/* For LOG_MODULE */
Module *m;
LogType type;
Anope::string category;
std::stringstream buf;
Log(LogType type = LOG_NORMAL, const Anope::string &category = "", BotInfo *bi = NULL);
/* LOG_COMMAND/OVERRIDE/ADMIN */
Log(LogType type, CommandSource &source, Command *c, ChannelInfo *ci = NULL);
/* LOG_CHANNEL */
Log(User *u, Channel *c, const Anope::string &category = "");
/* LOG_USER */
Log(User *u, const Anope::string &category = "", BotInfo *bi = NULL);
/* LOG_SERVER */
Log(Server *s, const Anope::string &category = "", BotInfo *bi = NULL);
Log(BotInfo *b, const Anope::string &category = "");
Log(Module *m, const Anope::string &category = "", BotInfo *bi = NULL);
~Log();
private:
Anope::string FormatSource() const;
Anope::string FormatCommand() const;
public:
Anope::string BuildPrefix() const;
template<typename T> Log &operator<<(T val)
{
this->buf << val;
return *this;
}
};
/* Configured in the configuration file, actually does the message logging */
class CoreExport LogInfo
{
public:
BotInfo *bot;
std::vector<Anope::string> targets;
std::vector<LogFile *> logfiles;
int last_day;
std::vector<Anope::string> sources;
int log_age;
std::vector<Anope::string> admin;
std::vector<Anope::string> override;
std::vector<Anope::string> commands;
std::vector<Anope::string> servers;
std::vector<Anope::string> users;
std::vector<Anope::string> channels;
std::vector<Anope::string> normal;
bool raw_io;
bool debug;
LogInfo(int logage, bool rawio, bool debug);
~LogInfo();
void OpenLogFiles();
bool HasType(LogType ltype, const Anope::string &type) const;
/* Logs the message l if configured to */
void ProcessMessage(const Log *l);
};
#endif // LOGGER_H

56
include/mail.h Normal file
View File

@ -0,0 +1,56 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef MAIL_H
#define MAIL_H
#include "anope.h"
#include "threadengine.h"
#include "serialize.h"
namespace Mail
{
extern CoreExport bool Send(User *from, NickCore *to, BotInfo *service, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool Send(NickCore *to, const Anope::string &subject, const Anope::string &message);
extern CoreExport bool Validate(const Anope::string &email);
/* A email message being sent */
class Message : public Thread
{
private:
Anope::string sendmail_path;
Anope::string send_from;
Anope::string mail_to;
Anope::string addr;
Anope::string subject;
Anope::string message;
bool dont_quote_addresses;
bool success;
public:
/** Construct this message. Once constructed call Thread::Start to launch the mail sending.
* @param sf Config->SendFrom
* @param mailto Name of person being mailed (u->nick, nc->display, etc)
* @param addr Destination address to mail
* @param subject Message subject
* @param message The actual message
*/
Message(const Anope::string &sf, const Anope::string &mailto, const Anope::string &addr, const Anope::string &subject, const Anope::string &message);
~Message();
/* Called from within the thread to actually send the mail */
void Run() anope_override;
};
} // namespace Mail
#endif // MAIL_H

55
include/memo.h Normal file
View File

@ -0,0 +1,55 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef MEMO_H
#define MEMO_H
#include "anope.h"
#include "serialize.h"
class CoreExport Memo : public Serializable
{
public:
MemoInfo *mi;
bool unread;
bool receipt;
Memo();
~Memo();
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
Anope::string owner;
/* When it was sent */
time_t time;
Anope::string sender;
Anope::string text;
};
/* Memo info structures. Since both nicknames and channels can have memos,
* we encapsulate memo data in a MemoInfo to make it easier to handle.
*/
struct CoreExport MemoInfo
{
int16_t memomax;
Serialize::Checker<std::vector<Memo *> > memos;
std::vector<Anope::string> ignores;
MemoInfo();
Memo *GetMemo(unsigned index) const;
unsigned GetIndex(Memo *m) const;
void Del(unsigned index);
bool HasIgnore(User *u);
static MemoInfo *GetMemoInfo(const Anope::string &targ, bool &is_chan);
};
#endif // MEMO_H

173
include/messages.h Normal file
View File

@ -0,0 +1,173 @@
/*
*
* (C) 2003-2022 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 "protocol.h"
/* Common IRCD messages.
* Protocol modules may chose to include some, none, or all of these handlers
* as they see fit.
*/
namespace Message
{
struct CoreExport Away : IRCDMessage
{
Away(Module *creator, const Anope::string &mname = "AWAY") : IRCDMessage(creator, mname, 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Capab : IRCDMessage
{
Capab(Module *creator, const Anope::string &mname = "CAPAB") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Error : IRCDMessage
{
Error(Module *creator, const Anope::string &mname = "ERROR") : IRCDMessage(creator, mname, 1) { }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Invite : IRCDMessage
{
Invite(Module *creator, const Anope::string &mname = "INVITE") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Join : IRCDMessage
{
Join(Module *creator, const Anope::string &mname = "JOIN") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
typedef std::pair<ChannelStatus, User *> SJoinUser;
/** Handle a SJOIN.
* @param source The source of the SJOIN
* @param chan The channel the users are joining to
* @param ts The TS for the channel
* @param modes The modes sent with the SJOIN, if any
* @param users The users and their status, if any
*/
static void SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users);
};
struct CoreExport Kick : IRCDMessage
{
Kick(Module *creator, const Anope::string &mname = "KICK") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Kill : IRCDMessage
{
Kill(Module *creator, const Anope::string &mname = "KILL") : IRCDMessage(creator, mname, 2) { }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Mode : IRCDMessage
{
Mode(Module *creator, const Anope::string &mname = "MODE") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport MOTD : IRCDMessage
{
MOTD(Module *creator, const Anope::string &mname = "MOTD") : IRCDMessage(creator, mname, 1) { }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Notice : IRCDMessage
{
Notice(Module *creator, const Anope::string &mname = "NOTICE") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Part : IRCDMessage
{
Part(Module *creator, const Anope::string &mname = "PART") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Ping : IRCDMessage
{
Ping(Module *creator, const Anope::string &mname = "PING") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Privmsg : IRCDMessage
{
Privmsg(Module *creator, const Anope::string &mname = "PRIVMSG") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Quit : IRCDMessage
{
Quit(Module *creator, const Anope::string &mname = "QUIT") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport SQuit : IRCDMessage
{
SQuit(Module *creator, const Anope::string &mname = "SQUIT") : IRCDMessage(creator, mname, 2) { }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Stats : IRCDMessage
{
Stats(Module *creator, const Anope::string &mname = "STATS") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Time : IRCDMessage
{
Time(Module *creator, const Anope::string &mname = "TIME") : IRCDMessage(creator, mname, 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Topic : IRCDMessage
{
Topic(Module *creator, const Anope::string &mname = "TOPIC") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Version : IRCDMessage
{
Version(Module *creator, const Anope::string &mname = "VERSION") : IRCDMessage(creator, mname, 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
struct CoreExport Whois : IRCDMessage
{
Whois(Module *creator, const Anope::string &mname = "WHOIS") : IRCDMessage(creator, mname, 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override;
};
} // namespace Message

422
include/modes.h Normal file
View File

@ -0,0 +1,422 @@
/* Mode support
*
* (C) 2008-2011 Adam <Adam@anope.org>
* (C) 2008-2022 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
#ifndef MODES_H
#define MODES_H
#include "anope.h"
#include "base.h"
/** The different types of modes
*/
enum ModeType
{
/* Regular mode */
MODE_REGULAR,
/* b/e/I */
MODE_LIST,
/* k/l etc */
MODE_PARAM,
/* v/h/o/a/q */
MODE_STATUS
};
/* Classes of modes, Channel modes and User modes
*/
enum ModeClass
{
MC_CHANNEL,
MC_USER
};
/** This class is the basis of all modes in Anope
*/
class CoreExport Mode : public Base
{
public:
/* Mode name */
Anope::string name;
/* Class of mode this is (user/channel) */
ModeClass mclass;
/* Mode char for this, eg 'b' */
char mchar;
/* Type of mode this is, eg MODE_LIST */
ModeType type;
/** constructor
* @param mname The mode name
* @param mclass The type of mode this is
* @param mc The mode char
* @param type The mode type
*/
Mode(const Anope::string &mname, ModeClass mclass, char mc, ModeType type);
virtual ~Mode();
/** 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
*/
class CoreExport UserMode : public Mode
{
public:
/** constructor
* @param name The mode name
* @param mc The mode char
*/
UserMode(const Anope::string &name, char mc);
};
class CoreExport UserModeParam : public UserMode
{
public:
/** constructor
* @param name The mode name
* @param mc The mode char
*/
UserModeParam(const Anope::string &name, char mc);
/** Check if the param is valid
* @param value The param
* @return true or false
*/
virtual bool IsValid(Anope::string &value) const { return true; }
};
/** This class is a channel mode, all channel modes use this/inherit from this
*/
class CoreExport ChannelMode : public Mode
{
public:
/* channel modes that can possibly unwrap this mode */
std::vector<ChannelMode *> listeners;
/** constructor
* @param name The mode name
* @param mc The mode char
*/
ChannelMode(const Anope::string &name, char mc);
bool CanSet(User *u) const anope_override;
virtual void Check() { }
/** 'wrap' this channel mode and param to the underlying mode and param
*/
virtual ChannelMode *Wrap(Anope::string &param);
/** 'unwrap' this mode to our internal representation
*/
ChannelMode *Unwrap(Anope::string &param);
/** called when a mode is being unwrapped, and is asking us if we can unwrap it
*/
virtual ChannelMode *Unwrap(ChannelMode *, Anope::string &param);
};
/** This is a mode for lists, eg b/e/I. These modes should inherit from this
*/
class CoreExport ChannelModeList : public ChannelMode
{
public:
/** constructor
* @param name The mode name
* @param mc The mode char
*/
ChannelModeList(const Anope::string &name, char mc);
/** Is the mask valid
* @param mask The mask
* @return true for yes, false for no
*/
virtual bool IsValid(Anope::string &mask) const;
/** Checks if mask affects user
* Should only be used for extbans or other weird ircd-specific things.
* @param u The user
* @param e The entry to match against
* @return true on match
*/
virtual bool Matches(User *u, const Entry *e) { return false; }
/** Called when a mask is added to a channel
* @param chan The channel
* @param mask The mask
*/
virtual void OnAdd(Channel *chan, const Anope::string &mask) { }
/** Called when a mask is removed from a channel
* @param chan The channel
* @param mask The mask
*/
virtual void OnDel(Channel *chan, const Anope::string &mask) { }
};
/** This is a mode with a paramater, eg +k/l. These modes should use/inherit from this
*/
class CoreExport ChannelModeParam : public ChannelMode
{
public:
/** constructor
* @param name The mode name
* @param mc The mode char
* @param minus_no_arg true if this mode sends no arg when unsetting
*/
ChannelModeParam(const Anope::string &name, char mc, bool minus_no_arg = false);
/* Should we send an arg when unsetting this mode? */
bool minus_no_arg;
/** Is the param valid
* @param value The param
* @return true for yes, false for no
*/
virtual bool IsValid(Anope::string &value) const { return true; }
};
/** This is a mode that is a channel status, eg +v/h/o/a/q.
*/
class CoreExport ChannelModeStatus : public ChannelMode
{
public:
/* The symbol, eg @ % + */
char symbol;
/* The "level" of the mode, used to compare with other modes.
* Used so we know op > halfop > voice etc.
*/
unsigned level;
/** constructor
* @param name The mode name
* @param mc The mode char
* @param msymbol The symbol for the mode, eg @ %
* @param mlevel A level for the mode, which is usually determined by the PREFIX capab
*/
ChannelModeStatus(const Anope::string &name, char mc, char msymbol, unsigned mlevel);
};
/** A virtual mode. This mode doesn't natively exist on the IRCd (like extbans),
* but we still have a representation for it.
*/
template<typename T>
class CoreExport ChannelModeVirtual : public T
{
Anope::string base;
ChannelMode *basech;
public:
ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename);
~ChannelModeVirtual();
void Check() anope_override;
ChannelMode *Wrap(Anope::string &param) anope_override;
ChannelMode *Unwrap(ChannelMode *cm, Anope::string &param) anope_override = 0;
};
/* The status a user has on a channel (+v, +h, +o) etc */
class CoreExport ChannelStatus
{
Anope::string modes;
public:
ChannelStatus();
ChannelStatus(const Anope::string &modes);
void AddMode(char c);
void DelMode(char c);
bool HasMode(char c) const;
bool Empty() const;
void Clear();
const Anope::string &Modes() const;
Anope::string BuildModePrefixList() const;
};
class CoreExport UserModeOperOnly : public UserMode
{
public:
UserModeOperOnly(const Anope::string &mname, char um) : UserMode(mname, um) { }
bool CanSet(User *u) const anope_override;
};
class CoreExport UserModeNoone : public UserMode
{
public:
UserModeNoone(const Anope::string &mname, char um) : UserMode(mname, um) { }
bool CanSet(User *u) const anope_override;
};
/** Channel mode +k (key)
*/
class CoreExport ChannelModeKey : public ChannelModeParam
{
public:
ChannelModeKey(char mc) : ChannelModeParam("KEY", mc) { }
bool IsValid(Anope::string &value) const anope_override;
};
/** This class is used for oper only channel modes
*/
class CoreExport ChannelModeOperOnly : public ChannelMode
{
public:
ChannelModeOperOnly(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
/* Opers only */
bool CanSet(User *u) const anope_override;
};
/** This class is used for channel modes only servers may set
*/
class CoreExport ChannelModeNoone : public ChannelMode
{
public:
ChannelModeNoone(const Anope::string &mname, char mc) : ChannelMode(mname, mc) { }
bool CanSet(User *u) const anope_override;
};
/** This is the mode manager
* It contains functions for adding modes to Anope so Anope can track them
* and do things such as MLOCK.
* This also contains a mode stacker that will combine multiple modes and set
* them on a channel or user at once
*/
class CoreExport ModeManager
{
public:
/* Number of generic channel and user modes we are tracking */
static unsigned GenericChannelModes;
static unsigned GenericUserModes;
/** Add a user mode to Anope
* @param um A UserMode or UserMode derived class
* @return true on success, false on error
*/
static bool AddUserMode(UserMode *um);
/** Add a channel mode to Anope
* @param cm A ChannelMode or ChannelMode derived class
* @return true on success, false on error
*/
static bool AddChannelMode(ChannelMode *cm);
/** Remove a user mode from Anope
* @param um A UserMode to remove
*/
static void RemoveUserMode(UserMode *um);
/** Remove a channel mode from Anope
* @param um A ChanneMode to remove
*/
static void RemoveChannelMode(ChannelMode *cm);
/** Find a channel mode
* @param mode The mode
* @return The mode class
*/
static ChannelMode *FindChannelModeByChar(char mode);
/** Find a user mode
* @param mode The mode
* @return The mode class
*/
static UserMode *FindUserModeByChar(char mode);
/** Find a channel mode
* @param name The modename
* @return The mode class
*/
static ChannelMode *FindChannelModeByName(const Anope::string &name);
/** Find a user mode
* @param name The modename
* @return The mode class
*/
static UserMode *FindUserModeByName(const Anope::string &name);
/** Gets the channel mode char for a symbol (eg + returns v)
* @param symbol The symbol
* @return The char
*/
static char GetStatusChar(char symbol);
static const std::vector<ChannelMode *> &GetChannelModes();
static const std::vector<UserMode *> &GetUserModes();
static const std::vector<ChannelModeStatus *> &GetStatusChannelModesByRank();
static void RebuildStatusModes();
/** Add a mode to the stacker to be set on a channel
* @param bi The client to set the modes from
* @param c The channel
* @param cm The channel mode
* @param set true for setting, false for removing
* @param param The param, if there is one
*/
static void StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool set, const Anope::string &param = "");
/** Add a mode to the stacker to be set on a user
* @param bi The client to set the modes from
* @param u The user
* @param um The user mode
* @param set true for setting, false for removing
* @param param The param, if there is one
*/
static void StackerAdd(BotInfo *bi, User *u, UserMode *um, bool set, const Anope::string &param = "");
/** Process all of the modes in the stacker and send them to the IRCd to be set on channels/users
*/
static void ProcessModes();
/** Delete a user, channel, or mode from the stacker
*/
static void StackerDel(User *u);
static void StackerDel(Channel *c);
static void StackerDel(Mode *m);
};
/** Represents a mask set on a channel (b/e/I)
*/
class CoreExport Entry
{
Anope::string name;
Anope::string mask;
public:
unsigned short cidr_len;
int family;
Anope::string nick, user, host, real;
/** Constructor
* @param mode What mode this host is for, can be empty for unknown/no mode
* @param host A full or partial nick!ident@host/cidr#real name mask
*/
Entry(const Anope::string &mode, const Anope::string &host);
/** Get the banned mask for this entry
* @return The mask
*/
const Anope::string GetMask() const;
const Anope::string GetNUHMask() const;
/** Check if this entry matches a user
* @param u The user
* @param full True to match against a users real host and IP
* @return true on match
*/
bool Matches(User *u, bool full = false) const;
};
#endif // MODES_H

54
include/module.h Normal file
View File

@ -0,0 +1,54 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef MODULE_H
#define MODULE_H
#include "access.h"
#include "account.h"
#include "anope.h"
#include "base.h"
#include "bots.h"
#include "channels.h"
#include "commands.h"
#include "config.h"
#include "extensible.h"
#include "hashcomp.h"
#include "language.h"
#include "lists.h"
#include "logger.h"
#include "mail.h"
#include "memo.h"
#include "messages.h"
#include "modes.h"
#include "modules.h"
#include "opertype.h"
#include "protocol.h"
#include "regexpr.h"
#include "regchannel.h"
#include "serialize.h"
#include "servers.h"
#include "service.h"
#include "services.h"
#include "socketengine.h"
#include "sockets.h"
#include "threadengine.h"
#include "timers.h"
#include "uplink.h"
#include "users.h"
#include "xline.h"
#include "modules/pseudoclients/chanserv.h"
#include "modules/pseudoclients/global.h"
#include "modules/pseudoclients/memoserv.h"
#include "modules/pseudoclients/nickserv.h"
#endif // MODULE_H

1239
include/modules.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,70 @@
/* BotServ core functions
*
* (C) 2003-2022 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.
*/
/** Flags for badwords
*/
enum BadWordType
{
/* Always kicks if the word is said */
BW_ANY,
/* User must way the entire word */
BW_SINGLE,
/* The word has to start with the badword */
BW_START,
/* The word has to end with the badword */
BW_END
};
/* Structure used to contain bad words. */
struct BadWord
{
Anope::string chan;
Anope::string word;
BadWordType type;
virtual ~BadWord() { }
protected:
BadWord() { }
};
struct BadWords
{
virtual ~BadWords() { }
/** Add a badword to the badword list
* @param word The badword
* @param type The type (SINGLE START END)
* @return The badword
*/
virtual BadWord* AddBadWord(const Anope::string &word, BadWordType type) = 0;
/** Get a badword structure by index
* @param index The index
* @return The badword
*/
virtual BadWord* GetBadWord(unsigned index) const = 0;
/** Get how many badwords are on this channel
* @return The number of badwords in the vector
*/
virtual unsigned GetBadWordCount() const = 0;
/** Remove a badword
* @param index The index of the badword
*/
virtual void EraseBadWord(unsigned index) = 0;
/** Clear all badwords from the channel
*/
virtual void ClearBadWords() = 0;
virtual void Check() = 0;
};

44
include/modules/bs_kick.h Normal file
View File

@ -0,0 +1,44 @@
/* BotServ core functions
*
* (C) 2003-2022 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.
*/
/* Indices for TTB (Times To Ban) */
enum
{
TTB_BOLDS,
TTB_COLORS,
TTB_REVERSES,
TTB_UNDERLINES,
TTB_BADWORDS,
TTB_CAPS,
TTB_FLOOD,
TTB_REPEAT,
TTB_ITALICS,
TTB_AMSGS,
TTB_SIZE
};
struct KickerData
{
bool amsgs, badwords, bolds, caps, colors, flood, italics, repeat, reverses, underlines;
int16_t ttb[TTB_SIZE]; /* Times to ban for each kicker */
int16_t capsmin, capspercent; /* For CAPS kicker */
int16_t floodlines, floodsecs; /* For FLOOD kicker */
int16_t repeattimes; /* For REPEAT kicker */
bool dontkickops, dontkickvoices;
protected:
KickerData() { }
public:
virtual ~KickerData() { }
virtual void Check(ChannelInfo *ci) = 0;
};

View File

@ -0,0 +1,34 @@
/*
*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
struct EntryMsg
{
Anope::string chan;
Anope::string creator;
Anope::string message;
time_t when;
virtual ~EntryMsg() { }
protected:
EntryMsg() { }
};
struct EntryMessageList : Serialize::Checker<std::vector<EntryMsg *> >
{
protected:
EntryMessageList() : Serialize::Checker<std::vector<EntryMsg *> >("EntryMsg") { }
public:
virtual ~EntryMessageList()
{
for (unsigned i = (*this)->size(); i > 0; --i)
delete (*this)->at(i - 1);
}
virtual EntryMsg* Create() = 0;
};

42
include/modules/cs_log.h Normal file
View File

@ -0,0 +1,42 @@
/* ChanServ core functions
*
* (C) 2003-2022 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.
*/
struct LogSetting
{
Anope::string chan;
/* Our service name of the command */
Anope::string service_name;
/* The name of the client the command is on */
Anope::string command_service;
/* Name of the command to the user, can have spaces */
Anope::string command_name;
Anope::string method, extra;
Anope::string creator;
time_t created;
virtual ~LogSetting() { }
protected:
LogSetting() { }
};
struct LogSettings : Serialize::Checker<std::vector<LogSetting *> >
{
typedef std::vector<LogSetting *>::iterator iterator;
protected:
LogSettings() : Serialize::Checker<std::vector<LogSetting *> >("LogSetting")
{
}
public:
virtual ~LogSettings() { }
virtual LogSetting *Create() = 0;
};

89
include/modules/cs_mode.h Normal file
View File

@ -0,0 +1,89 @@
/* ChanServ core functions
*
* (C) 2003-2022 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.
*/
struct ModeLock
{
Anope::string ci;
bool set;
Anope::string name;
Anope::string param;
Anope::string setter;
time_t created;
virtual ~ModeLock() { }
protected:
ModeLock() { }
};
struct ModeLocks
{
typedef std::vector<ModeLock *> ModeList;
virtual ~ModeLocks() { }
/** Check if a mode is mlocked
* @param mode The mode
* @param An optional param
* @param status True to check mlock on, false for mlock off
* @return true on success, false on fail
*/
virtual bool HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const = 0;
/** Set a mlock
* @param mode The mode
* @param status True for mlock on, false for mlock off
* @param param An optional param arg for + mlocked modes
* @param setter Who is setting the mlock
* @param created When the mlock was created
* @return true on success, false on failure (module blocking)
*/
virtual bool SetMLock(ChannelMode *mode, bool status, const Anope::string &param = "", Anope::string setter = "", time_t created = Anope::CurTime) = 0;
/** Remove a mlock
* @param mode The mode
* @param status True for mlock on, false for mlock off
* @param param The param of the mode, required if it is a list or status mode
* @return true on success, false on failure
*/
virtual bool RemoveMLock(ChannelMode *mode, bool status, const Anope::string &param = "") = 0;
virtual void RemoveMLock(ModeLock *mlock) = 0;
/** Clear all mlocks on the channel
*/
virtual void ClearMLock() = 0;
/** Get all of the mlocks for this channel
* @return The mlocks
*/
virtual const ModeList &GetMLock() const = 0;
/** Get a list of mode locks on a channel
* @param name The mode name to get a list of
* @return a list of mlocks for the given mode
*/
virtual std::list<ModeLock *> GetModeLockList(const Anope::string &name) = 0;
/** Get details for a specific mlock
* @param mname The mode name
* @param An optional param to match with
* @return The MLock, if any
*/
virtual const ModeLock *GetMLock(const Anope::string &mname, const Anope::string &param = "") = 0;
/** Get the current mode locks as a string
* @param complete True to show mlock parameters as well
* @return A string of mode locks, eg: +nrt
*/
virtual Anope::string GetMLockAsString(bool complete) const = 0;
virtual void Check() = 0;
};

178
include/modules/dns.h Normal file
View File

@ -0,0 +1,178 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef DNS_H
#define DNS_H
namespace DNS
{
/** Valid query types
*/
enum QueryType
{
/* Nothing */
QUERY_NONE,
/* A simple A lookup */
QUERY_A = 1,
/* An authoritative name server */
QUERY_NS = 2,
/* A CNAME lookup */
QUERY_CNAME = 5,
/* Start of a zone of authority */
QUERY_SOA = 6,
/* Reverse DNS lookup */
QUERY_PTR = 12,
/* IPv6 AAAA lookup */
QUERY_AAAA = 28,
/* Zone transfer */
QUERY_AXFR = 252,
/* A lookup for any record */
QUERY_ANY = 255
};
/** Flags that can be AND'd into DNSPacket::flags to receive certain values
*/
enum
{
QUERYFLAGS_QR = 0x8000,
QUERYFLAGS_OPCODE = 0x7800,
QUERYFLAGS_OPCODE_NOTIFY = 0x2000,
QUERYFLAGS_AA = 0x400,
QUERYFLAGS_TC = 0x200,
QUERYFLAGS_RD = 0x100,
QUERYFLAGS_RA = 0x80,
QUERYFLAGS_Z = 0x70,
QUERYFLAGS_RCODE = 0xF
};
enum Error
{
ERROR_NONE,
ERROR_UNKNOWN,
ERROR_UNLOADED,
ERROR_TIMEDOUT,
ERROR_NOT_AN_ANSWER,
ERROR_NONSTANDARD_QUERY,
ERROR_FORMAT_ERROR,
ERROR_SERVER_FAILURE,
ERROR_DOMAIN_NOT_FOUND,
ERROR_NOT_IMPLEMENTED,
ERROR_REFUSED,
ERROR_NO_RECORDS,
ERROR_INVALIDTYPE
};
struct Question
{
Anope::string name;
QueryType type;
unsigned short qclass;
Question() : type(QUERY_NONE), qclass(0) { }
Question(const Anope::string &n, QueryType t, unsigned short c = 1) : name(n), type(t), qclass(c) { }
inline bool operator==(const Question & other) const { return name == other.name && type == other.type && qclass == other.qclass; }
struct hash
{
size_t operator()(const Question &q) const
{
return Anope::hash_ci()(q.name);
}
};
};
struct ResourceRecord : Question
{
unsigned int ttl;
Anope::string rdata;
time_t created;
ResourceRecord(const Anope::string &n, QueryType t, unsigned short c = 1) : Question(n, t, c), ttl(0), created(Anope::CurTime) { }
ResourceRecord(const Question &q) : Question(q), ttl(0), created(Anope::CurTime) { }
};
struct Query
{
std::vector<Question> questions;
std::vector<ResourceRecord> answers, authorities, additional;
Error error;
Query() : error(ERROR_NONE) { }
Query(const Question &q) : error(ERROR_NONE) { questions.push_back(q); }
};
class ReplySocket;
class Request;
/** DNS manager
*/
class Manager : public Service
{
public:
Manager(Module *creator) : Service(creator, "DNS::Manager", "dns/manager") { }
virtual ~Manager() { }
virtual void Process(Request *req) = 0;
virtual void RemoveRequest(Request *req) = 0;
virtual bool HandlePacket(ReplySocket *s, const unsigned char *const data, int len, sockaddrs *from) = 0;
virtual void UpdateSerial() = 0;
virtual void Notify(const Anope::string &zone) = 0;
virtual uint32_t GetSerial() const = 0;
};
/** A DNS query.
*/
class Request : public Timer, public Question
{
Manager *manager;
public:
/* Use result cache if available */
bool use_cache;
/* Request id */
unsigned short id;
/* Creator of this request */
Module *creator;
Request(Manager *mgr, Module *c, const Anope::string &addr, QueryType qt, bool cache = false) : Timer(0), Question(addr, qt), manager(mgr),
use_cache(cache), id(0), creator(c) { }
virtual ~Request()
{
manager->RemoveRequest(this);
}
/** Called when this request succeeds
* @param r The query sent back from the nameserver
*/
virtual void OnLookupComplete(const Query *r) = 0;
/** Called when this request fails or times out.
* @param r The query sent back from the nameserver, check the error code.
*/
virtual void OnError(const Query *r) { }
/** Used to time out the query, xalls OnError and lets the TimerManager
* delete this request.
*/
void Tick(time_t) anope_override
{
Log(LOG_DEBUG_2) << "Resolver: timeout for query " << this->name;
Query rr(*this);
rr.error = ERROR_TIMEDOUT;
this->OnError(&rr);
}
};
} // namespace DNS
#endif // DNS_H

View File

@ -0,0 +1,35 @@
/*
*
* (C) 2003-2022 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.
*/
namespace Encryption
{
typedef std::pair<const unsigned char *, size_t> Hash;
typedef std::pair<const uint32_t *, size_t> IV;
class Context
{
public:
virtual ~Context() { }
virtual void Update(const unsigned char *data, size_t len) = 0;
virtual void Finalize() = 0;
virtual Hash GetFinalizedHash() = 0;
};
class Provider : public Service
{
public:
Provider(Module *creator, const Anope::string &sname) : Service(creator, "Encryption::Provider", sname) { }
virtual ~Provider() { }
virtual Context *CreateContext(IV * = NULL) = 0;
virtual IV GetDefaultIV() = 0;
};
}

243
include/modules/httpd.h Normal file
View File

@ -0,0 +1,243 @@
/*
*
* (C) 2012-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef ANOPE_HTTPD_H
#define ANOPE_HTTPD_H
enum HTTPError
{
HTTP_ERROR_OK = 200,
HTTP_FOUND = 302,
HTTP_BAD_REQUEST = 400,
HTTP_PAGE_NOT_FOUND = 404,
HTTP_NOT_SUPPORTED = 505
};
/* A message to someone */
struct HTTPReply
{
HTTPError error;
Anope::string content_type;
std::map<Anope::string, Anope::string, ci::less> headers;
typedef std::list<std::pair<Anope::string, Anope::string> > cookie;
std::vector<cookie> cookies;
HTTPReply() : error(HTTP_ERROR_OK), length(0) { }
HTTPReply(const HTTPReply& other) : error(other.error), length(other.length)
{
content_type = other.content_type;
headers = other.headers;
cookies = other.cookies;
for (unsigned i = 0; i < other.out.size(); ++i)
out.push_back(new Data(other.out[i]->buf, other.out[i]->len));
}
~HTTPReply()
{
for (unsigned i = 0; i < out.size(); ++i)
delete out[i];
out.clear();
}
struct Data
{
char *buf;
size_t len;
Data(const char *b, size_t l)
{
this->buf = new char[l];
memcpy(this->buf, b, l);
this->len = l;
}
~Data()
{
delete [] buf;
}
};
std::deque<Data *> out;
size_t length;
void Write(const Anope::string &message)
{
this->out.push_back(new Data(message.c_str(), message.length()));
this->length += message.length();
}
void Write(const char *b, size_t l)
{
this->out.push_back(new Data(b, l));
this->length += l;
}
};
/* A message from someone */
struct HTTPMessage
{
std::map<Anope::string, Anope::string> headers;
std::map<Anope::string, Anope::string> cookies;
std::map<Anope::string, Anope::string> get_data;
std::map<Anope::string, Anope::string> post_data;
Anope::string content;
};
class HTTPClient;
class HTTPProvider;
class HTTPPage : public Base
{
Anope::string url;
Anope::string content_type;
public:
HTTPPage(const Anope::string &u, const Anope::string &ct = "text/html") : url(u), content_type(ct) { }
const Anope::string &GetURL() const { return this->url; }
const Anope::string &GetContentType() const { return this->content_type; }
/** Called when this page is requested
* @param The server this page is on
* @param The page name
* @param The client requesting the page
* @param The HTTP header sent from the client to request the page
* @param The HTTP header that will be sent back to the client
*/
virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0;
};
class HTTPClient : public ClientSocket, public BinarySocket, public Base
{
protected:
void WriteClient(const Anope::string &message)
{
BinarySocket::Write(message + "\r\n");
}
public:
HTTPClient(ListenSocket *l, int f, const sockaddrs &a) : ClientSocket(l, a), BinarySocket() { }
virtual const Anope::string GetIP()
{
return this->clientaddr.addr();
}
virtual void SendError(HTTPError err, const Anope::string &msg) = 0;
virtual void SendReply(HTTPReply *) = 0;
};
class HTTPProvider : public ListenSocket, public Service
{
Anope::string ip;
unsigned short port;
bool ssl;
public:
std::vector<Anope::string> ext_ips;
std::vector<Anope::string> ext_headers;
HTTPProvider(Module *c, const Anope::string &n, const Anope::string &i, const unsigned short p, bool s) : ListenSocket(i, p, i.find(':') != Anope::string::npos), Service(c, "HTTPProvider", n), ip(i), port(p), ssl(s) { }
const Anope::string &GetIP() const
{
return this->ip;
}
unsigned short GetPort() const
{
return this->port;
}
bool IsSSL() const
{
return this->ssl;
}
virtual bool RegisterPage(HTTPPage *page) = 0;
virtual void UnregisterPage(HTTPPage *page) = 0;
virtual HTTPPage* FindPage(const Anope::string &name) = 0;
};
namespace HTTPUtils
{
inline Anope::string URLDecode(const Anope::string &url)
{
Anope::string decoded;
for (unsigned i = 0; i < url.length(); ++i)
{
const char& c = url[i];
if (c == '%' && i + 2 < url.length())
{
Anope::string dest;
Anope::Unhex(url.substr(i + 1, 2), dest);
decoded += dest;
i += 2;
}
else if (c == '+')
decoded += ' ';
else
decoded += c;
}
return decoded;
}
inline Anope::string URLEncode(const Anope::string &url)
{
Anope::string encoded;
for (unsigned i = 0; i < url.length(); ++i)
{
const char& c = url[i];
if (isalnum(c) || c == '.' || c == '-' || c == '*' || c == '_')
encoded += c;
else if (c == ' ')
encoded += '+';
else
encoded += "%" + Anope::Hex(c);
}
return encoded;
}
inline Anope::string Escape(const Anope::string &src)
{
Anope::string dst;
for (unsigned i = 0; i < src.length(); ++i)
{
switch (src[i])
{
case '<':
dst += "&lt;";
break;
case '>':
dst += "&gt;";
break;
case '"':
dst += "&quot;";
break;
case '&':
dst += "&amp;";
break;
default:
dst += src[i];
}
}
return dst;
}
}
#endif // ANOPE_HTTPD_H

171
include/modules/ldap.h Normal file
View File

@ -0,0 +1,171 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef ANOPE_LDAP_H
#define ANOPE_LDAP_H
class LDAPException : public ModuleException
{
public:
LDAPException(const Anope::string &reason) : ModuleException(reason) { }
virtual ~LDAPException() throw() { }
};
struct LDAPModification
{
enum LDAPOperation
{
LDAP_ADD,
LDAP_DEL,
LDAP_REPLACE
};
LDAPOperation op;
Anope::string name;
std::vector<Anope::string> values;
};
typedef std::vector<LDAPModification> LDAPMods;
struct LDAPAttributes : public std::map<Anope::string, std::vector<Anope::string> >
{
size_t size(const Anope::string &attr) const
{
const std::vector<Anope::string>& array = this->getArray(attr);
return array.size();
}
const std::vector<Anope::string> keys() const
{
std::vector<Anope::string> k;
for (const_iterator it = this->begin(), it_end = this->end(); it != it_end; ++it)
k.push_back(it->first);
return k;
}
const Anope::string &get(const Anope::string &attr) const
{
const std::vector<Anope::string>& array = this->getArray(attr);
if (array.empty())
throw LDAPException("Empty attribute " + attr + " in LDAPResult::get");
return array[0];
}
const std::vector<Anope::string>& getArray(const Anope::string &attr) const
{
const_iterator it = this->find(attr);
if (it == this->end())
throw LDAPException("Unknown attribute " + attr + " in LDAPResult::getArray");
return it->second;
}
};
enum QueryType
{
QUERY_UNKNOWN,
QUERY_BIND,
QUERY_SEARCH,
QUERY_ADD,
QUERY_DELETE,
QUERY_MODIFY
};
struct LDAPResult
{
std::vector<LDAPAttributes> messages;
Anope::string error;
QueryType type;
LDAPResult()
{
this->type = QUERY_UNKNOWN;
}
size_t size() const
{
return this->messages.size();
}
bool empty() const
{
return this->messages.empty();
}
const LDAPAttributes &get(size_t sz) const
{
if (sz >= this->messages.size())
throw LDAPException("Index out of range");
return this->messages[sz];
}
const Anope::string &getError() const
{
return this->error;
}
};
class LDAPInterface
{
public:
Module *owner;
LDAPInterface(Module *m) : owner(m) { }
virtual ~LDAPInterface() { }
virtual void OnResult(const LDAPResult &r) = 0;
virtual void OnError(const LDAPResult &err) = 0;
virtual void OnDelete() { }
};
class LDAPProvider : public Service
{
public:
LDAPProvider(Module *c, const Anope::string &n) : Service(c, "LDAPProvider", n) { }
/** Attempt to bind to the LDAP server as an admin
* @param i The LDAPInterface the result is sent to
*/
virtual void BindAsAdmin(LDAPInterface *i) = 0;
/** Bind to LDAP
* @param i The LDAPInterface the result is sent to
* @param who The binddn
* @param pass The password
*/
virtual void Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) = 0;
/** Search ldap for the specified filter
* @param i The LDAPInterface the result is sent to
* @param base The base DN to search
* @param filter The filter to apply
*/
virtual void Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) = 0;
/** Add an entry to LDAP
* @param i The LDAPInterface the result is sent to
* @param dn The dn of the entry to add
* @param attributes The attributes
*/
virtual void Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) = 0;
/** Delete an entry from LDAP
* @param i The LDAPInterface the result is sent to
* @param dn The dn of the entry to delete
*/
virtual void Del(LDAPInterface *i, const Anope::string &dn) = 0;
/** Modify an existing entry in LDAP
* @param i The LDAPInterface the result is sent to
* @param base The base DN to modify
* @param attributes The attributes to modify
*/
virtual void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) = 0;
};
#endif // ANOPE_LDAP_H

70
include/modules/ns_cert.h Normal file
View File

@ -0,0 +1,70 @@
/* NickServ core functions
*
* (C) 2003-2022 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.
*/
struct NSCertList
{
protected:
NSCertList() { }
public:
virtual ~NSCertList() { }
/** Add an entry to the nick's certificate list
*
* @param entry The fingerprint to add to the cert list
*
* Adds a new entry into the cert list.
*/
virtual void AddCert(const Anope::string &entry) = 0;
/** Get an entry from the nick's cert list by index
*
* @param entry Index in the certificate list vector to retrieve
* @return The fingerprint entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds
*
* Retrieves an entry from the certificate list corresponding to the given index.
*/
virtual Anope::string GetCert(unsigned entry) const = 0;
virtual unsigned GetCertCount() const = 0;
/** Find an entry in the nick's cert list
*
* @param entry The fingerprint to search for
* @return True if the fingerprint is found in the cert list, false otherwise
*
* Search for an fingerprint within the cert list.
*/
virtual bool FindCert(const Anope::string &entry) const = 0;
/** Erase a fingerprint from the nick's certificate list
*
* @param entry The fingerprint to remove
*
* Removes the specified fingerprint from the cert list.
*/
virtual void EraseCert(const Anope::string &entry) = 0;
/** Clears the entire nick's cert list
*
* Deletes all the memory allocated in the certificate list vector and then clears the vector.
*/
virtual void ClearCert() = 0;
virtual void Check() = 0;
};
class CertService : public Service
{
public:
CertService(Module *c) : Service(c, "CertService", "certs") { }
virtual NickCore* FindAccountFromCert(const Anope::string &cert) = 0;
};

View File

@ -0,0 +1,55 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef OS_FORBID_H
#define OS_FORBID_H
enum ForbidType
{
FT_NICK = 1,
FT_CHAN,
FT_EMAIL,
FT_REGISTER,
FT_SIZE
};
struct ForbidData
{
Anope::string mask;
Anope::string creator;
Anope::string reason;
time_t created;
time_t expires;
ForbidType type;
virtual ~ForbidData() { }
protected:
ForbidData() : created(0), expires(0) { }
};
class ForbidService : public Service
{
public:
ForbidService(Module *m) : Service(m, "ForbidService", "forbid") { }
virtual void AddForbid(ForbidData *d) = 0;
virtual void RemoveForbid(ForbidData *d) = 0;
virtual ForbidData* CreateForbid() = 0;
virtual ForbidData *FindForbid(const Anope::string &mask, ForbidType type) = 0;
virtual ForbidData *FindForbidExact(const Anope::string &mask, ForbidType type) = 0;
virtual std::vector<ForbidData *> GetForbids() = 0;
};
static ServiceReference<ForbidService> forbid_service("ForbidService", "forbid");
#endif

View File

@ -0,0 +1,43 @@
/* OperServ ignore interface
*
* (C) 2003-2022 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.
*/
struct IgnoreData
{
Anope::string mask;
Anope::string creator;
Anope::string reason;
time_t time; /* When do we stop ignoring them? */
virtual ~IgnoreData() { }
protected:
IgnoreData() : time(0) { }
};
class IgnoreService : public Service
{
protected:
IgnoreService(Module *c) : Service(c, "IgnoreService", "ignore") { }
public:
virtual void AddIgnore(IgnoreData *) = 0;
virtual void DelIgnore(IgnoreData *) = 0;
virtual void ClearIgnores() = 0;
virtual IgnoreData *Create() = 0;
virtual IgnoreData *Find(const Anope::string &mask) = 0;
virtual std::vector<IgnoreData *> &GetIgnores() = 0;
};
static ServiceReference<IgnoreService> ignore_service("IgnoreService", "ignore");

52
include/modules/os_news.h Normal file
View File

@ -0,0 +1,52 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef OS_NEWS
#define OS_NEWS
enum NewsType
{
NEWS_LOGON,
NEWS_RANDOM,
NEWS_OPER
};
struct NewsMessages
{
NewsType type;
Anope::string name;
const char *msgs[10];
};
struct NewsItem : Serializable
{
NewsType type;
Anope::string text;
Anope::string who;
time_t time;
NewsItem() : Serializable("NewsItem") { }
};
class NewsService : public Service
{
public:
NewsService(Module *m) : Service(m, "NewsService", "news") { }
virtual NewsItem *CreateNewsItem() = 0;
virtual void AddNewsItem(NewsItem *n) = 0;
virtual void DelNewsItem(NewsItem *n) = 0;
virtual std::vector<NewsItem *> &GetNewsList(NewsType t) = 0;
};
static ServiceReference<NewsService> news_service("NewsService", "news");
#endif // OS_NEWS

View File

@ -0,0 +1,94 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef OS_SESSION_H
#define OS_SESSION_H
struct Session
{
cidr addr; /* A cidr (sockaddrs + len) representing this session */
unsigned count; /* Number of clients with this host */
unsigned hits; /* Number of subsequent kills for a host */
Session(const sockaddrs &ip, int len) : addr(ip, len), count(1), hits(0) { }
};
struct Exception : Serializable
{
Anope::string mask; /* Hosts to which this exception applies */
unsigned limit; /* Session limit for exception */
Anope::string who; /* Nick of person who added the exception */
Anope::string reason; /* Reason for exception's addition */
time_t time; /* When this exception was added */
time_t expires; /* Time when it expires. 0 == no expiry */
Exception() : Serializable("Exception") { }
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
};
class SessionService : public Service
{
public:
typedef TR1NS::unordered_map<cidr, Session *, cidr::hash> SessionMap;
typedef std::vector<Exception *> ExceptionVector;
SessionService(Module *m) : Service(m, "SessionService", "session") { }
virtual Exception *CreateException() = 0;
virtual void AddException(Exception *e) = 0;
virtual void DelException(Exception *e) = 0;
virtual Exception *FindException(User *u) = 0;
virtual Exception *FindException(const Anope::string &host) = 0;
virtual ExceptionVector &GetExceptions() = 0;
virtual Session *FindSession(const Anope::string &ip) = 0;
virtual SessionMap &GetSessions() = 0;
};
static ServiceReference<SessionService> session_service("SessionService", "session");
void Exception::Serialize(Serialize::Data &data) const
{
data["mask"] << this->mask;
data["limit"] << this->limit;
data["who"] << this->who;
data["reason"] << this->reason;
data["time"] << this->time;
data["expires"] << this->expires;
}
Serializable* Exception::Unserialize(Serializable *obj, Serialize::Data &data)
{
if (!session_service)
return NULL;
Exception *ex;
if (obj)
ex = anope_dynamic_static_cast<Exception *>(obj);
else
ex = new Exception;
data["mask"] >> ex->mask;
data["limit"] >> ex->limit;
data["who"] >> ex->who;
data["reason"] >> ex->reason;
data["time"] >> ex->time;
data["expires"] >> ex->expires;
if (!obj)
session_service->AddException(ex);
return ex;
}
#endif

View File

@ -0,0 +1,25 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef CHANSERV_H
#define CHANSERV_H
class ChanServService : public Service
{
public:
ChanServService(Module *m) : Service(m, "ChanServService", "ChanServ")
{
}
/* Have ChanServ hold the channel, that is, join and set +nsti and wait
* for a few minutes so no one can join or rejoin.
*/
virtual void Hold(Channel *c) = 0;
};
#endif // CHANSERV_H

View File

@ -0,0 +1,30 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef GLOBAL_H
#define GLOBAL_H
class GlobalService : public Service
{
public:
GlobalService(Module *m) : Service(m, "GlobalService", "Global")
{
}
/** Retrieves the bot which sends global messages unless otherwise specified. */
virtual Reference<BotInfo> GetDefaultSender() = 0;
/** Send out a global message to all users
* @param sender Our client which should send the global
* @param source The sender of the global
* @param message The message
*/
virtual void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) = 0;
};
#endif // GLOBAL_H

View File

@ -0,0 +1,41 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef MEMOSERV_H
#define MEMOSERV_H
class MemoServService : public Service
{
public:
enum MemoResult
{
MEMO_SUCCESS,
MEMO_INVALID_TARGET,
MEMO_TOO_FAST,
MEMO_TARGET_FULL
};
MemoServService(Module *m) : Service(m, "MemoServService", "MemoServ")
{
}
/** Sends a memo.
* @param source The source of the memo, can be anything.
* @param target The target of the memo, nick or channel.
* @param message Memo text
* @param force true to force the memo, restrictions/delays etc are not checked
*/
virtual MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force = false) = 0;
/** Check for new memos and notify the user if there are any
* @param u The user
*/
virtual void Check(User *u) = 0;
};
#endif // MEMOSERV_H

View File

@ -0,0 +1,24 @@
/*
*
* (C) 2011-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef NICKSERV_H
#define NICKSERV_H
class NickServService : public Service
{
public:
NickServService(Module *m) : Service(m, "NickServService", "NickServ")
{
}
virtual void Validate(User *u) = 0;
virtual void Collide(User *u, NickAlias *na) = 0;
virtual void Release(NickAlias *na) = 0;
};
#endif // NICKSERV_H

74
include/modules/redis.h Normal file
View File

@ -0,0 +1,74 @@
/*
*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
namespace Redis
{
struct Reply
{
enum Type
{
NOT_PARSED,
NOT_OK,
OK,
INT,
BULK,
MULTI_BULK
}
type;
Reply() { Clear(); }
~Reply() { Clear(); }
void Clear()
{
type = NOT_PARSED;
i = 0;
bulk.clear();
multi_bulk_size = 0;
for (unsigned j = 0; j < multi_bulk.size(); ++j)
delete multi_bulk[j];
multi_bulk.clear();
}
int64_t i;
Anope::string bulk;
int multi_bulk_size;
std::deque<Reply *> multi_bulk;
};
class Interface
{
public:
Module *owner;
Interface(Module *m) : owner(m) { }
virtual ~Interface() { }
virtual void OnResult(const Reply &r) = 0;
virtual void OnError(const Anope::string &error) { Log(owner) << error; }
};
class Provider : public Service
{
public:
Provider(Module *c, const Anope::string &n) : Service(c, "Redis::Provider", n) { }
virtual bool IsSocketDead() = 0;
virtual void SendCommand(Interface *i, const std::vector<Anope::string> &cmds) = 0;
virtual void SendCommand(Interface *i, const Anope::string &str) = 0;
virtual bool BlockAndProcess() = 0;
virtual void Subscribe(Interface *i, const Anope::string &pattern) = 0;
virtual void Unsubscribe(const Anope::string &pattern) = 0;
virtual void StartTransaction() = 0;
virtual void CommitTransaction() = 0;
};
}

139
include/modules/sasl.h Normal file
View File

@ -0,0 +1,139 @@
/*
*
* (C) 2014-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
namespace SASL
{
struct Message
{
Anope::string source;
Anope::string target;
Anope::string type;
Anope::string data;
Anope::string ext;
};
class Mechanism;
struct Session;
class Service : public ::Service
{
public:
Service(Module *o) : ::Service(o, "SASL::Service", "sasl") { }
virtual void ProcessMessage(const Message &) = 0;
virtual Anope::string GetAgent() = 0;
virtual Session* GetSession(const Anope::string &uid) = 0;
virtual void SendMessage(SASL::Session *session, const Anope::string &type, const Anope::string &data) = 0;
virtual void Succeed(Session *, NickCore *) = 0;
virtual void Fail(Session *) = 0;
virtual void SendMechs(Session *) = 0;
virtual void DeleteSessions(Mechanism *, bool = false) = 0;
virtual void RemoveSession(Session *) = 0;
};
static ServiceReference<SASL::Service> sasl("SASL::Service", "sasl");
struct Session
{
time_t created;
Anope::string uid;
Anope::string hostname, ip;
Reference<Mechanism> mech;
Session(Mechanism *m, const Anope::string &u) : created(Anope::CurTime), uid(u), mech(m) { }
virtual ~Session()
{
if (sasl)
sasl->RemoveSession(this);
}
};
/* PLAIN, EXTERNAL, etc */
class Mechanism : public ::Service
{
public:
Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { }
virtual Session* CreateSession(const Anope::string &uid) { return new Session(this, uid); }
virtual void ProcessMessage(Session *session, const Message &) = 0;
virtual ~Mechanism()
{
if (sasl)
sasl->DeleteSessions(this, true);
}
};
class IdentifyRequest : public ::IdentifyRequest
{
Anope::string uid;
Anope::string hostname, ip;
public:
IdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass, const Anope::string &h, const Anope::string &i) : ::IdentifyRequest(m, acc, pass), uid(id), hostname(h), ip(i) { }
void OnSuccess() anope_override
{
if (!sasl)
return;
NickAlias *na = NickAlias::Find(GetAccount());
if (!na || na->nc->HasExt("NS_SUSPENDED") || na->nc->HasExt("UNCONFIRMED"))
return OnFail();
unsigned int maxlogins = Config->GetModule("ns_identify")->Get<unsigned int>("maxlogins");
if (maxlogins && na->nc->users.size() >= maxlogins)
return OnFail();
Session *s = sasl->GetSession(uid);
if (s)
{
Anope::string user = "A user";
if (!hostname.empty() && !ip.empty())
user = hostname + " (" + ip + ")";
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << user << " identified to account " << this->GetAccount() << " using SASL";
sasl->Succeed(s, na->nc);
delete s;
}
}
void OnFail() anope_override
{
if (!sasl)
return;
Session *s = sasl->GetSession(uid);
if (s)
{
sasl->Fail(s);
delete s;
}
Anope::string accountstatus;
NickAlias *na = NickAlias::Find(GetAccount());
if (!na)
accountstatus = "nonexistent ";
else if (na->nc->HasExt("NS_SUSPENDED"))
accountstatus = "suspended ";
else if (na->nc->HasExt("UNCONFIRMED"))
accountstatus = "unconfirmed ";
Anope::string user = "A user";
if (!hostname.empty() && !ip.empty())
user = hostname + " (" + ip + ")";
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << user << " failed to identify for " << accountstatus << "account " << this->GetAccount() << " using SASL";
}
};
}

View File

@ -0,0 +1,17 @@
/*
*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
struct MiscData
{
Anope::string object;
Anope::string name;
Anope::string data;
MiscData() { }
virtual ~MiscData() { }
};

216
include/modules/sql.h Normal file
View File

@ -0,0 +1,216 @@
/*
*
* (C) 2003-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
namespace SQL
{
class Data : public Serialize::Data
{
public:
typedef std::map<Anope::string, std::stringstream *> Map;
Map data;
std::map<Anope::string, Type> types;
~Data()
{
Clear();
}
std::iostream& operator[](const Anope::string &key) anope_override
{
std::stringstream *&ss = data[key];
if (!ss)
ss = new std::stringstream();
return *ss;
}
std::set<Anope::string> KeySet() const anope_override
{
std::set<Anope::string> keys;
for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
keys.insert(it->first);
return keys;
}
size_t Hash() const anope_override
{
size_t hash = 0;
for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
if (!it->second->str().empty())
hash ^= Anope::hash_cs()(it->second->str());
return hash;
}
std::map<Anope::string, std::iostream *> GetData() const
{
std::map<Anope::string, std::iostream *> d;
for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
d[it->first] = it->second;
return d;
}
void Clear()
{
for (Map::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
delete it->second;
this->data.clear();
}
void SetType(const Anope::string &key, Type t) anope_override
{
this->types[key] = t;
}
Type GetType(const Anope::string &key) const anope_override
{
std::map<Anope::string, Type>::const_iterator it = this->types.find(key);
if (it != this->types.end())
return it->second;
return DT_TEXT;
}
};
/** A SQL exception, can be thrown at various points
*/
class Exception : public ModuleException
{
public:
Exception(const Anope::string &reason) : ModuleException(reason) { }
virtual ~Exception() throw() { }
};
/** A SQL query
*/
struct QueryData
{
Anope::string data;
bool escape;
};
struct Query
{
Anope::string query;
std::map<Anope::string, QueryData> parameters;
Query() { }
Query(const Anope::string &q) : query(q) { }
Query& operator=(const Anope::string &q)
{
this->query = q;
this->parameters.clear();
return *this;
}
bool operator==(const Query &other) const
{
return this->query == other.query;
}
inline bool operator!=(const Query &other) const
{
return !(*this == other);
}
template<typename T> void SetValue(const Anope::string &key, const T& value, bool escape = true)
{
try
{
Anope::string string_value = stringify(value);
this->parameters[key].data = string_value;
this->parameters[key].escape = escape;
}
catch (const ConvertException &ex) { }
}
};
/** A result from a SQL query
*/
class Result
{
protected:
/* Rows, column, item */
std::vector<std::map<Anope::string, Anope::string> > entries;
Query query;
Anope::string error;
public:
unsigned int id;
Anope::string finished_query;
Result() : id(0) { }
Result(unsigned int i, const Query &q, const Anope::string &fq, const Anope::string &err = "") : query(q), error(err), id(i), finished_query(fq) { }
inline operator bool() const { return this->error.empty(); }
inline unsigned int GetID() const { return this->id; }
inline const Query &GetQuery() const { return this->query; }
inline const Anope::string &GetError() const { return this->error; }
int Rows() const { return this->entries.size(); }
const std::map<Anope::string, Anope::string> &Row(size_t index) const
{
try
{
return this->entries.at(index);
}
catch (const std::out_of_range &)
{
throw Exception("Out of bounds access to SQLResult");
}
}
const Anope::string Get(size_t index, const Anope::string &col) const
{
const std::map<Anope::string, Anope::string> rows = this->Row(index);
std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col);
if (it == rows.end())
throw Exception("Unknown column name in SQLResult: " + col);
return it->second;
}
};
/* An interface used by modules to retrieve the results
*/
class Interface
{
public:
Module *owner;
Interface(Module *m) : owner(m) { }
virtual ~Interface() { }
virtual void OnResult(const Result &r) = 0;
virtual void OnError(const Result &r) = 0;
};
/** Class providing the SQL service, modules call this to execute queries
*/
class Provider : public Service
{
public:
Provider(Module *c, const Anope::string &n) : Service(c, "SQL::Provider", n) { }
virtual void Run(Interface *i, const Query &query) = 0;
virtual Result RunQuery(const Query &query) = 0;
virtual std::vector<Query> CreateTable(const Anope::string &table, const Data &data) = 0;
virtual Query BuildInsert(const Anope::string &table, unsigned int id, Data &data) = 0;
virtual Query GetTables(const Anope::string &prefix) = 0;
virtual Anope::string FromUnixtime(time_t) = 0;
};
}

15
include/modules/ssl.h Normal file
View File

@ -0,0 +1,15 @@
/*
*
* (C) 2010-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
class SSLService : public Service
{
public:
SSLService(Module *o, const Anope::string &n) : Service(o, "SSLService", n) { }
virtual void Init(Socket *s) = 0;
};

19
include/modules/suspend.h Normal file
View File

@ -0,0 +1,19 @@
/*
*
* (C) 2003-2022 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.
*/
struct SuspendInfo
{
Anope::string what, by, reason;
time_t when, expires;
SuspendInfo() { }
virtual ~SuspendInfo() { }
};

47
include/modules/xmlrpc.h Normal file
View File

@ -0,0 +1,47 @@
/*
*
* (C) 2010-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#include "httpd.h"
class XMLRPCRequest
{
std::map<Anope::string, Anope::string> replies;
public:
Anope::string name;
Anope::string id;
std::deque<Anope::string> data;
HTTPReply& r;
XMLRPCRequest(HTTPReply &_r) : r(_r) { }
inline void reply(const Anope::string &dname, const Anope::string &ddata) { this->replies.insert(std::make_pair(dname, ddata)); }
inline const std::map<Anope::string, Anope::string> &get_replies() { return this->replies; }
};
class XMLRPCServiceInterface;
class XMLRPCEvent
{
public:
virtual ~XMLRPCEvent() { }
virtual bool Run(XMLRPCServiceInterface *iface, HTTPClient *client, XMLRPCRequest &request) = 0;
};
class XMLRPCServiceInterface : public Service
{
public:
XMLRPCServiceInterface(Module *creator, const Anope::string &sname) : Service(creator, "XMLRPCServiceInterface", sname) { }
virtual void Register(XMLRPCEvent *event) = 0;
virtual void Unregister(XMLRPCEvent *event) = 0;
virtual Anope::string Sanitize(const Anope::string &string) = 0;
virtual void Reply(XMLRPCRequest &request) = 0;
};

127
include/opertype.h Normal file
View File

@ -0,0 +1,127 @@
/*
*
* (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
* (C) 2008-2022 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
#ifndef OPERTYPE_H
#define OPERTYPE_H
#include "services.h"
#include "account.h"
/* A services operator. Usually made by the configuration file, but not always.
* NickAlias::Find(name)->nc->o == this
*/
struct CoreExport Oper
{
/* The oper's nick */
Anope::string name;
/* The type of operator this operator is */
OperType *ot;
/* Whether the user must be an IRC operator (umode +o) to be considered a services operator */
bool require_oper;
Anope::string password;
Anope::string certfp;
/* Hosts allowed to use this operator block */
std::vector<Anope::string> hosts;
Anope::string vhost;
Oper(const Anope::string &n, OperType *o);
virtual ~Oper();
static std::vector<Oper *> opers;
/** Find an oper block by name
* @param name The name
* @return the oper block
*/
static Oper *Find(const Anope::string &name);
};
class CoreExport OperType
{
private:
/** The name of this opertype, e.g. "sra".
*/
Anope::string name;
/** Privs that this opertype may use, e.g. 'users/auspex'.
* This *must* be std::list, see commands comment for details.
*/
std::list<Anope::string> privs;
/** Commands this user may execute, e.g:
* botserv/set/ *, botserv/set/private, botserv/ *
* et cetera.
*
* This *must* be std::list, not std::map, because
* we support full globbing here. This shouldn't be a problem
* as we don't invoke it often.
*/
std::list<Anope::string> commands;
/** Set of opertypes we inherit from
*/
std::set<OperType *> inheritances;
public:
/** Modes to set when someone identifies using this opertype
*/
Anope::string modes;
/** Find an oper type by name
* @param name The name
* @return The oper type
*/
static OperType *Find(const Anope::string &name);
/** Create a new opertype of the given name.
* @param nname The opertype name, e.g. "sra".
*/
OperType(const Anope::string &nname);
/** Check whether this opertype has access to run the given command string.
* @param cmdstr The string to check, e.g. botserv/set/private.
* @return True if this opertype may run the specified command, false otherwise.
*/
bool HasCommand(const Anope::string &cmdstr) const;
/** Check whether this opertype has access to the given special permission.
* @param privstr The priv to check for, e.g. users/auspex.
* @return True if this opertype has the specified priv, false otherwise.
*/
bool HasPriv(const Anope::string &privstr) const;
/** Add the specified command to this opertype.
* @param cmdstr The command mask to grant this opertype access to, e.g: nickserv/ *, chanserv/set/ *, botserv/set/private.
*/
void AddCommand(const Anope::string &cmdstr);
/** Add the specified priv mask to this opertype.
* @param privstr The specified mask of privs to grant this opertype access to, e.g. users/auspex, users/ *, etc.
*/
void AddPriv(const Anope::string &privstr);
/** Returns the name of this opertype.
*/
const Anope::string &GetName() const;
/** Make this opertype inherit commands and privs from another opertype
* @param ot The opertype to inherit from
*/
void Inherits(OperType *ot);
/** Gets the icommands for this opertype
* @return A list of commands
*/
const std::list<Anope::string> GetCommands() const;
/** Gets the privileges for this opertype
* @return A list of privileges
*/
const std::list<Anope::string> GetPrivs() const;
};
#endif // OPERTYPE_H

318
include/protocol.h Normal file
View File

@ -0,0 +1,318 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef PROTOCOL_H
#define PROTOCOL_H
#include "services.h"
#include "anope.h"
#include "service.h"
#include "modes.h"
/* Encapsulates the IRCd protocol we are speaking. */
class CoreExport IRCDProto : public Service
{
Anope::string proto_name;
protected:
IRCDProto(Module *creator, const Anope::string &proto_name);
public:
virtual ~IRCDProto();
virtual void SendSVSKillInternal(const MessageSource &, User *, const Anope::string &);
virtual void SendModeInternal(const MessageSource &, const Channel *, const Anope::string &);
virtual void SendModeInternal(const MessageSource &, User *, const Anope::string &);
virtual void SendKickInternal(const MessageSource &, const Channel *, User *, const Anope::string &);
virtual void SendNoticeInternal(const MessageSource &, const Anope::string &dest, const Anope::string &msg);
virtual void SendPrivmsgInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf);
virtual void SendQuitInternal(User *, const Anope::string &buf);
virtual void SendPartInternal(User *, const Channel *chan, const Anope::string &buf);
virtual void SendGlobopsInternal(const MessageSource &, const Anope::string &buf);
virtual void SendCTCPInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf);
virtual void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf);
const Anope::string &GetProtocolName();
virtual bool Parse(const Anope::string &, Anope::map<Anope::string> &, Anope::string &, Anope::string &, std::vector<Anope::string> &);
virtual Anope::string Format(const Anope::string &source, const Anope::string &message);
/* Modes used by default by our clients */
Anope::string DefaultPseudoclientModes;
/* Can we force change a users's nick? */
bool CanSVSNick;
/* Can we force join or part users? */
bool CanSVSJoin;
/* Can we set vhosts/vidents on users? */
bool CanSetVHost, CanSetVIdent;
/* Can we ban specific gecos from being used? */
bool CanSNLine;
/* Can we ban specific nicknames from being used? */
bool CanSQLine;
/* Can we ban specific channel names from being used? */
bool CanSQLineChannel;
/* Can we ban by IP? */
bool CanSZLine;
/* Can we place temporary holds on specific nicknames? */
bool CanSVSHold;
/* See os_oline */
bool CanSVSO;
/* See ns_cert */
bool CanCertFP;
/* Whether this IRCd requires unique IDs for each user or server. See TS6/P10. */
bool RequiresID;
/* If this IRCd has unique ids, whether the IDs and nicknames are ambiguous */
bool AmbiguousID;
/* The maximum number of modes we are allowed to set with one MODE command */
unsigned MaxModes;
/* The maximum number of bytes a line may have */
unsigned MaxLine;
/* Retrieves the next free UID or SID */
virtual Anope::string UID_Retrieve();
virtual Anope::string SID_Retrieve();
/** Sets the server in NOOP mode. If NOOP mode is enabled, no users
* will be able to oper on the server.
* @param s The server
* @param mode Whether to turn NOOP on or off
*/
virtual void SendSVSNOOP(const Server *s, bool mode) { }
/** Sets the topic on a channel
* @param bi The bot to set the topic from
* @param c The channel to set the topic on. The topic being set is Channel::topic
*/
virtual void SendTopic(const MessageSource &, Channel *);
/** Sets a vhost on a user.
* @param u The user
* @param vident The ident to set
* @param vhost The vhost to set
*/
virtual void SendVhost(User *u, const Anope::string &vident, const Anope::string &vhost) { }
virtual void SendVhostDel(User *) { }
/** Sets an akill. This is a recursive function that can be called multiple times
* for the same xline, but for different users, if the xline is not one that can be
* enforced by the IRCd, such as a nick/user/host/realname combination ban.
* @param u The user affected by the akill, if known
* @param x The akill
*/
virtual void SendAkill(User *, XLine *) = 0;
virtual void SendAkillDel(const XLine *) = 0;
/* Realname ban */
virtual void SendSGLine(User *, const XLine *) { }
virtual void SendSGLineDel(const XLine *) { }
/* IP ban */
virtual void SendSZLine(User *u, const XLine *) { }
virtual void SendSZLineDel(const XLine *) { }
/* Nick ban (and sometimes channel) */
virtual void SendSQLine(User *, const XLine *x) { }
virtual void SendSQLineDel(const XLine *x) { }
virtual void SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason);
/** Kills a user
* @param source Who is doing the kill
* @param user The user to be killed
* @param fmt Kill reason
*/
virtual void SendSVSKill(const MessageSource &source, User *user, const char *fmt, ...);
virtual void SendMode(const MessageSource &source, const Channel *dest, const char *fmt, ...);
virtual void SendMode(const MessageSource &source, User *u, const char *fmt, ...);
/** Introduces a client to the rest of the network
* @param u The client to introduce
*/
virtual void SendClientIntroduction(User *u) = 0;
virtual void SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt, ...);
virtual void SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
virtual void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
virtual void SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
virtual void SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...);
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 SendQuit(User *u, const char *fmt, ...);
virtual void SendPing(const Anope::string &servname, const Anope::string &who);
virtual void SendPong(const Anope::string &servname, const Anope::string &who);
/** Joins one of our users to a channel.
* @param u The user to join
* @param c The channel to join the user to
* @param status The status to set on the user after joining. This may or may not already internally
* be set on the user. This may include the modes in the join, but will usually place them on the mode
* stacker to be set "soon".
*/
virtual void SendJoin(User *u, Channel *c, const ChannelStatus *status) = 0;
virtual void SendPart(User *u, const Channel *chan, const char *fmt, ...);
/** Force joins a user that isn't ours to a channel.
* @param bi The source of the message
* @param u The user to join
* @param chan The channel to join the user to
* @param param Channel key?
*/
virtual void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) { }
/** Force parts a user that isn't ours from a channel.
* @param source The source of the message
* @param u The user to part
* @param chan The channel to part the user from
* @param param part reason, some IRCds don't support this
*/
virtual void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) { }
virtual void SendInvite(const MessageSource &source, const Channel *c, User *u);
virtual void SendGlobops(const MessageSource &source, const char *fmt, ...);
/** Sets oper flags on a user, currently only supported by Unreal
*/
virtual void SendSVSO(BotInfo *, const Anope::string &, const Anope::string &) { }
/** Sends a nick change of one of our clients.
*/
virtual void SendNickChange(User *u, const Anope::string &newnick);
/** Forces a nick change of a user that isn't ours (SVSNICK)
*/
virtual void SendForceNickChange(User *u, const Anope::string &newnick, time_t when);
/** Used to introduce ourselves to our uplink. Usually will SendServer(Me) and any other
* initial handshake requirements.
*/
virtual void SendConnect() = 0;
/** Called right before we begin our burst, after we have handshaked successfully with the uplink.
* At this point none of our servers, users, or channels exist on the uplink
*/
virtual void SendBOB() { }
virtual void SendEOB() { }
virtual void SendSVSHold(const Anope::string &, time_t) { }
virtual void SendSVSHoldDel(const Anope::string &) { }
virtual void SendSWhois(const MessageSource &, const Anope::string &, const Anope::string &) { }
/** Introduces a server to the uplink
*/
virtual void SendServer(const Server *) = 0;
virtual void SendSquit(Server *, const Anope::string &message);
virtual void SendNumeric(int numeric, const Anope::string &dest, const char *fmt, ...);
virtual void SendLogin(User *u, NickAlias *na) = 0;
virtual void SendLogout(User *u) = 0;
/** Send a channel creation message to the uplink.
* On most TS6 IRCds this is a SJOIN with no nick
*/
virtual void SendChannel(Channel *c) { }
/** Make the user an IRC operator
* Normally this is a simple +o, though some IRCds require us to send the oper type
*/
virtual void SendOper(User *u);
virtual void SendSASLMechanisms(std::vector<Anope::string> &) { }
virtual void SendSASLMessage(const SASL::Message &) { }
virtual void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) { }
virtual bool IsNickValid(const Anope::string &);
virtual bool IsChannelValid(const Anope::string &);
virtual bool IsIdentValid(const Anope::string &);
virtual bool IsHostValid(const Anope::string &);
virtual bool IsExtbanValid(const Anope::string &) { return false; }
/** Retrieve the maximum number of list modes settable on this channel
* Defaults to Config->ListSize
*/
virtual unsigned GetMaxListFor(Channel *c);
virtual unsigned GetMaxListFor(Channel *c, ChannelMode *cm);
virtual Anope::string NormalizeMask(const Anope::string &mask);
};
class CoreExport MessageSource
{
Anope::string source;
User *u;
Server *s;
public:
MessageSource(const Anope::string &);
MessageSource(User *u);
MessageSource(Server *s);
const Anope::string &GetName() const;
const Anope::string &GetSource() const;
User *GetUser() const;
BotInfo *GetBot() const;
Server *GetServer() const;
};
enum IRCDMessageFlag
{
IRCDMESSAGE_SOFT_LIMIT,
IRCDMESSAGE_REQUIRE_SERVER,
IRCDMESSAGE_REQUIRE_USER
};
class CoreExport IRCDMessage : public Service
{
Anope::string name;
unsigned param_count;
std::set<IRCDMessageFlag> flags;
public:
IRCDMessage(Module *owner, const Anope::string &n, unsigned p = 0);
unsigned GetParamCount() const;
virtual void Run(MessageSource &, const std::vector<Anope::string> &params) = 0;
virtual void Run(MessageSource &, const std::vector<Anope::string> &params, const Anope::map<Anope::string> &tags);
void SetFlag(IRCDMessageFlag f) { flags.insert(f); }
bool HasFlag(IRCDMessageFlag f) const { return flags.count(f); }
};
/** MessageTokenizer allows tokens in the IRC wire format to be read from a string */
class CoreExport MessageTokenizer
{
private:
/** The message we are parsing tokens from. */
Anope::string message;
/** The current position within the message. */
Anope::string::size_type position;
public:
/** Create a tokenstream and fill it with the provided data. */
MessageTokenizer(const Anope::string &msg);
/** Retrieve the next \<middle> token in the message.
* @param token The next token available, or an empty string if none remain.
* @return True if a token was retrieved; otherwise, false.
*/
bool GetMiddle(Anope::string &token);
/** Retrieve the next \<trailing> token in the message.
* @param token The next token available, or an empty string if none remain.
* @return True if a token was retrieved; otherwise, false.
*/
bool GetTrailing(Anope::string &token);
};
extern CoreExport IRCDProto *IRCD;
#endif // PROTOCOL_H

800
include/pstdint.h Normal file
View File

@ -0,0 +1,800 @@
/* A portable stdint.h
****************************************************************************
* BSD License:
****************************************************************************
*
* Copyright (c) 2005-2011 Paul Hsieh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************
*
* Version 0.1.12
*
* The ANSI C standard committee, for the C99 standard, specified the
* inclusion of a new standard include file called stdint.h. This is
* a very useful and long desired include file which contains several
* very precise definitions for integer scalar types that is
* critically important for making portable several classes of
* applications including cryptography, hashing, variable length
* integer libraries and so on. But for most developers its likely
* useful just for programming sanity.
*
* The problem is that most compiler vendors have decided not to
* implement the C99 standard, and the next C++ language standard
* (which has a lot more mindshare these days) will be a long time in
* coming and its unknown whether or not it will include stdint.h or
* how much adoption it will have. Either way, it will be a long time
* before all compilers come with a stdint.h and it also does nothing
* for the extremely large number of compilers available today which
* do not include this file, or anything comparable to it.
*
* So that's what this file is all about. Its an attempt to build a
* single universal include file that works on as many platforms as
* possible to deliver what stdint.h is supposed to. A few things
* that should be noted about this file:
*
* 1) It is not guaranteed to be portable and/or present an identical
* interface on all platforms. The extreme variability of the
* ANSI C standard makes this an impossibility right from the
* very get go. Its really only meant to be useful for the vast
* majority of platforms that possess the capability of
* implementing usefully and precisely defined, standard sized
* integer scalars. Systems which are not intrinsically 2s
* complement may produce invalid constants.
*
* 2) There is an unavoidable use of non-reserved symbols.
*
* 3) Other standard include files are invoked.
*
* 4) This file may come in conflict with future platforms that do
* include stdint.h. The hope is that one or the other can be
* used with no real difference.
*
* 5) In the current version, if your platform can't represent
* int32_t, int16_t and int8_t, it just dumps out with a compiler
* error.
*
* 6) 64 bit integers may or may not be defined. Test for their
* presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
* Note that this is different from the C99 specification which
* requires the existence of 64 bit support in the compiler. If
* this is not defined for your platform, yet it is capable of
* dealing with 64 bits then it is because this file has not yet
* been extended to cover all of your system's capabilities.
*
* 7) (u)intptr_t may or may not be defined. Test for its presence
* with the test: #ifdef PTRDIFF_MAX. If this is not defined
* for your platform, then it is because this file has not yet
* been extended to cover all of your system's capabilities, not
* because its optional.
*
* 8) The following might not been defined even if your platform is
* capable of defining it:
*
* WCHAR_MIN
* WCHAR_MAX
* (u)int64_t
* PTRDIFF_MIN
* PTRDIFF_MAX
* (u)intptr_t
*
* 9) The following have not been defined:
*
* WINT_MIN
* WINT_MAX
*
* 10) The criteria for defining (u)int_least(*)_t isn't clear,
* except for systems which don't have a type that precisely
* defined 8, 16, or 32 bit types (which this include file does
* not support anyways). Default definitions have been given.
*
* 11) The criteria for defining (u)int_fast(*)_t isn't something I
* would trust to any particular compiler vendor or the ANSI C
* committee. It is well known that "compatible systems" are
* commonly created that have very different performance
* characteristics from the systems they are compatible with,
* especially those whose vendors make both the compiler and the
* system. Default definitions have been given, but its strongly
* recommended that users never use these definitions for any
* reason (they do *NOT* deliver any serious guarantee of
* improved performance -- not in this file, nor any vendor's
* stdint.h).
*
* 12) The following macros:
*
* PRINTF_INTMAX_MODIFIER
* PRINTF_INT64_MODIFIER
* PRINTF_INT32_MODIFIER
* PRINTF_INT16_MODIFIER
* PRINTF_LEAST64_MODIFIER
* PRINTF_LEAST32_MODIFIER
* PRINTF_LEAST16_MODIFIER
* PRINTF_INTPTR_MODIFIER
*
* are strings which have been defined as the modifiers required
* for the "d", "u" and "x" printf formats to correctly output
* (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
* (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
* PRINTF_INTPTR_MODIFIER is not defined for some systems which
* provide their own stdint.h. PRINTF_INT64_MODIFIER is not
* defined if INT64_MAX is not defined. These are an extension
* beyond what C99 specifies must be in stdint.h.
*
* In addition, the following macros are defined:
*
* PRINTF_INTMAX_HEX_WIDTH
* PRINTF_INT64_HEX_WIDTH
* PRINTF_INT32_HEX_WIDTH
* PRINTF_INT16_HEX_WIDTH
* PRINTF_INT8_HEX_WIDTH
* PRINTF_INTMAX_DEC_WIDTH
* PRINTF_INT64_DEC_WIDTH
* PRINTF_INT32_DEC_WIDTH
* PRINTF_INT16_DEC_WIDTH
* PRINTF_INT8_DEC_WIDTH
*
* Which specifies the maximum number of characters required to
* print the number of that type in either hexadecimal or decimal.
* These are an extension beyond what C99 specifies must be in
* stdint.h.
*
* Compilers tested (all with 0 warnings at their highest respective
* settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
* bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
* .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
*
* This file should be considered a work in progress. Suggestions for
* improvements, especially those which increase coverage are strongly
* encouraged.
*
* Acknowledgements
*
* The following people have made significant contributions to the
* development and testing of this file:
*
* Chris Howie
* John Steele Scott
* Dave Thorup
* John Dill
*
*/
#include <stddef.h>
#include <limits.h>
#include <signal.h>
/*
* For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
* do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
*/
#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
#include <stdint.h>
#define _PSTDINT_H_INCLUDED
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
# endif
# ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
# endif
# ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
# endif
# ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
# endif
# ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "20"
# endif
# ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
# endif
# ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
# endif
# ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
/*
* Something really weird is going on with Open Watcom. Just pull some of
* these duplicated definitions from Open Watcom's stdint.h file for now.
*/
# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
# if !defined (INT64_C)
# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
# endif
# if !defined (UINT64_C)
# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
# endif
# if !defined (INT32_C)
# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
# endif
# if !defined (UINT32_C)
# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
# endif
# if !defined (INT16_C)
# define INT16_C(x) (x)
# endif
# if !defined (UINT16_C)
# define UINT16_C(x) (x)
# endif
# if !defined (INT8_C)
# define INT8_C(x) (x)
# endif
# if !defined (UINT8_C)
# define UINT8_C(x) (x)
# endif
# if !defined (UINT64_MAX)
# define UINT64_MAX 18446744073709551615ULL
# endif
# if !defined (INT64_MAX)
# define INT64_MAX 9223372036854775807LL
# endif
# if !defined (UINT32_MAX)
# define UINT32_MAX 4294967295UL
# endif
# if !defined (INT32_MAX)
# define INT32_MAX 2147483647L
# endif
# if !defined (INTMAX_MAX)
# define INTMAX_MAX INT64_MAX
# endif
# if !defined (INTMAX_MIN)
# define INTMAX_MIN INT64_MIN
# endif
# endif
#endif
#ifndef _PSTDINT_H_INCLUDED
#define _PSTDINT_H_INCLUDED
#ifndef SIZE_MAX
# define SIZE_MAX (~(size_t)0)
#endif
/*
* Deduce the type assignments from limits.h under the assumption that
* integer sizes in bits are powers of 2, and follow the ANSI
* definitions.
*/
#ifndef UINT8_MAX
# define UINT8_MAX 0xff
#endif
#ifndef uint8_t
# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
typedef unsigned char uint8_t;
# define UINT8_C(v) ((uint8_t) v)
# else
# error "Platform not supported"
# endif
#endif
#ifndef INT8_MAX
# define INT8_MAX 0x7f
#endif
#ifndef INT8_MIN
# define INT8_MIN INT8_C(0x80)
#endif
#ifndef int8_t
# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
typedef signed char int8_t;
# define INT8_C(v) ((int8_t) v)
# else
# error "Platform not supported"
# endif
#endif
#ifndef UINT16_MAX
# define UINT16_MAX 0xffff
#endif
#ifndef uint16_t
#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
typedef unsigned int uint16_t;
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER ""
# endif
# define UINT16_C(v) ((uint16_t) (v))
#elif (USHRT_MAX == UINT16_MAX)
typedef unsigned short uint16_t;
# define UINT16_C(v) ((uint16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef INT16_MAX
# define INT16_MAX 0x7fff
#endif
#ifndef INT16_MIN
# define INT16_MIN INT16_C(0x8000)
#endif
#ifndef int16_t
#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
typedef signed int int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER ""
# endif
#elif (SHRT_MAX == INT16_MAX)
typedef signed short int16_t;
# define INT16_C(v) ((int16_t) (v))
# ifndef PRINTF_INT16_MODIFIER
# define PRINTF_INT16_MODIFIER "h"
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef UINT32_MAX
# define UINT32_MAX (0xffffffffUL)
#endif
#ifndef uint32_t
#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
typedef unsigned long uint32_t;
# define UINT32_C(v) v ## UL
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
#elif (UINT_MAX == UINT32_MAX)
typedef unsigned int uint32_t;
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
# define UINT32_C(v) v ## U
#elif (USHRT_MAX == UINT32_MAX)
typedef unsigned short uint32_t;
# define UINT32_C(v) ((unsigned short) (v))
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif
#ifndef INT32_MAX
# define INT32_MAX (0x7fffffffL)
#endif
#ifndef INT32_MIN
# define INT32_MIN INT32_C(0x80000000)
#endif
#ifndef int32_t
#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
typedef signed long int32_t;
# define INT32_C(v) v ## L
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER "l"
# endif
#elif (INT_MAX == INT32_MAX)
typedef signed int int32_t;
# define INT32_C(v) v
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#elif (SHRT_MAX == INT32_MAX)
typedef signed short int32_t;
# define INT32_C(v) ((short) (v))
# ifndef PRINTF_INT32_MODIFIER
# define PRINTF_INT32_MODIFIER ""
# endif
#else
#error "Platform not supported"
#endif
#endif
/*
* The macro stdint_int64_defined is temporarily used to record
* whether or not 64 integer support is available. It must be
* defined for any 64 integer extensions for new platforms that are
* added.
*/
#undef stdint_int64_defined
#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S)
# define stdint_int64_defined
typedef long long int64_t;
typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# endif
#endif
#if !defined (stdint_int64_defined)
# if defined(__GNUC__)
# define stdint_int64_defined
__extension__ typedef long long int64_t;
__extension__ typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
# define stdint_int64_defined
typedef long long int64_t;
typedef unsigned long long uint64_t;
# define UINT64_C(v) v ## ULL
# define INT64_C(v) v ## LL
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "ll"
# endif
# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
# define stdint_int64_defined
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
# define UINT64_C(v) v ## UI64
# define INT64_C(v) v ## I64
# ifndef PRINTF_INT64_MODIFIER
# define PRINTF_INT64_MODIFIER "I64"
# endif
# endif
#endif
#if !defined (LONG_LONG_MAX) && defined (INT64_C)
# define LONG_LONG_MAX INT64_C (9223372036854775807)
#endif
#ifndef ULONG_LONG_MAX
# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
#endif
#if !defined (INT64_MAX) && defined (INT64_C)
# define INT64_MAX INT64_C (9223372036854775807)
#endif
#if !defined (INT64_MIN) && defined (INT64_C)
# define INT64_MIN INT64_C (-9223372036854775808)
#endif
#if !defined (UINT64_MAX) && defined (INT64_C)
# define UINT64_MAX UINT64_C (18446744073709551615)
#endif
/*
* Width of hexadecimal for number field.
*/
#ifndef PRINTF_INT64_HEX_WIDTH
# define PRINTF_INT64_HEX_WIDTH "16"
#endif
#ifndef PRINTF_INT32_HEX_WIDTH
# define PRINTF_INT32_HEX_WIDTH "8"
#endif
#ifndef PRINTF_INT16_HEX_WIDTH
# define PRINTF_INT16_HEX_WIDTH "4"
#endif
#ifndef PRINTF_INT8_HEX_WIDTH
# define PRINTF_INT8_HEX_WIDTH "2"
#endif
#ifndef PRINTF_INT64_DEC_WIDTH
# define PRINTF_INT64_DEC_WIDTH "20"
#endif
#ifndef PRINTF_INT32_DEC_WIDTH
# define PRINTF_INT32_DEC_WIDTH "10"
#endif
#ifndef PRINTF_INT16_DEC_WIDTH
# define PRINTF_INT16_DEC_WIDTH "5"
#endif
#ifndef PRINTF_INT8_DEC_WIDTH
# define PRINTF_INT8_DEC_WIDTH "3"
#endif
/*
* Ok, lets not worry about 128 bit integers for now. Moore's law says
* we don't need to worry about that until about 2040 at which point
* we'll have bigger things to worry about.
*/
#ifdef stdint_int64_defined
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
# define INTMAX_MAX INT64_MAX
# define INTMAX_MIN INT64_MIN
# define UINTMAX_MAX UINT64_MAX
# define UINTMAX_C(v) UINT64_C(v)
# define INTMAX_C(v) INT64_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
# endif
#else
typedef int32_t intmax_t;
typedef uint32_t uintmax_t;
# define INTMAX_MAX INT32_MAX
# define UINTMAX_MAX UINT32_MAX
# define UINTMAX_C(v) UINT32_C(v)
# define INTMAX_C(v) INT32_C(v)
# ifndef PRINTF_INTMAX_MODIFIER
# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
# endif
# ifndef PRINTF_INTMAX_HEX_WIDTH
# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
# endif
# ifndef PRINTF_INTMAX_DEC_WIDTH
# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
# endif
#endif
/*
* Because this file currently only supports platforms which have
* precise powers of 2 as bit sizes for the default integers, the
* least definitions are all trivial. Its possible that a future
* version of this file could have different definitions.
*/
#ifndef stdint_least_defined
typedef int8_t int_least8_t;
typedef uint8_t uint_least8_t;
typedef int16_t int_least16_t;
typedef uint16_t uint_least16_t;
typedef int32_t int_least32_t;
typedef uint32_t uint_least32_t;
# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
# define UINT_LEAST8_MAX UINT8_MAX
# define INT_LEAST8_MAX INT8_MAX
# define UINT_LEAST16_MAX UINT16_MAX
# define INT_LEAST16_MAX INT16_MAX
# define UINT_LEAST32_MAX UINT32_MAX
# define INT_LEAST32_MAX INT32_MAX
# define INT_LEAST8_MIN INT8_MIN
# define INT_LEAST16_MIN INT16_MIN
# define INT_LEAST32_MIN INT32_MIN
# ifdef stdint_int64_defined
typedef int64_t int_least64_t;
typedef uint64_t uint_least64_t;
# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
# define UINT_LEAST64_MAX UINT64_MAX
# define INT_LEAST64_MAX INT64_MAX
# define INT_LEAST64_MIN INT64_MIN
# endif
#endif
#undef stdint_least_defined
/*
* The ANSI C committee pretending to know or specify anything about
* performance is the epitome of misguided arrogance. The mandate of
* this file is to *ONLY* ever support that absolute minimum
* definition of the fast integer types, for compatibility purposes.
* No extensions, and no attempt to suggest what may or may not be a
* faster integer type will ever be made in this file. Developers are
* warned to stay away from these types when using this or any other
* stdint.h.
*/
typedef int_least8_t int_fast8_t;
typedef uint_least8_t uint_fast8_t;
typedef int_least16_t int_fast16_t;
typedef uint_least16_t uint_fast16_t;
typedef int_least32_t int_fast32_t;
typedef uint_least32_t uint_fast32_t;
#define UINT_FAST8_MAX UINT_LEAST8_MAX
#define INT_FAST8_MAX INT_LEAST8_MAX
#define UINT_FAST16_MAX UINT_LEAST16_MAX
#define INT_FAST16_MAX INT_LEAST16_MAX
#define UINT_FAST32_MAX UINT_LEAST32_MAX
#define INT_FAST32_MAX INT_LEAST32_MAX
#define INT_FAST8_MIN INT_LEAST8_MIN
#define INT_FAST16_MIN INT_LEAST16_MIN
#define INT_FAST32_MIN INT_LEAST32_MIN
#ifdef stdint_int64_defined
typedef int_least64_t int_fast64_t;
typedef uint_least64_t uint_fast64_t;
# define UINT_FAST64_MAX UINT_LEAST64_MAX
# define INT_FAST64_MAX INT_LEAST64_MAX
# define INT_FAST64_MIN INT_LEAST64_MIN
#endif
#undef stdint_int64_defined
/*
* Whatever piecemeal, per compiler thing we can do about the wchar_t
* type limits.
*/
#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
# include <wchar.h>
# ifndef WCHAR_MIN
# define WCHAR_MIN 0
# endif
# ifndef WCHAR_MAX
# define WCHAR_MAX ((wchar_t)-1)
# endif
#endif
/*
* Whatever piecemeal, per compiler/platform thing we can do about the
* (u)intptr_t types and limits.
*/
#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
# define STDINT_H_UINTPTR_T_DEFINED
#endif
#ifndef STDINT_H_UINTPTR_T_DEFINED
# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
# define stdint_intptr_bits 64
# elif defined (__WATCOMC__) || defined (__TURBOC__)
# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
# define stdint_intptr_bits 16
# else
# define stdint_intptr_bits 32
# endif
# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
# define stdint_intptr_bits 32
# elif defined (__INTEL_COMPILER)
/* TODO -- what did Intel do about x86-64? */
# endif
# ifdef stdint_intptr_bits
# define stdint_intptr_glue3_i(a,b,c) a##b##c
# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
# ifndef PRINTF_INTPTR_MODIFIER
# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
# endif
# ifndef PTRDIFF_MAX
# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
# endif
# ifndef PTRDIFF_MIN
# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
# endif
# ifndef UINTPTR_MAX
# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
# endif
# ifndef INTPTR_MAX
# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
# endif
# ifndef INTPTR_MIN
# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
# endif
# ifndef INTPTR_C
# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
# endif
# ifndef UINTPTR_C
# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
# endif
typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
# else
/* TODO -- This following is likely wrong for some platforms, and does
nothing for the definition of uintptr_t. */
typedef ptrdiff_t intptr_t;
# endif
# define STDINT_H_UINTPTR_T_DEFINED
#endif
/*
* Assumes sig_atomic_t is signed and we have a 2s complement machine.
*/
#ifndef SIG_ATOMIC_MAX
# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
#endif
#endif
#if defined (__TEST_PSTDINT_FOR_CORRECTNESS)
/*
* Please compile with the maximum warning settings to make sure macros are not
* defined more than once.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define glue3_aux(x,y,z) x ## y ## z
#define glue3(x,y,z) glue3_aux(x,y,z)
#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0);
#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0);
#define DECL(us,bits) glue3(DECL,us,) (bits)
#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits)
int main () {
DECL(I,8)
DECL(U,8)
DECL(I,16)
DECL(U,16)
DECL(I,32)
DECL(U,32)
#ifdef INT64_MAX
DECL(I,64)
DECL(U,64)
#endif
intmax_t imax = INTMAX_C(0);
uintmax_t umax = UINTMAX_C(0);
char str0[256], str1[256];
sprintf (str0, "%d %x\n", 0, ~0);
sprintf (str1, "%d %x\n", i8, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1);
sprintf (str1, "%u %x\n", u8, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1);
sprintf (str1, "%d %x\n", i16, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1);
sprintf (str1, "%u %x\n", u16, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1);
sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1);
sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1);
#ifdef INT64_MAX
sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1);
#endif
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1);
sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0);
if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1);
TESTUMAX(8);
TESTUMAX(16);
TESTUMAX(32);
#ifdef INT64_MAX
TESTUMAX(64);
#endif
return EXIT_SUCCESS;
}
#endif

252
include/regchannel.h Normal file
View File

@ -0,0 +1,252 @@
/*
*
* (C) 2008-2022 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#ifndef REGCHANNEL_H
#define REGCHANNEL_H
#include "memo.h"
#include "modes.h"
#include "extensible.h"
#include "logger.h"
#include "modules.h"
#include "serialize.h"
#include "bots.h"
typedef Anope::hash_map<ChannelInfo *> registered_channel_map;
extern CoreExport Serialize::Checker<registered_channel_map> RegisteredChannelList;
/* AutoKick data. */
class CoreExport AutoKick : public Serializable
{
public:
/* Channel this autokick is on */
Serialize::Reference<ChannelInfo> ci;
Anope::string mask;
Serialize::Reference<NickCore> nc;
Anope::string reason;
Anope::string creator;
time_t addtime;
time_t last_used;
AutoKick();
~AutoKick();
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
};
/* It matters that Base is here before Extensible (it is inherited by Serializable)
*/
class CoreExport ChannelInfo : public Serializable, public Extensible
{
/* channels who reference this one */
Anope::map<int> references;
private:
Serialize::Reference<NickCore> founder; /* Channel founder */
Serialize::Reference<NickCore> successor; /* Who gets the channel if the founder nick is dropped or expires */
Serialize::Checker<std::vector<ChanAccess *> > access; /* List of authorized users */
Serialize::Checker<std::vector<AutoKick *> > akick; /* List of users to kickban */
Anope::map<int16_t> levels;
public:
friend class ChanAccess;
friend class AutoKick;
Anope::string name; /* Channel name */
Anope::string desc;
time_t time_registered;
time_t last_used;
Anope::string last_topic; /* The last topic that was set on this channel */
Anope::string last_topic_setter; /* Setter */
time_t last_topic_time; /* Time */
Channel::ModeList last_modes; /* The last modes set on this channel */
int16_t bantype;
MemoInfo memos;
Channel *c; /* Pointer to channel, if the channel exists */
/* For BotServ */
Serialize::Reference<BotInfo> bi; /* Bot used on this channel */
time_t banexpire; /* Time bans expire in */
/** Constructor
* @param chname The channel name
*/
ChannelInfo(const Anope::string &chname);
/** Copy constructor
* @param ci The ChannelInfo to copy settings from
*/
ChannelInfo(const ChannelInfo &ci);
~ChannelInfo();
void Serialize(Serialize::Data &data) const anope_override;
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
/** Change the founder of the channel
* @params nc The new founder
*/
void SetFounder(NickCore *nc);
/** Get the founder of the channel
* @return The founder
*/
NickCore *GetFounder() const;
void SetSuccessor(NickCore *nc);
NickCore *GetSuccessor() const;
/** Find which bot should send mode/topic/etc changes for this channel
* @return The bot
*/
BotInfo *WhoSends() const;
/** Add an entry to the channel access list
* @param access The entry
*/
void AddAccess(ChanAccess *access);
/** Get an entry from the channel access list by index
*
* @param index The index in the access list vector
* @return A ChanAccess struct corresponding to the index given, or NULL if outside the bounds
*
* Retrieves an entry from the access list that matches the given index.
*/
ChanAccess *GetAccess(unsigned index) const;
/** Retrieve the access for a user or group in the form of a vector of access entries
* (as multiple entries can affect a single user).
*/
AccessGroup AccessFor(const User *u, bool updateLastUsed = true);
AccessGroup AccessFor(const NickCore *nc, bool updateLastUsed = true);
/** Get the size of the access vector for this channel
* @return The access vector size
*/
unsigned GetAccessCount() const;
/** Get the number of access entries for this channel,
* including those that are on other channels.
*/
unsigned GetDeepAccessCount() const;
/** Erase an entry from the channel access list
*
* @param index The index in the access list vector
*
* @return The erased entry
*/
ChanAccess *EraseAccess(unsigned index);
/** Clear the entire channel access list
*
* Clears the entire access list by deleting every item and then clearing the vector.
*/
void ClearAccess();
/** Add an akick entry to the channel by NickCore
* @param user The user who added the akick
* @param akicknc The nickcore being akicked
* @param reason The reason for the akick
* @param t The time the akick was added, defaults to now
* @param lu The time the akick was last used, defaults to never
*/
AutoKick* AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0);
/** Add an akick entry to the channel by reason
* @param user The user who added the akick
* @param mask The mask of the akick
* @param reason The reason for the akick
* @param t The time the akick was added, defaults to now
* @param lu The time the akick was last used, defaults to never
*/
AutoKick* AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0);
/** Get an entry from the channel akick list
* @param index The index in the akick vector
* @return The akick structure, or NULL if not found
*/
AutoKick* GetAkick(unsigned index) const;
/** Get the size of the akick vector for this channel
* @return The akick vector size
*/
unsigned GetAkickCount() const;
/** Erase an entry from the channel akick list
* @param index The index of the akick
*/
void EraseAkick(unsigned index);
/** Clear the whole akick list
*/
void ClearAkick();
/** Get the level entries for the channel.
* @return The levels for the channel.
*/
const Anope::map<int16_t> &GetLevelEntries();
/** Get the level for a privilege
* @param priv The privilege name
* @return the level
* @throws CoreException if priv is not a valid privilege
*/
int16_t GetLevel(const Anope::string &priv) const;
/** Set the level for a privilege
* @param priv The privilege priv
* @param level The new level
*/
void SetLevel(const Anope::string &priv, int16_t level);
/** Remove a privilege from the channel
* @param priv The privilege
*/
void RemoveLevel(const Anope::string &priv);
/** Clear all privileges from the channel
*/
void ClearLevels();
/** Gets a ban mask for the given user based on the bantype
* of the channel.
* @param u The user
* @return A ban mask that affects the user
*/
Anope::string GetIdealBan(User *u) const;
/** Finds a ChannelInfo
* @param name channel name to lookup
* @return the ChannelInfo associated with the channel
*/
static ChannelInfo* Find(const Anope::string &name);
void AddChannelReference(const Anope::string &what);
void RemoveChannelReference(const Anope::string &what);
void GetChannelReferences(std::deque<Anope::string> &chans);
};
/** Is the user the real founder?
* @param user The user
* @param ci The channel
* @return true or false
*/
extern CoreExport bool IsFounder(const User *user, const ChannelInfo *ci);
#endif // REGCHANNEL_H

45
include/regexpr.h Normal file
View File

@ -0,0 +1,45 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef REGEXPR_H
#define REGEXPR_H
#include "services.h"
#include "anope.h"
#include "service.h"
class RegexException : public CoreException
{
public:
RegexException(const Anope::string &reason = "") : CoreException(reason) { }
virtual ~RegexException() throw() { }
};
class CoreExport Regex
{
Anope::string expression;
protected:
Regex(const Anope::string &expr) : expression(expr) { }
public:
virtual ~Regex() { }
const Anope::string &GetExpression() { return expression; }
virtual bool Matches(const Anope::string &str) = 0;
};
class CoreExport RegexProvider : public Service
{
public:
RegexProvider(Module *o, const Anope::string &n) : Service(o, "Regex", n) { }
virtual Regex *Compile(const Anope::string &) = 0;
};
#endif // REGEXPR_H

335
include/serialize.h Normal file
View File

@ -0,0 +1,335 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef SERIALIZE_H
#define SERIALIZE_H
#include <sstream>
#include "anope.h"
#include "base.h"
namespace Serialize
{
class Data
{
public:
enum Type
{
DT_TEXT,
DT_INT
};
virtual ~Data() { }
virtual std::iostream& operator[](const Anope::string &key) = 0;
virtual std::set<Anope::string> KeySet() const { throw CoreException("Not supported"); }
virtual size_t Hash() const { throw CoreException("Not supported"); }
virtual void SetType(const Anope::string &key, Type t) { }
virtual Type GetType(const Anope::string &key) const { return DT_TEXT; }
};
extern void RegisterTypes();
extern void CheckTypes();
class Type;
template<typename T> class Checker;
template<typename T> class Reference;
}
/** A serializable object. Serializable objects can be serialized into
* abstract data types (Serialize::Data), and then reconstructed or
* updated later at any time.
*/
class CoreExport Serializable : public virtual Base
{
private:
/* A list of every serializable item in Anope.
* Some of these are static and constructed at runtime,
* so this list must be on the heap, as it is not always
* constructed before other objects are if it isn't.
*/
static std::list<Serializable *> *SerializableItems;
friend class Serialize::Type;
/* The type of item this object is */
Serialize::Type *s_type;
/* Iterator into serializable_items */
std::list<Serializable *>::iterator s_iter;
/* The hash of the last serialized form of this object committed to the database */
size_t last_commit;
/* The last time this object was committed to the database */
time_t last_commit_time;
protected:
Serializable(const Anope::string &serialize_type);
Serializable(const Serializable &);
Serializable &operator=(const Serializable &);
public:
virtual ~Serializable();
/* Unique ID (per type, not globally) for this object */
uint64_t id;
/* Only used by redis, to ignore updates */
unsigned short redis_ignore;
/** Marks the object as potentially being updated "soon".
*/
void QueueUpdate();
bool IsCached(Serialize::Data &);
void UpdateCache(Serialize::Data &);
bool IsTSCached();
void UpdateTS();
/** Get the type of serializable object this is
* @return The serializable object type
*/
Serialize::Type* GetSerializableType() const { return this->s_type; }
virtual void Serialize(Serialize::Data &data) const = 0;
static const std::list<Serializable *> &GetItems();
};
/* A serializable type. There should be one of these classes for each type
* of class that inherits from Serializable. Used for unserializing objects
* of this type, as it requires a function pointer to a static member function.
*/
class CoreExport Serialize::Type : public Base
{
typedef Serializable* (*unserialize_func)(Serializable *obj, Serialize::Data &);
static std::vector<Anope::string> TypeOrder;
static std::map<Anope::string, Serialize::Type *> Types;
/* The name of this type, should be a class name */
Anope::string name;
unserialize_func unserialize;
/* Owner of this type. Used for placing objects of this type in separate databases
* based on what module, if any, owns it.
*/
Module *owner;
/* The timestamp for this type. All objects of this type are as up to date as
* this timestamp. if curtime == timestamp then we have the most up to date
* version of every object of this type.
*/
time_t timestamp;
public:
/* Map of Serializable::id to Serializable objects */
std::map<uint64_t, Serializable *> objects;
/** Creates a new serializable type
* @param n Type name
* @param f Func to unserialize objects
* @param owner Owner of this type. Leave NULL for the core.
*/
Type(const Anope::string &n, unserialize_func f, Module *owner = NULL);
~Type();
/** Gets the name for this type
* @return The name, eg "NickAlias"
*/
const Anope::string &GetName() { return this->name; }
/** Unserialized an object.
* @param obj NULL if this object doesn't yet exist. If this isn't NULL, instead
* update the contents of this object.
* @param data The data to unserialize
* @return The unserialized object. If obj != NULL this should be obj.
*/
Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
/** Check if this object type has any pending changes and update them.
*/
void Check();
/** Gets the timestamp for the object type. That is, the time we know
* all objects of this type are updated at least to.
*/
time_t GetTimestamp() const;
/** Bumps object type timestamp to current time
*/
void UpdateTimestamp();
Module* GetOwner() const { return this->owner; }
static Serialize::Type *Find(const Anope::string &name);
static const std::vector<Anope::string> &GetTypeOrder();
static const std::map<Anope::string, Serialize::Type *>& GetTypes();
};
/** Should be used to hold lists and other objects of a specific type,
* but not a specific object. Used for ensuring that any access to
* this object type is always up to date. These are usually constructed
* at run time, before main is called, so no types are registered. This
* is why there are static Serialize::Type* variables in every function.
*/
template<typename T>
class Serialize::Checker
{
Anope::string name;
T obj;
mutable ::Reference<Serialize::Type> type;
inline void Check() const
{
if (!type)
type = Serialize::Type::Find(this->name);
if (type)
type->Check();
}
public:
Checker(const Anope::string &n) : name(n), type(NULL) { }
inline const T* operator->() const
{
this->Check();
return &this->obj;
}
inline T* operator->()
{
this->Check();
return &this->obj;
}
inline const T& operator*() const
{
this->Check();
return this->obj;
}
inline T& operator*()
{
this->Check();
return this->obj;
}
inline operator const T&() const
{
this->Check();
return this->obj;
}
inline operator T&()
{
this->Check();
return this->obj;
}
};
/** Used to hold references to serializable objects. Reference should always be
* used when holding references to serializable objects for extended periods of time
* to ensure that the object it refers to it always up to date. This also behaves like
* Reference in that it will invalidate itself if the object it refers to is
* destructed.
*/
template<typename T>
class Serialize::Reference : public ReferenceBase
{
protected:
T *ref;
public:
Reference() : ref(NULL)
{
}
Reference(T *obj) : ref(obj)
{
if (obj)
obj->AddReference(this);
}
Reference(const Reference<T> &other) : ReferenceBase(other), ref(other.ref)
{
if (ref && !invalid)
this->ref->AddReference(this);
}
~Reference()
{
if (ref && !invalid)
this->ref->DelReference(this);
}
inline Reference<T>& operator=(const Reference<T> &other)
{
if (this != &other)
{
if (ref && !invalid)
this->ref->DelReference(this);
this->ref = other.ref;
this->invalid = other.invalid;
if (ref && !invalid)
this->ref->AddReference(this);
}
return *this;
}
inline operator bool() const
{
if (!this->invalid)
return this->ref != NULL;
return false;
}
inline operator T*() const
{
if (!this->invalid)
{
if (this->ref)
// This can invalidate me
this->ref->QueueUpdate();
if (!this->invalid)
return this->ref;
}
return NULL;
}
inline T* operator*() const
{
if (!this->invalid)
{
if (this->ref)
// This can invalidate me
this->ref->QueueUpdate();
if (!this->invalid)
return this->ref;
}
return NULL;
}
inline T* operator->() const
{
if (!this->invalid)
{
if (this->ref)
// This can invalidate me
this->ref->QueueUpdate();
if (!this->invalid)
return this->ref;
}
return NULL;
}
};
#endif // SERIALIZE_H

187
include/servers.h Normal file
View File

@ -0,0 +1,187 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef SERVERS_H
#define SERVERS_H
#include "services.h"
#include "anope.h"
#include "extensible.h"
/* Anope. We are at the top of the server tree, our uplink is
* almost always me->GetLinks()[0]. We never have an uplink. */
extern CoreExport Server *Me;
namespace Servers
{
/* Gets our uplink. Note we don't actually have an "uplink", this is just
* the only server whose uplink *is* Me that is not a juped server.
* @return Our uplink, or NULL if not uplinked to anything
*/
extern CoreExport Server* GetUplink();
/* Server maps by name and id */
extern CoreExport Anope::map<Server *> ByName;
extern CoreExport Anope::map<Server *> ByID;
/* CAPAB/PROTOCTL given by the uplink */
extern CoreExport std::set<Anope::string> Capab;
}
/** Class representing a server
*/
class CoreExport Server : public Extensible
{
private:
/* Server name */
Anope::string name;
/* Hops between services and server */
unsigned int hops;
/* Server description */
Anope::string description;
/* Server ID */
Anope::string sid;
/* Links for this server */
std::vector<Server *> links;
/* Uplink for this server */
Server *uplink;
/* Server is syncing */
bool syncing;
/* The server is juped */
bool juped;
/* The server is about to quit */
bool quitting;
/* Reason this server was quit */
Anope::string quit_reason;
public:
/** Constructor
* @param uplink The uplink this server is from, is only NULL when creating Me
* @param name The server name
* @param hops Hops from services server
* @param description Server rdescription
* @param sid Server sid/numeric
* @param jupe If the server is juped
*/
Server(Server *uplink, const Anope::string &name, unsigned hops, const Anope::string &description, const Anope::string &sid = "", bool jupe = false);
private:
/** Destructor
*/
~Server();
public:
/* Number of users on the server */
unsigned users;
/** Delete this server with a reason
* @param reason The reason
*/
void Delete(const Anope::string &reason);
/** Get the name for this server
* @return The name
*/
const Anope::string &GetName() const;
/** Get the number of hops this server is from services
* @return Number of hops
*/
unsigned GetHops() const;
/** Set the server description
* @param desc The new description
*/
void SetDescription(const Anope::string &desc);
/** Get the server description
* @return The server description
*/
const Anope::string &GetDescription() const;
/** Change this servers SID
* @param sid The new SID
*/
void SetSID(const Anope::string &sid);
/** Get the server numeric/SID, else the server name
* @return The numeric/SID
*/
const Anope::string &GetSID() const;
/** Retrieves the reason this server is quitting
*/
const Anope::string &GetQuitReason() const;
/** Get the list of links this server has, or NULL if it has none
* @return A list of servers
*/
const std::vector<Server *> &GetLinks() const;
/** Get the uplink server for this server, if this is our uplink will be Me
* @return The servers uplink
*/
Server *GetUplink();
/** Adds a link to this server
* @param s The linking server
*/
void AddLink(Server *s);
/** Delinks a server from this server
* @param s The server
*/
void DelLink(Server *s);
/** Finish syncing this server and optionally all links to it
* @param sync_links True to sync the links for this server too (if any)
*/
void Sync(bool sync_links);
/** Check if this server is synced
* @return true or false
*/
bool IsSynced() const;
/** Unsync the server. Only used for Me->Unsync()
*/
void Unsync();
/** Check if this server is ULined
* @return true or false
*/
bool IsULined() const;
/** Check if this server is juped (a pseudoserver other than us)
* @return true if this server is a juped server
*/
bool IsJuped() const;
/** Check if the server is quitting
* @return true if this server is quitting.
*/
bool IsQuitting() const;
/** Send a message to all users on this server
* @param source The source of the message
* @param message The message
*/
void Notice(BotInfo *source, const Anope::string &message);
/** Find a server
* @param name The name or SID/numeric
* @param name_only set to true to only look up by name, not SID
* @return The server
*/
static Server *Find(const Anope::string &name, bool name_only = false);
};
#endif // SERVERS_H

173
include/service.h Normal file
View File

@ -0,0 +1,173 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef SERVICE_H
#define SERVICE_H
#include "services.h"
#include "anope.h"
#include "base.h"
/** Anything that inherits from this class can be referred to
* using ServiceReference. Any interfaces provided by modules,
* such as commands, use this. This is also used for modules
* that publish a service (m_ssl_openssl, etc).
*/
class CoreExport Service : public virtual Base
{
static std::map<Anope::string, std::map<Anope::string, Service *> > Services;
static std::map<Anope::string, std::map<Anope::string, Anope::string> > Aliases;
static Service *FindService(const std::map<Anope::string, Service *> &services, const std::map<Anope::string, Anope::string> *aliases, const Anope::string &n)
{
std::map<Anope::string, Service *>::const_iterator it = services.find(n);
if (it != services.end())
return it->second;
if (aliases != NULL)
{
std::map<Anope::string, Anope::string>::const_iterator it2 = aliases->find(n);
if (it2 != aliases->end())
return FindService(services, aliases, it2->second);
}
return NULL;
}
public:
static Service *FindService(const Anope::string &t, const Anope::string &n)
{
std::map<Anope::string, std::map<Anope::string, Service *> >::const_iterator it = Services.find(t);
if (it == Services.end())
return NULL;
std::map<Anope::string, std::map<Anope::string, Anope::string> >::const_iterator it2 = Aliases.find(t);
if (it2 != Aliases.end())
return FindService(it->second, &it2->second, n);
return FindService(it->second, NULL, n);
}
static std::vector<Anope::string> GetServiceKeys(const Anope::string &t)
{
std::vector<Anope::string> keys;
std::map<Anope::string, std::map<Anope::string, Service *> >::iterator it = Services.find(t);
if (it != Services.end())
for (std::map<Anope::string, Service *>::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2)
keys.push_back(it2->first);
return keys;
}
static void AddAlias(const Anope::string &t, const Anope::string &n, const Anope::string &v)
{
std::map<Anope::string, Anope::string> &smap = Aliases[t];
smap[n] = v;
}
static void DelAlias(const Anope::string &t, const Anope::string &n)
{
std::map<Anope::string, Anope::string> &smap = Aliases[t];
smap.erase(n);
if (smap.empty())
Aliases.erase(t);
}
Module *owner;
/* Service type, which should be the class name (eg "Command") */
Anope::string type;
/* Service name, commands are usually named service/command */
Anope::string name;
Service(Module *o, const Anope::string &t, const Anope::string &n) : owner(o), type(t), name(n)
{
this->Register();
}
virtual ~Service()
{
this->Unregister();
}
void Register()
{
std::map<Anope::string, Service *> &smap = Services[this->type];
if (smap.find(this->name) != smap.end())
throw ModuleException("Service " + this->type + " with name " + this->name + " already exists");
smap[this->name] = this;
}
void Unregister()
{
std::map<Anope::string, Service *> &smap = Services[this->type];
smap.erase(this->name);
if (smap.empty())
Services.erase(this->type);
}
};
/** Like Reference, but used to refer to Services.
*/
template<typename T>
class ServiceReference : public Reference<T>
{
Anope::string type;
Anope::string name;
public:
ServiceReference() { }
ServiceReference(const Anope::string &t, const Anope::string &n) : type(t), name(n)
{
}
inline void operator=(const Anope::string &n)
{
this->name = n;
this->invalid = true;
}
operator bool() anope_override
{
if (this->invalid)
{
this->invalid = false;
this->ref = NULL;
}
if (!this->ref)
{
/* This really could be dynamic_cast in every case, except for when a module
* creates its own service type (that other modules must include the header file
* for), as the core is not compiled with it so there is no RTTI for it.
*/
this->ref = static_cast<T *>(::Service::FindService(this->type, this->name));
if (this->ref)
this->ref->AddReference(this);
}
return this->ref;
}
};
class ServiceAlias
{
Anope::string t, f;
public:
ServiceAlias(const Anope::string &type, const Anope::string &from, const Anope::string &to) : t(type), f(from)
{
Service::AddAlias(type, from, to);
}
~ServiceAlias()
{
Service::DelAlias(t, f);
}
};
#endif // SERVICE_H

68
include/services.h Normal file
View File

@ -0,0 +1,68 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef SERVICES_H
#define SERVICES_H
#include "sysconf.h"
#define BUFSIZE 1024
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <stdexcept>
#include <string.h>
#if HAVE_STRINGS_H
# include <strings.h>
#endif
#ifndef _WIN32
#include <unistd.h>
#endif
/* Pull in the various bits of STL */
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <exception>
#include <list>
#include <vector>
#include <deque>
#include <bitset>
#include <set>
#include <algorithm>
#include <iterator>
#include "defs.h"
#define _(x) x
#if defined __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L
# define anope_override override
# define anope_final final
#else
# define anope_override
# define anope_final
#endif
#ifndef _WIN32
# define DllExport
# define CoreExport
# define MARK_DEPRECATED __attribute((deprecated))
# define anope_close close
#else
# include "anope_windows.h"
#endif
#endif // SERVICES_H

50
include/socketengine.h Normal file
View File

@ -0,0 +1,50 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef SOCKETENGINE_H
#define SOCKETENGINE_H
#include "services.h"
#include "sockets.h"
class CoreExport SocketEngine
{
static const int DefaultSize = 2; // Uplink, mode stacker
public:
/* Map of sockets */
static std::map<int, Socket *> Sockets;
/** Called to initialize the socket engine
*/
static void Init();
/** Called to shutdown the socket engine
*/
static void Shutdown();
/** Set a flag on a socket
* @param s The socket
* @param set Whether setting or unsetting
* @param flag The flag to set or unset
*/
static void Change(Socket *s, bool set, SocketFlag flag);
/** Read from sockets and do things
*/
static void Process();
static int GetLastError();
static void SetLastError(int);
static bool IgnoreErrno();
};
#endif // SOCKETENGINE_H

511
include/sockets.h Normal file
View File

@ -0,0 +1,511 @@
/*
*
* (C) 2003-2022 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.
*/
#ifndef SOCKETS_H
#define SOCKETS_H
#ifndef _WIN32
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#endif
#include "anope.h"
#define NET_BUFSIZE 65535
/** A sockaddr union used to combine IPv4 and IPv6 sockaddrs
*/
union CoreExport sockaddrs
{
sockaddr sa;
sockaddr_in sa4;
sockaddr_in6 sa6;
/** Construct the object, sets everything to 0
*/
sockaddrs(const Anope::string &address = "");
/** Memset the object to 0
*/
void clear();
/** Get address family.
*/
int family() const;
/** Get the size of the sockaddr we represent
* @return The size
*/
size_t size() const;
/** Get the port represented by this addr
* @return The port, or -1 on fail
*/
int port() const;
/** Get the address represented by this addr
* @return The address
*/
Anope::string addr() const;
/** Get the reverse address represented by this addr
* @return The reverse address
*/
Anope::string reverse() const;
/* Is this address ipv6? */
bool ipv6() const;
/** Check if this sockaddr has data in it
*/
bool valid() const;
/** Compares with sockaddr with another. Compares address type, port, and address
* @return true if they are the same
*/
bool operator==(const sockaddrs &other) const;
/* The same as above but not */
inline bool operator!=(const sockaddrs &other) const { return !(*this == other); }
/** The equivalent of inet_pton
* @param type AF_INET or AF_INET6
* @param address The address to place in the sockaddr structures
* @param pport An option port to include in the sockaddr structures
* @throws A socket exception if given invalid IPs
*/
void pton(int type, const Anope::string &address, int pport = 0);
/** The equivalent of inet_ntop
* @param type AF_INET or AF_INET6
* @param address The in_addr or in_addr6 structure
* @throws A socket exception if given an invalid structure
*/
void ntop(int type, const void *src);
};
class CoreExport cidr
{
sockaddrs addr;
Anope::string cidr_ip;
unsigned short cidr_len;
public:
cidr(const Anope::string &ip);
cidr(const Anope::string &ip, unsigned char len);
cidr(const sockaddrs &ip, unsigned char len);
Anope::string mask() const;
bool match(const sockaddrs &other);
bool valid() const;
bool operator<(const cidr &other) const;
bool operator==(const cidr &other) const;
bool operator!=(const cidr &other) const;
struct CoreExport hash
{
size_t operator()(const cidr &s) const;
};
};
class SocketException : public CoreException
{
public:
/** Constructor for socket exceptions
* @param message Error message
*/
SocketException(const Anope::string &message) : CoreException(message) { }
/** Destructor
* @throws Nothing
*/
virtual ~SocketException() throw() { }
};
enum SocketFlag
{
SF_DEAD = 1,
SF_READABLE,
SF_WRITABLE,
SF_CONNECTING,
SF_CONNECTED,
SF_ACCEPTING,
SF_ACCEPTED,
SF_SIZE
};
class CoreExport SocketIO
{
public:
virtual ~SocketIO() { }
/** Receive something from the buffer
* @param s The socket
* @param buf The buf to read to
* @param sz How much to read
* @return Number of bytes received
*/
virtual int Recv(Socket *s, char *buf, size_t sz);
/** Write something to the socket
* @param s The socket
* @param buf The data to write
* @param size The length of the data
*/
virtual int Send(Socket *s, const char *buf, size_t sz);
int Send(Socket *s, const Anope::string &buf);
/** Accept a connection from a socket
* @param s The socket
* @return The new socket
*/
virtual ClientSocket *Accept(ListenSocket *s);
/** Finished accepting a connection from a socket
* @param s The socket
* @return SF_ACCEPTED if accepted, SF_ACCEPTING if still in process, SF_DEAD on error
*/
virtual SocketFlag FinishAccept(ClientSocket *cs);
/** Bind a socket
* @param s The socket
* @param ip The IP to bind to
* @param port The optional port to bind to
*/
virtual void Bind(Socket *s, const Anope::string &ip, int port = 0);
/** Connect the socket
* @param s The socket
* @param target IP to connect to
* @param port to connect to
*/
virtual void Connect(ConnectionSocket *s, const Anope::string &target, int port);
/** Called to potentially finish a pending connection
* @param s The socket
* @return SF_CONNECTED on success, SF_CONNECTING if still pending, and SF_DEAD on error.
*/
virtual SocketFlag FinishConnect(ConnectionSocket *s);
/** Called when the socket is destructing
*/
virtual void Destroy() { }
};
class CoreExport Socket
{
protected:
/* Socket FD */
int sock;
/* Is this an IPv6 socket? */
bool ipv6;
public:
std::bitset<SF_SIZE> flags;
/* Sockaddrs for bind() (if it's bound) */
sockaddrs bindaddr;
/* I/O functions used for this socket */
SocketIO *io;
/** Empty constructor, should not be called.
*/
Socket();
/** Constructor, possibly creates the socket and adds it to the engine
* @param sock The socket to use, -1 if we need to create our own
* @param ipv6 true if using ipv6
* @param type The socket type, defaults to SOCK_STREAM
*/
Socket(int sock, bool ipv6 = false, int type = SOCK_STREAM);
/** Destructor, closes the socket and removes it from the engine
*/
virtual ~Socket();
/** Get the socket FD for this socket
* @return the fd
*/
int GetFD() const;
/** Check if this socket is IPv6
* @return true or false
*/
bool IsIPv6() const;
/** Mark a socket as (non)blocking
* @param state true to enable blocking, false to disable blocking
* @return true if the socket is now blocking
*/
bool SetBlocking(bool state);
/** Bind the socket to an ip and port
* @param ip The ip
* @param port The port
*/
void Bind(const Anope::string &ip, int port = 0);
/** Called when there either is a read or write event.
* @return true to continue to call ProcessRead/ProcessWrite, false to not continue
*/
virtual bool Process();
/** Called when there is something to be received for this socket
* @return true on success, false to drop this socket
*/
virtual bool ProcessRead();
/** Called when the socket is ready to be written to
* @return true on success, false to drop this socket
*/
virtual bool ProcessWrite();
/** Called when there is an error for this socket
* @return true on success, false to drop this socket
*/
virtual void ProcessError();
};
class CoreExport BufferedSocket : public virtual Socket
{
protected:
/* Things read from the socket */
Anope::string read_buffer;
/* Things to be written to the socket */
Anope::string write_buffer;
/* How much data was received from this socket on this recv() */
int recv_len;
public:
BufferedSocket();
virtual ~BufferedSocket();
/** Called when there is something to be received for this socket
* @return true on success, false to drop this socket
*/
bool ProcessRead() anope_override;
/** Called when the socket is ready to be written to
* @return true on success, false to drop this socket
*/
bool ProcessWrite() anope_override;
/** Gets the new line from the input buffer, if any
*/
const Anope::string GetLine();
/** Write to the socket
* @param message The message
*/
protected:
virtual void Write(const char *buffer, size_t l);
public:
void Write(const char *message, ...);
void Write(const Anope::string &message);
/** Get the length of the read buffer
* @return The length of the read buffer
*/
int ReadBufferLen() const;
/** Get the length of the write buffer
* @return The length of the write buffer
*/
int WriteBufferLen() const;
};
class CoreExport BinarySocket : public virtual Socket
{
protected:
struct DataBlock
{
char *orig;
char *buf;
size_t len;
DataBlock(const char *b, size_t l);
~DataBlock();
};
/* Data to be written out */
std::deque<DataBlock *> write_buffer;
public:
BinarySocket();
virtual ~BinarySocket();
/** Called when there is something to be received for this socket
* @return true on success, false to drop this socket
*/
bool ProcessRead() anope_override;
/** Called when the socket is ready to be written to
* @return true on success, false to drop this socket
*/
bool ProcessWrite() anope_override;
/** Write data to the socket
* @param buffer The data to write
* @param l The length of the data; if 0 then this function returns without doing anything
*/
virtual void Write(const char *buffer, size_t l);
void Write(const char *message, ...);
void Write(const Anope::string &message);
/** Called with data from the socket
* @param buffer The data
* @param l The length of buffer
* @return true to continue reading, false to drop the socket
*/
virtual bool Read(const char *buffer, size_t l);
};
class CoreExport ListenSocket : public virtual Socket
{
public:
/** Constructor
* @param bindip The IP to bind to
* @param port The port to listen on
* @param ipv6 true for ipv6
*/
ListenSocket(const Anope::string &bindip, int port, bool ipv6);
virtual ~ListenSocket();
/** Process what has come in from the connection
* @return false to destroy this socket
*/
bool ProcessRead();
/** Called when a connection is accepted
* @param fd The FD for the new connection
* @param addr The sockaddr for where the connection came from
* @return The new socket
*/
virtual ClientSocket *OnAccept(int fd, const sockaddrs &addr) = 0;
};
class CoreExport ConnectionSocket : public virtual Socket
{
public:
/* Sockaddrs for connection ip/port */
sockaddrs conaddr;
/** Connect the socket
* @param TargetHost The target host to connect to
* @param Port The target port to connect to
*/
void Connect(const Anope::string &TargetHost, int Port);
/** Called when there either is a read or write event.
* Used to determine whether or not this socket is connected yet.
* @return true to continue to call ProcessRead/ProcessWrite, false to not continue
*/
bool Process() anope_override;
/** Called when there is an error for this socket
* @return true on success, false to drop this socket
*/
void ProcessError() anope_override;
/** Called on a successful connect
*/
virtual void OnConnect();
/** Called when a connection is not successful
* @param error The error
*/
virtual void OnError(const Anope::string &error);
};
class CoreExport ClientSocket : public virtual Socket
{
public:
/* Listen socket this connection came from */
ListenSocket *ls;
/* Clients address */
sockaddrs clientaddr;
/** Constructor
* @param ls Listen socket this connection is from
* @param addr Address the connection came from
*/
ClientSocket(ListenSocket *ls, const sockaddrs &addr);
/** Called when there either is a read or write event.
* Used to determine whether or not this socket is connected yet.
* @return true to continue to call ProcessRead/ProcessWrite, false to not continue
*/
bool Process() anope_override;
/** Called when there is an error for this socket
* @return true on success, false to drop this socket
*/
void ProcessError() anope_override;
/** Called when a client has been accepted() successfully.
*/
virtual void OnAccept();
/** Called when there was an error accepting the client
*/
virtual void OnError(const Anope::string &error);
};
class CoreExport Pipe : public Socket
{
public:
/** The FD of the write pipe
* this->sock is the readfd
*/
int write_pipe;
Pipe();
~Pipe();
/** Called when data is to be read, reads the data then calls OnNotify
*/
bool ProcessRead() anope_override;
/** Write data to this pipe
* @param data The data to write
* @param sz The amount of data to wirite
*/
void Write(const char *data, size_t sz);
inline void Write(const Anope::string &data) { this->Write(data.c_str(), data.length() + 1); }
/** Read data from this pipe
* @param data A buffer to read data into
* @param sz The size of the buffer
* @return The amount of data read
*/
int Read(char *data, size_t sz);
/** Mark the write end of this pipe (non)blocking
* @param state true to enable blocking, false to disable blocking
* @return true if the socket is now blocking
*/
bool SetWriteBlocking(bool state);
/** Called when this pipe needs to be woken up
* Is the same as Write("\0", 1)
*/
void Notify();
/** Called after ProcessRead comes back from Notify(), overload to do something useful
*/
virtual void OnNotify() = 0;
};
extern CoreExport uint32_t TotalRead;
extern CoreExport uint32_t TotalWritten;
extern CoreExport SocketIO NormalSocketIO;
#endif // SOCKET_H

47
include/sysconf.h.cmake Normal file
View File

@ -0,0 +1,47 @@
#ifndef _SYSCONF_H_
#define _SYSCONF_H_
#cmakedefine DEBUG_BUILD
#cmakedefine DEFUMASK @DEFUMASK@
#cmakedefine HAVE_CSTDINT 1
#cmakedefine HAVE_STDINT_H 1
#cmakedefine HAVE_STDDEF_H 1
#cmakedefine HAVE_STRCASECMP 1
#cmakedefine HAVE_STRICMP 1
#cmakedefine HAVE_STRINGS_H 1
#cmakedefine HAVE_UMASK 1
#cmakedefine HAVE_EVENTFD 1
#cmakedefine HAVE_EPOLL 1
#cmakedefine HAVE_POLL 1
#cmakedefine GETTEXT_FOUND 1
#ifdef HAVE_CSTDINT
# include <cstdint>
#else
# ifdef HAVE_STDINT_H
# include <stdint.h>
# else
# include "pstdint.h"
# endif
#endif
#ifdef HAVE_STDDEF_H
# include <stddef.h>
#endif
#ifdef _WIN32
# define popen _popen
# define pclose _pclose
# define ftruncate _chsize
# ifdef MSVCPP
# define PATH_MAX MAX_PATH
# endif
# define MAXPATHLEN MAX_PATH
# define bzero(buf, size) memset(buf, 0, size)
# ifdef MSVCPP
# define strcasecmp stricmp
# endif
# define sleep(x) Sleep(x * 1000)
#endif
#endif

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