mirror of
https://github.com/anope/anope.git
synced 2026-06-14 09:54:47 +02:00
Compare commits
173 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a762391446 | |||
| c070a00114 | |||
| e7c3090a70 | |||
| 5dd6326eff | |||
| 535ad6fd70 | |||
| 5df4ac9a98 | |||
| 4c54a3939f | |||
| 3d09748d1c | |||
| 36a4be7623 | |||
| 5fc72660e4 | |||
| 303e652a35 | |||
| e5447a8024 | |||
| 1bee18fcf4 | |||
| a57e41304f | |||
| e0e8147ee0 | |||
| 41a24afa4f | |||
| 4266d17e8c | |||
| 8d3fa47ab2 | |||
| 64781817ac | |||
| 69c18f131f | |||
| e030771cbc | |||
| 03f05d3948 | |||
| 32c4908c8c | |||
| c5ff7c6868 | |||
| 89257d9bce | |||
| e47aacad0e | |||
| 72ade225a7 | |||
| a52af0d260 | |||
| 92920f5a1c | |||
| bf727285bc | |||
| 310e95a92e | |||
| 78bff86dab | |||
| 3f093d708f | |||
| c3cc5804c3 | |||
| dc58239c8a | |||
| b67963353f | |||
| a899c04ec2 | |||
| fb17bc85ea | |||
| 474cd7a99b | |||
| 7de4b86b7f | |||
| 76337bc04a | |||
| abe232601b | |||
| 6ada3ec871 | |||
| 61a8dd57f7 | |||
| 94427b234c | |||
| fb3c819bee | |||
| f0c23e80a2 | |||
| 1e86c46000 | |||
| 2f49065500 | |||
| 41ae2dbefb | |||
| f44280a9c9 | |||
| d147db9023 | |||
| f484a68dee | |||
| 8550e22167 | |||
| 9834518b28 | |||
| 64ca357b13 | |||
| dc5039e994 | |||
| 845ca576b4 | |||
| 2264a206d2 | |||
| d324e91520 | |||
| 9ac1b4ba01 | |||
| 7e0cb6d8ef | |||
| 3055b7272b | |||
| 969cd5dd6c | |||
| 1f02278a1c | |||
| 32007f81cf | |||
| 609f87d39f | |||
| e88925e587 | |||
| c46ec39e50 | |||
| 9b2202dfee | |||
| 03f6e26550 | |||
| c554e85063 | |||
| 2892c9580f | |||
| 3c0994a89e | |||
| e800afcfac | |||
| 2ad697898f | |||
| e4068249dd | |||
| d45cb5451e | |||
| d9c9f2a407 | |||
| 7213413f8b | |||
| 516211c88a | |||
| d576137f28 | |||
| e1f5e030bc | |||
| afffeb0a1d | |||
| 4fc71bb22f | |||
| d4732faf41 | |||
| 95684187b6 | |||
| 4f33b17f96 | |||
| 0cdab86978 | |||
| 4f76bee273 | |||
| 8557a4161a | |||
| c9008cdafa | |||
| 8a7793da0c | |||
| 64b332730e | |||
| 36837330ae | |||
| 8b64e46ef1 | |||
| c4460784c2 | |||
| 408ec02406 | |||
| 67fc8c3416 | |||
| fb2fd9e9d3 | |||
| 527e04275f | |||
| c895bd2e59 | |||
| 94b2d1ac12 | |||
| a76e074f6d | |||
| 2f004c2aab | |||
| b940077553 | |||
| c8ded08b43 | |||
| 62a01dcc87 | |||
| 0cd3bfa24f | |||
| e46bcff324 | |||
| 67719e8db1 | |||
| 48be41cf7b | |||
| 5ceee5df38 | |||
| 1c12976958 | |||
| 96583892c6 | |||
| 0991d4e199 | |||
| 58233fb8bc | |||
| be928b5bbc | |||
| 31bc1d6b82 | |||
| 829ef1b7bd | |||
| b068874f40 | |||
| 18b3c572f4 | |||
| af034928cb | |||
| 8d40a750cc | |||
| 6a3f7c01b1 | |||
| 4c2bf72cb6 | |||
| 8e7b742ec7 | |||
| 19b47c7bae | |||
| 3bdc81348a | |||
| bf8f62c32d | |||
| d417241a5b | |||
| e5cb2018e5 | |||
| df6095fed2 | |||
| 8210e82a5e | |||
| d6d72cd803 | |||
| 063d9bf5f6 | |||
| 830e8617e6 | |||
| cf89e10a4c | |||
| 6842ad36f7 | |||
| 24f17de4aa | |||
| bbb04d4662 | |||
| 20052247c3 | |||
| 8b61a529a2 | |||
| 1137c50095 | |||
| 52d422d020 | |||
| 43c460e593 | |||
| 17ba13bc95 | |||
| 60229b15d2 | |||
| 3c88f3b8cf | |||
| 93cb5d06db | |||
| 7a64d95f7c | |||
| ff66e15f38 | |||
| 07902c03fd | |||
| d9949320c7 | |||
| b0ec178e85 | |||
| f753a925ad | |||
| 74dbfe0699 | |||
| 3bea089793 | |||
| ff93355af8 | |||
| 8fecad3039 | |||
| 37bd2c238e | |||
| 9a947fa435 | |||
| 4f7868b125 | |||
| 8066378471 | |||
| ab27b792b0 | |||
| f1c3bdd55e | |||
| 08edb15bea | |||
| 56c6ef4449 | |||
| 6526d2d8b3 | |||
| 76ab5c2c38 | |||
| 54e98f017c | |||
| bb7706d0f7 | |||
| 16e0b72d2d |
+16
-12
@@ -2,6 +2,12 @@
|
||||
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)
|
||||
|
||||
# If the Source dir and the Binary dir are the same, we are building in-source, which we will disallow due to Autotools being there (but only on non-Windows)
|
||||
@@ -80,7 +86,7 @@ set(DEFAULT_LIBRARY_DIRS)
|
||||
set(DEFAULT_INCLUDE_DIRS)
|
||||
|
||||
# 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}" STREQUAL "Clang")
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "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: "
|
||||
@@ -146,7 +152,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
if(DEFAULT_INCLUDE_DIRS)
|
||||
remove_list_duplicates(DEFAULT_INCLUDE_DIRS)
|
||||
endif(DEFAULT_INCLUDE_DIRS)
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "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)
|
||||
@@ -408,16 +414,14 @@ endif(NOT LOGS_DIR)
|
||||
read_from_file(${Anope_SOURCE_DIR}/src/version.sh "^VERSION_" VERSIONS)
|
||||
# Iterate through the strings found
|
||||
foreach(VERSION_STR ${VERSIONS})
|
||||
# Get the length of the string
|
||||
string(LENGTH ${VERSION_STR} VERSION_LEN)
|
||||
# Subtract 16 from the string's length (8 for VERSION_, 5 more for the type, 2 for the space and leading quote, 1 for the trailing quote)
|
||||
math(EXPR VERSION_NUM_LEN "${VERSION_LEN} - 16")
|
||||
# Extract the type from the string
|
||||
string(SUBSTRING ${VERSION_STR} 8 5 VERSION_TYPE)
|
||||
# Extract the actual value from the string
|
||||
string(SUBSTRING ${VERSION_STR} 15 ${VERSION_NUM_LEN} VERSION)
|
||||
# Set the version type to the value extract from above
|
||||
set(VERSION_${VERSION_TYPE} ${VERSION})
|
||||
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
|
||||
|
||||
@@ -176,42 +176,9 @@ done
|
||||
which cmake > /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
clear
|
||||
if exists "cmake-bin" ; then :
|
||||
else
|
||||
echo "Anope requires CMake 2.4 or newer, which can be downloaded at http://cmake.org"
|
||||
echo "If you have installed CMake already, ensure it is in your PATH environment variable."
|
||||
|
||||
if [ `uname` = "Linux" ] ; then
|
||||
|
||||
echo ""
|
||||
echo "Config can attempt to install CMake for you now, which"
|
||||
echo "will take approximately 50 MB of disk space."
|
||||
echo "Would you like to install CMake now?"
|
||||
echo2 "[y] "
|
||||
read YN
|
||||
if [ "$YN" = "n" ] ; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Downloading CMake... this may take a minute or two."
|
||||
wget -q http://anope.org/cmake/linux-i386.php -O cmake-bin.tar.gz
|
||||
if [ $? -ne 0 ] ; then
|
||||
rm -f cmake-bin.tar.gz
|
||||
echo "Unable to download CMake"
|
||||
exit 0
|
||||
fi
|
||||
mkdir -p cmake-bin
|
||||
tar zxf cmake-bin.tar.gz -C cmake-bin
|
||||
rm -f cmake-bin.tar.gz
|
||||
echo "Done!"
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
CMAKE_BIN=`find cmake-bin -name cmake`
|
||||
CMAKE_BIN="`pwd`/`dirname $CMAKE_BIN`"
|
||||
PATH="$PATH:$CMAKE_BIN"
|
||||
echo "Anope requires CMake 2.4 or newer, which can be downloaded at http://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
|
||||
|
||||
###########################################################################
|
||||
|
||||
BIN
Binary file not shown.
+6
-14
@@ -2,33 +2,25 @@
|
||||
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_library(ICONV_LIBRARY iconv 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_library(ICONV_LIBRARY libiconv PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_LIBS})
|
||||
find_library(MINGWEX_LIBRARY libmingwex PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_LIBS})
|
||||
find_library(GCC_LIBRARY libgcc 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_MSGFMT AND ICONV_LIBRARY AND MINGWEX_LIBRARY AND GCC_LIBRARY)
|
||||
if(GETTEXT_INCLUDE AND GETTEXT_LIBRARY AND GETTEXT_MSGFMT)
|
||||
set(GETTEXT_FOUND TRUE)
|
||||
endif(GETTEXT_INCLUDE AND GETTEXT_MSGFMT AND ICONV_LIBRARY AND MINGWEX_LIBRARY AND GCC_LIBRARY)
|
||||
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})
|
||||
|
||||
if(WIN32)
|
||||
set(GETTEXT_LIBRARIES libiconv libintl libmingwex libgcc)
|
||||
else(WIN32)
|
||||
if(GETTEXT_LIBRARY)
|
||||
set(GETTEXT_LIBRARIES ${GETTEXT_LIBRARY} ${ICONV_LIBRARY})
|
||||
endif(GETTEXT_LIBRARY)
|
||||
endif(WIN32)
|
||||
endif(GETTEXT_FOUND)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* client, the client becomes no different from a normal service bot, so you will have to use botserv/bot
|
||||
* to manually delete the client.
|
||||
*
|
||||
* You may then waant to map some of the below commands to other services, like placing botserv/bot on
|
||||
* You may then want to map some of the below commands to other services, like placing botserv/bot on
|
||||
* OperServ so you can delete the below client, and mapping assign and unassign to ChanServ so users are
|
||||
* able to control whether or not ChanServ is in the channel. You may also want to map botserv/set/nobot
|
||||
* to OperServ so you can restrict who can assign the other core service clients.
|
||||
@@ -202,7 +202,7 @@ command { service = "BotServ"; name = "BADWORDS"; command = "botserv/badwords";
|
||||
* Used for administrating BotServ bots.
|
||||
*/
|
||||
module { name = "bs_bot" }
|
||||
command { service = "BotServ"; name = "BOT"; command = "botserv/bot"; }
|
||||
command { service = "BotServ"; name = "BOT"; command = "botserv/bot"; permission = "botserv/bot"; }
|
||||
|
||||
/*
|
||||
* bs_botlist
|
||||
|
||||
@@ -151,6 +151,13 @@ module
|
||||
*/
|
||||
reasonmax = 200
|
||||
|
||||
/*
|
||||
* The message formatting to use for signed kick messages.
|
||||
* %n is the nick of the kicker
|
||||
* %m is the message specified
|
||||
*/
|
||||
signkickformat = "%m (%n)"
|
||||
|
||||
/*
|
||||
* If set, prevents channel access entries from containing hostmasks.
|
||||
*/
|
||||
@@ -1061,6 +1068,13 @@ module
|
||||
* If not set, the default is +nt.
|
||||
*/
|
||||
mlock = "+nt"
|
||||
|
||||
/*
|
||||
* The maximum number of entries that may be on a mode lock list.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
max = 32
|
||||
}
|
||||
command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; group = "chanserv/management"; }
|
||||
|
||||
@@ -1161,7 +1175,7 @@ command { service = "ChanServ"; name = "SET"; command = "chanserv/set"; group =
|
||||
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"; }
|
||||
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"; }
|
||||
|
||||
+18
-5
@@ -319,6 +319,16 @@ networkinfo
|
||||
*/
|
||||
modelistsize = 100
|
||||
|
||||
/*
|
||||
* Characters allowed in nicknames. This always includes the characters described
|
||||
* in RFC1459, and so does not need to be set for normal behavior. Changing this to
|
||||
* include characters your IRCd doesn't support will cause your IRCd and/or Services
|
||||
* to break. Multibyte characters are not supported, nor are escape sequences.
|
||||
*
|
||||
* It is recommended you DON'T change this.
|
||||
*/
|
||||
#nick_chars = ""
|
||||
|
||||
/*
|
||||
* The characters allowed in hostnames. This is used for validating hostnames given
|
||||
* to services, such as BotServ bot hostnames and user vhosts. Changing this is not
|
||||
@@ -462,7 +472,7 @@ options
|
||||
|
||||
/*
|
||||
* If set, this will allow users to let Services send PRIVMSGs to them
|
||||
* instead of NOTICEs. Also see the defmsg option of nickserv:defaults,
|
||||
* instead of NOTICEs. Also see the "msg" option of nickserv:defaults,
|
||||
* which also toggles the default communication (PRIVMSG or NOTICE) to
|
||||
* use for unregistered users.
|
||||
*
|
||||
@@ -703,7 +713,7 @@ log
|
||||
* create, destroy, join, part, kick, leave, mode
|
||||
*
|
||||
* Valid user options are:
|
||||
* connect, disconnect, quit, nick, ident, host, mode, maxusers, oper
|
||||
* connect, disconnect, quit, nick, ident, host, mode, maxusers, oper, away
|
||||
*
|
||||
* Rawio and debug are simple yes/no answers, there are no types for them.
|
||||
*
|
||||
@@ -747,7 +757,9 @@ log
|
||||
*
|
||||
* Available privileges:
|
||||
* botserv/administration - Can view and assign private BotServ bots
|
||||
* botserv/fantasy - Can use fantasy commands without the FANTASIA privilege
|
||||
* chanserv/administration - Can modify the settings of any channel (including changing of the owner!)
|
||||
* chanserv/access/list - Can view channel access and akick lists, but not modify them
|
||||
* chanserv/access/modify - Can modify channel access and akick lists, and use /chanserv enforce
|
||||
* chanserv/auspex - Can see any information with /chanserv info
|
||||
* chanserv/no-register-limit - May register an unlimited number of channels and nicknames
|
||||
@@ -761,13 +773,14 @@ log
|
||||
* nickserv/confirm - Can confirm other users nicknames
|
||||
* nickserv/drop - Can drop other users nicks
|
||||
* operserv/config - Can modify services's configuration
|
||||
* operserv/oper/modify - Can add and remove operators with at most the same privileges
|
||||
* protected - Can not be kicked from channels by Services
|
||||
*
|
||||
* Available commands:
|
||||
* botserv/bot/del botserv/bot/add botserv/bot/change botserv/set/private
|
||||
* botserv/set/nobot
|
||||
*
|
||||
* chanserv/access/list chanserv/drop chanserv/getkey chanserv/invite
|
||||
* chanserv/drop chanserv/getkey chanserv/invite
|
||||
* chanserv/list chanserv/suspend chanserv/topic
|
||||
*
|
||||
* chanserv/saset/bantype chanserv/saset/description chanserv/saset/email chanserv/saset/keepmodes
|
||||
@@ -848,7 +861,7 @@ opertype
|
||||
|
||||
inherits = "Services Operator"
|
||||
|
||||
commands = "chanserv/access/list chanserv/drop chanserv/getkey chanserv/saset/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svs operserv/stats operserv/oline operserv/noop operserv/forbid global/*"
|
||||
commands = "botserv/* chanserv/access/list chanserv/drop chanserv/getkey chanserv/saset/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svs operserv/stats operserv/oline operserv/noop operserv/forbid global/*"
|
||||
|
||||
privs = "*"
|
||||
}
|
||||
@@ -1005,7 +1018,7 @@ mail
|
||||
emailchange_subject = "Email confirmation"
|
||||
emailchange_message = "Hi,
|
||||
|
||||
You have requested to change your email address to %e.
|
||||
You have requested to change your email address from %e to %E.
|
||||
Please type \" /msg NickServ CONFIRM %c \" to confirm this change.
|
||||
|
||||
If you don't know why this mail was sent to you, please ignore it silently.
|
||||
|
||||
@@ -137,7 +137,17 @@ command { service = "MemoServ"; name = "DEL"; command = "memoserv/del"; }
|
||||
*
|
||||
* Used to ignore memos from specific users.
|
||||
*/
|
||||
module { name = "ms_ignore" }
|
||||
module
|
||||
{
|
||||
name = "ms_ignore"
|
||||
|
||||
/*
|
||||
* The maximum number of entries that may be on a memo ignore list.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
max = 32
|
||||
}
|
||||
command { service = "MemoServ"; name = "IGNORE"; command = "memoserv/ignore"; }
|
||||
|
||||
/*
|
||||
|
||||
+52
-10
@@ -124,26 +124,58 @@ module { name = "help" }
|
||||
* %g is the realname of the user
|
||||
* %h is the hostname of the user
|
||||
* %i is the IP of the user
|
||||
* %r is the reason (configured below). Will be nothing if not configured.
|
||||
* %r is the reply reason (configured below). Will be nothing if not configured.
|
||||
* %N is the network name set in networkinfo:networkname
|
||||
*/
|
||||
reason = "You are listed in the efnet RBL, visit http://rbl.efnetrbl.org/?i=%i for info"
|
||||
|
||||
/* Replies to ban and their reason. If this is totally omitted all replies get banned. */
|
||||
1 = "Open Proxy"
|
||||
/* Don't ban for result 2 or 3 */
|
||||
#2 = "spamtrap666"
|
||||
#3 = "spamtrap50"
|
||||
4 = "TOR"
|
||||
5 = "Drones / Flooding"
|
||||
/* Replies to ban and their reason. If no relies are configured, all replies get banned. */
|
||||
reply
|
||||
{
|
||||
code = 1
|
||||
reason = "Open Proxy"
|
||||
}
|
||||
|
||||
#reply
|
||||
{
|
||||
code = 2
|
||||
reason = "spamtrap666"
|
||||
}
|
||||
|
||||
#reply
|
||||
{
|
||||
code = 3
|
||||
reason = "spamtrap50"
|
||||
}
|
||||
|
||||
reply
|
||||
{
|
||||
code = 4
|
||||
reason = "TOR"
|
||||
|
||||
/*
|
||||
* If set, users identified to services at the time the result comes back
|
||||
* will not be banned.
|
||||
*/
|
||||
#allow_account = yes
|
||||
}
|
||||
|
||||
reply
|
||||
{
|
||||
code = 5
|
||||
reason = "Drones / Flooding"
|
||||
}
|
||||
}
|
||||
|
||||
blacklist
|
||||
#blacklist
|
||||
{
|
||||
name = "dnsbl.dronebl.org"
|
||||
time = 4h
|
||||
reason = "You have a host listed in the DroneBL. For more information, visit http://dronebl.org/lookup_branded?ip=%i&network=%N"
|
||||
}
|
||||
|
||||
/* Exempt localhost from DNSBL checks */
|
||||
exempt { ip = "127.0.0.1" }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -267,7 +299,9 @@ module { name = "help" }
|
||||
password_attribute = "userPassword"
|
||||
|
||||
/*
|
||||
* If set, the reason to give the users who try to "/msg NickServ REGISTER".
|
||||
* If set, the reason to give the users who try to register with nickserv,
|
||||
* including nick registration from grouping.
|
||||
*
|
||||
* If not set, then registration is not blocked.
|
||||
*/
|
||||
#disable_register_reason = "To register on this network visit http://some.misconfigured.site/register"
|
||||
@@ -588,6 +622,14 @@ module { name = "help" }
|
||||
*/
|
||||
cert = "data/anope.crt"
|
||||
key = "data/anope.key"
|
||||
|
||||
/*
|
||||
* As of 2014 SSL 3.0 is considered insecure, but it might be enabled
|
||||
* on some systems by default for compatibility reasons.
|
||||
* You can use the following option to enable or disable it explicitly.
|
||||
* Leaving this option not set defaults to the default system behavior.
|
||||
*/
|
||||
#sslv3 = no
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -260,7 +260,7 @@ command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"
|
||||
*/
|
||||
#akillreason = "This network is currently not accepting connections, please try again later."
|
||||
}
|
||||
#command { service = "OperServ"; name = "DEFCON"; command = "operserv/defcon"; }
|
||||
#command { service = "OperServ"; name = "DEFCON"; command = "operserv/defcon"; permission = "operserv/defcon"; }
|
||||
|
||||
/*
|
||||
* os_dns
|
||||
|
||||
@@ -1,3 +1,26 @@
|
||||
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
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
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
|
||||
|
||||
+4
-19
@@ -21,26 +21,19 @@ Note: You should also read the README and FAQ files!
|
||||
|
||||
http://www.anope.org/
|
||||
|
||||
Anope can be built one of two ways. The recommended way is to use CMake.
|
||||
You can check if CMake is already installed on your system using the
|
||||
command:
|
||||
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.6-patch 1". If the version is less than 2.4 or you get
|
||||
"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:
|
||||
|
||||
http://www.cmake.org/cmake/resources/software.html
|
||||
|
||||
If you are unable to install CMake yourself (either due to lack of space
|
||||
or restrictions by your hosting provider), you still have the alternative
|
||||
to use the provided configure script. This option is not recommended and
|
||||
will eventually be phased out, but is provided for compatibility for those
|
||||
lacking CMake.
|
||||
|
||||
Next, unpack the package in your home directory, and go into the created
|
||||
directory.
|
||||
|
||||
@@ -51,16 +44,8 @@ Note: You should also read the README and FAQ files!
|
||||
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.
|
||||
The question to using configure or cmake depends on your decision from
|
||||
above. If you have CMake and wish to use it, answer with cmake, otherwise
|
||||
answer with configure.
|
||||
|
||||
You can now type make to compile Anope. If there are errors in the
|
||||
Makefile, *try to use gmake* instead. If it still doesn't work, you (or
|
||||
the system administrator if it's a shell) must install GNU make. You may
|
||||
find it at ftp://prep.ai.mit.edu/pub/gnu/.
|
||||
|
||||
Now type make install (or gmake install; see above). This will install
|
||||
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
|
||||
|
||||
+90
-99
@@ -1,5 +1,5 @@
|
||||
Instructions d'installation d'Anope
|
||||
------------------------------------
|
||||
-----------------------------------
|
||||
|
||||
1) Installation d'Anope
|
||||
2) Mettre à jour Anope
|
||||
@@ -11,148 +11,139 @@ Note : Vous devrez également lire les fichiers README et FAQ !
|
||||
|
||||
1) Installation d'Anope
|
||||
|
||||
NOTE IMPORTANTE : il n'est pas recommandé 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.
|
||||
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 :
|
||||
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 :
|
||||
|
||||
http://www.anope.org/
|
||||
http://www.anope.org/
|
||||
|
||||
Anope peut être installé de deux façons. La méthode recommandée est
|
||||
d'utiliser CMake. Vous pouvez vérifier si CMake est déjà installé
|
||||
sur votre système en utilisant la commande :
|
||||
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 similaire
|
||||
à "cmake version 2.6 cmake-patch 1". 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 serez pas en mesure d'utiliser CMake, sauf si vous l'installez
|
||||
vous-même dans votre répertoire home. CMake peut être téléchargé ici :
|
||||
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 :
|
||||
|
||||
http://www.cmake.org/cmake/resources/software.html
|
||||
|
||||
Si vous n'arrivez pas à l'installer (soit en raison du manque d'espace
|
||||
ou de restrictions par votre fournisseur d'hébergement), vous pouvez encore
|
||||
utiliser le script de configuration fourni. Cette option n'est pas
|
||||
recommandée et finira par être retirée, mais est fournie pour la
|
||||
compatibilité de ceux à qui il manque CMake.
|
||||
Ensuite, décompressez le package dans votre répertoire home, et allez
|
||||
dans le répértoire qui vient d'être créé.
|
||||
|
||||
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 compiler Anope sur votre système. Si vous
|
||||
ne savez pas répondre à une question, utilisez la valeur par défaut. La
|
||||
question d'utiliser CMake ou configure dépend de la décision que vous avez
|
||||
prise précedemment. Si vous avez CMake et que vous souhaitez l'utiliser,
|
||||
répondez avec cmake, sinon répondez avec configure.
|
||||
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.
|
||||
|
||||
Vous pouvez maintenant taper make pour compiler Anope. S'il y'a des erreurs
|
||||
dans le Makefile, *essayez d'utiliser* gmake à la place. Si cela ne
|
||||
fonctionne toujours pas, vous (ou votre administrateur système) devriez
|
||||
installer GNU make.
|
||||
Vous pouvez le trouver ici : ftp://prep.ai.mit.edu/pub/gnu/.
|
||||
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.
|
||||
|
||||
Maintenant, tapez make install (ou gmake install ; voir ci-dessus). Cela
|
||||
permet d'installer tous les fichiers nécessaires dans les chemins que vous
|
||||
avez spécifié au script configure, et de régler les permissions des fichiers.
|
||||
Vous devez vous assurer que le répertoire data n'est pas accessible par les
|
||||
autres utilisateurs, 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 tout utilisateur.
|
||||
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 voyez des erreurs lors de ce processus, merci de nous envoyer un
|
||||
e-mail avec la sortie d'erreur *complète* et n'oubliez pas de mentionner
|
||||
les versions de votre système, compilateur et bibliothèque C++.
|
||||
|
||||
Allez maintenant dans le répertoire de données (par défaut, ~/services/data).
|
||||
Copiez l'exemple de fichier de configuration (example.conf) en services.conf
|
||||
et ouvrez ce dernier avec votre éditeur de texte favori. Il contient toute
|
||||
les directives de configuration. Anope va l'utiliser au démarrage.
|
||||
Lisez attentivement les instructions contenues dans le fichier.
|
||||
L'utilisation des valeurs par défaut n'est pas recommendé et Anope ne
|
||||
fonctionnera probablement pas.
|
||||
|
||||
Si vous avez besoin d'aide, abonnez-vous à la liste de diffusion Anope
|
||||
et envoyez-y vos e-mails pour obtenir de l'aide de la part des autres
|
||||
utilisateurs. Voir le fichier README pour plus d'informations.
|
||||
Si vous avez besoin d'aide, vous pouvez aller sur le site
|
||||
http://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. Il y a cependant une ligne de conduite
|
||||
spécifique :
|
||||
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, toujours
|
||||
redémarrer avec un fichier de configuration neuf depuis example.conf.
|
||||
* 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 linker.
|
||||
Pour les relier à votre réseau, vous aurez besoin de configurer votre
|
||||
IRCd pour permettre aux services de se connecter.
|
||||
|
||||
La configuration varie selon les IRCd, mais vous aurez probablement besoin
|
||||
d'un block link (aussi appelé connect block, ou C line), un U line (aussi
|
||||
appelé shared block) et assurez-vous que l'IRCd écoute sur le port donné
|
||||
dans le block link.
|
||||
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 link peuvent être trouvés dans le fichier
|
||||
example.conf pour certains des IRCd les plus populaires.
|
||||
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 link interactif situé ici :
|
||||
Vous pouvez également essayer notre créateur de bloc link interactif
|
||||
situé ici :
|
||||
|
||||
http://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.
|
||||
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 ya des erreurs de syntaxe dans le fichier de configuration, elles
|
||||
seront affichées sur 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.
|
||||
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.
|
||||
Certains IRCds sur certains systèmes peuvent être très lents pour le
|
||||
processus de liaison. Si rien n'arrive après environ une minute, il y a
|
||||
probablement un problème de configuration. Essayez de lancer Anope en mode
|
||||
debug ./services -debug -nofork pour voir toutes les erreurs rencontrées
|
||||
et essayez de les corriger.
|
||||
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.
|
||||
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.
|
||||
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 le chemin d'Anope
|
||||
(par défaut, ~/services/data) 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 faites cela ;))
|
||||
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. Tapez crontab -e.
|
||||
Cela va ouvrir l'éditeur de texte par défaut avec le fichier crontab.
|
||||
Entrez la ligne suivante (avec le chemin correct) :
|
||||
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/data/services.chk > /dev/null 2>&1
|
||||
*/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 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
|
||||
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é.
|
||||
Sauvegardez, quittez, et c'est installé !
|
||||
|
||||
+3
-11
@@ -73,18 +73,10 @@ Anope for Windows
|
||||
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 additional search paths to the last question in
|
||||
Config, such as:
|
||||
they are by passing their location to Config.
|
||||
|
||||
-DEXTRA_INCLUDE:STRING=c:/openssl/include;c:/mysql/include
|
||||
-DEXTRA_LIBS:STRING=c:/openssl/lib;c:/mysql/lib
|
||||
|
||||
Building Anope with gettext requires libintl, libiconv, libgcc and
|
||||
libmingex. We have precompiled these libraries for you that you may
|
||||
use if you want. They are avaiable at http://anope.org/downloads/anope-extra.zip
|
||||
The OpenSSL, MySQL, and OpenLDAP header files and libraries are also included in
|
||||
this package. Once downloaded and extracted, you should run install.bat
|
||||
then give Config the path to the new 'installed' directory.
|
||||
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:
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@ This allows external applications, such as websites, to execute remote procedure
|
||||
|
||||
Currently there are 5 supported XMLRPC calls, provided by m_xmlrpc_main:
|
||||
|
||||
checkAuthetication - 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.
|
||||
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 a the given command to Anope using the given service name. If the user given is online, the
|
||||
|
||||
@@ -7,7 +7,7 @@ get_target_property(version_BINARY version 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
|
||||
COMMAND ${version_BINARY} ${Anope_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/version.h ${CMAKE_CURRENT_BINARY_DIR}/build.h
|
||||
DEPENDS version ${SRC_SRCS}
|
||||
)
|
||||
# Add version to list of files for CPack to ignore
|
||||
@@ -15,6 +15,7 @@ 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 "")
|
||||
|
||||
+3
-3
@@ -242,9 +242,9 @@ class CoreExport Channel : public Base, public Extensible
|
||||
|
||||
/** Get a list of modes on a channel
|
||||
* @param name A mode name to get the list of
|
||||
* @return a pair of iterators for the beginning and end of the list
|
||||
* @return a vector of the list mode entries
|
||||
*/
|
||||
std::pair<ModeList::iterator, ModeList::iterator> GetModeList(const Anope::string &name);
|
||||
std::vector<Anope::string> GetModeList(const Anope::string &name);
|
||||
|
||||
/** Get a string of the modes set on this channel
|
||||
* @param complete Include mode parameters
|
||||
@@ -258,7 +258,7 @@ class CoreExport Channel : public Base, public Extensible
|
||||
* @param newtopic The new topic
|
||||
* @param ts The time the new topic is being set
|
||||
*/
|
||||
void ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts = Anope::CurTime);
|
||||
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
|
||||
|
||||
@@ -170,6 +170,8 @@ class CoreExport Command : public Service
|
||||
*/
|
||||
static void Run(CommandSource &source, const Anope::string &message);
|
||||
|
||||
void Run(CommandSource &source, const Anope::string &, const CommandInfo &, std::vector<Anope::string> ¶ms);
|
||||
|
||||
/** 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
|
||||
|
||||
@@ -103,6 +103,8 @@ namespace Configuration
|
||||
time_t TimeoutCheck;
|
||||
/* options:usestrictprivmsg */
|
||||
bool UseStrictPrivmsg;
|
||||
/* networkinfo:nickchars */
|
||||
Anope::string NickChars;
|
||||
|
||||
/* either "/msg " or "/" */
|
||||
Anope::string StrictPrivmsg;
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ namespace Language
|
||||
#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. Please try again with a shorter password.")
|
||||
#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.")
|
||||
|
||||
@@ -107,6 +107,8 @@ class CoreExport ChannelMode : public Mode
|
||||
|
||||
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 ¶m);
|
||||
@@ -215,6 +217,8 @@ class CoreExport ChannelModeVirtual : public T
|
||||
|
||||
~ChannelModeVirtual();
|
||||
|
||||
void Check() anope_override;
|
||||
|
||||
ChannelMode *Wrap(Anope::string ¶m) anope_override;
|
||||
|
||||
ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) = 0;
|
||||
|
||||
+39
-14
@@ -20,6 +20,7 @@
|
||||
#include "timers.h"
|
||||
#include "logger.h"
|
||||
#include "extensible.h"
|
||||
#include "version.h"
|
||||
|
||||
/** This definition is used as shorthand for the various classes
|
||||
* and functions needed to make a module loadable by the OS.
|
||||
@@ -40,6 +41,14 @@
|
||||
extern "C" void AnopeFini(x *m) \
|
||||
{ \
|
||||
delete m; \
|
||||
} \
|
||||
extern "C" DllExport ModuleVersionC AnopeVersion() \
|
||||
{ \
|
||||
ModuleVersionC ver; \
|
||||
ver.version_major = VERSION_MAJOR; \
|
||||
ver.version_minor = VERSION_MINOR; \
|
||||
ver.version_patch = VERSION_PATCH; \
|
||||
return ver; \
|
||||
}
|
||||
#else
|
||||
# define MODULE_INIT(x) \
|
||||
@@ -50,6 +59,14 @@
|
||||
extern "C" DllExport void AnopeFini(x *m) \
|
||||
{ \
|
||||
delete m; \
|
||||
} \
|
||||
extern "C" DllExport ModuleVersionC AnopeVersion() \
|
||||
{ \
|
||||
ModuleVersionC ver; \
|
||||
ver.version_major = VERSION_MAJOR; \
|
||||
ver.version_minor = VERSION_MINOR; \
|
||||
ver.version_patch = VERSION_PATCH; \
|
||||
return ver; \
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -173,6 +190,11 @@ enum
|
||||
};
|
||||
typedef unsigned short ModType;
|
||||
|
||||
struct ModuleVersionC
|
||||
{
|
||||
int version_major, version_minor, version_patch;
|
||||
};
|
||||
|
||||
/** Returned by Module::GetVersion, used to see what version of Anope
|
||||
* a module is compiled against.
|
||||
*/
|
||||
@@ -184,12 +206,7 @@ class ModuleVersion
|
||||
int version_patch;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
* @param major The major version number
|
||||
* @param minor The minor version number
|
||||
* @param patch The patch version number
|
||||
*/
|
||||
ModuleVersion(int major, int minor, int patch);
|
||||
ModuleVersion(const ModuleVersionC &);
|
||||
|
||||
/** Get the major version of Anope this was built against
|
||||
* @return The major version
|
||||
@@ -279,11 +296,7 @@ class CoreExport Module : public Extensible
|
||||
*/
|
||||
void SetAuthor(const Anope::string &author);
|
||||
|
||||
/** Get the version of Anope this module was
|
||||
* compiled against
|
||||
* @return The version
|
||||
*/
|
||||
ModuleVersion GetVersion() const;
|
||||
virtual void Prioritize();
|
||||
|
||||
/* Everything below here are events. Modules must ModuleManager::Attach to these events
|
||||
* before they will be called.
|
||||
@@ -472,11 +485,12 @@ class CoreExport Module : public Extensible
|
||||
virtual void OnJoinChannel(User *u, Channel *c) { throw NotImplementedException(); }
|
||||
|
||||
/** Called when a new topic is set
|
||||
* @param source The user changing the topic, if any
|
||||
* @param c The channel
|
||||
* @param setter The user who set the new topic
|
||||
* @param setter The user who set the new topic, if there is no source
|
||||
* @param topic The new topic
|
||||
*/
|
||||
virtual void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) { throw NotImplementedException(); }
|
||||
virtual void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) { throw NotImplementedException(); }
|
||||
|
||||
/** Called before a channel expires
|
||||
* @param ci The channel
|
||||
@@ -747,6 +761,12 @@ class CoreExport Module : public Extensible
|
||||
*/
|
||||
virtual void OnNickRegister(User *user, NickAlias *na, const Anope::string &pass) { throw NotImplementedException(); }
|
||||
|
||||
/** Called when a nick is confirmed. This will never be called if registration confirmation is not enabled.
|
||||
* @param user The user confirming the nick
|
||||
* @param The account being confirmed
|
||||
*/
|
||||
virtual void OnNickConfirm(User *user, NickCore *) { throw NotImplementedException(); }
|
||||
|
||||
/** Called when a nick is suspended
|
||||
* @param na The nick alias
|
||||
*/
|
||||
@@ -1091,7 +1111,7 @@ enum Implementation
|
||||
I_OnAccessClear, I_OnLevelChange, I_OnChanDrop, I_OnChanRegistered, I_OnChanSuspend, I_OnChanUnsuspend,
|
||||
I_OnCreateChan, I_OnDelChan, I_OnChannelCreate, I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick,
|
||||
I_OnChanInfo, I_OnCheckPriv, I_OnGroupCheckPriv, I_OnNickDrop, I_OnNickGroup, I_OnNickIdentify,
|
||||
I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate,
|
||||
I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickConfirm, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate,
|
||||
I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearCert,
|
||||
I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnBotInfo, I_OnCheckAuthentication, I_OnNickUpdate,
|
||||
I_OnFingerprint, I_OnUserAway, I_OnInvite, I_OnDeleteVhost, I_OnSetVhost, I_OnSetDisplayedHost, I_OnMemoSend, I_OnMemoDel,
|
||||
@@ -1197,6 +1217,11 @@ class CoreExport ModuleManager
|
||||
* @return MOD_ERR_OK on success, anything else on fail
|
||||
*/
|
||||
static ModuleReturn DeleteModule(Module *m);
|
||||
|
||||
/** Get the version of Anope the module was compiled against
|
||||
* @return The version
|
||||
*/
|
||||
static ModuleVersion GetVersion(void *handle);
|
||||
};
|
||||
|
||||
#endif // MODULES_H
|
||||
|
||||
+16
-26
@@ -1,8 +1,6 @@
|
||||
#ifndef ANOPE_LDAP_H
|
||||
#define ANOPE_LDAP_H
|
||||
|
||||
typedef int LDAPQuery;
|
||||
|
||||
class LDAPException : public ModuleException
|
||||
{
|
||||
public:
|
||||
@@ -59,28 +57,26 @@ struct LDAPAttributes : public std::map<Anope::string, std::vector<Anope::string
|
||||
}
|
||||
};
|
||||
|
||||
enum QueryType
|
||||
{
|
||||
QUERY_UNKNOWN,
|
||||
QUERY_BIND,
|
||||
QUERY_SEARCH,
|
||||
QUERY_ADD,
|
||||
QUERY_DELETE,
|
||||
QUERY_MODIFY
|
||||
};
|
||||
|
||||
struct LDAPResult
|
||||
{
|
||||
std::vector<LDAPAttributes> messages;
|
||||
Anope::string error;
|
||||
|
||||
enum QueryType
|
||||
{
|
||||
QUERY_UNKNOWN,
|
||||
QUERY_BIND,
|
||||
QUERY_SEARCH,
|
||||
QUERY_ADD,
|
||||
QUERY_DELETE,
|
||||
QUERY_MODIFY
|
||||
};
|
||||
|
||||
QueryType type;
|
||||
LDAPQuery id;
|
||||
|
||||
LDAPResult()
|
||||
{
|
||||
this->type = QUERY_UNKNOWN;
|
||||
this->id = -1;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
@@ -126,48 +122,42 @@ class LDAPProvider : public Service
|
||||
|
||||
/** Attempt to bind to the LDAP server as an admin
|
||||
* @param i The LDAPInterface the result is sent to
|
||||
* @return The query ID
|
||||
*/
|
||||
virtual LDAPQuery BindAsAdmin(LDAPInterface *i) = 0;
|
||||
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
|
||||
* @return The query ID
|
||||
*/
|
||||
virtual LDAPQuery Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) = 0;
|
||||
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
|
||||
* @return The query ID
|
||||
*/
|
||||
virtual LDAPQuery Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) = 0;
|
||||
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
|
||||
* @return The query ID
|
||||
*/
|
||||
virtual LDAPQuery Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) = 0;
|
||||
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
|
||||
* @return The query ID
|
||||
*/
|
||||
virtual LDAPQuery Del(LDAPInterface *i, const Anope::string &dn) = 0;
|
||||
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
|
||||
* @return The query ID
|
||||
*/
|
||||
virtual LDAPQuery Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) = 0;
|
||||
virtual void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) = 0;
|
||||
};
|
||||
|
||||
#endif // ANOPE_LDAP_H
|
||||
|
||||
@@ -198,6 +198,11 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
|
||||
*/
|
||||
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
|
||||
|
||||
+3
-3
@@ -60,9 +60,9 @@ class CoreExport Serializable : public virtual Base
|
||||
* 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;
|
||||
private:
|
||||
/* Iterator into serializable_items */
|
||||
std::list<Serializable *>::iterator s_iter;
|
||||
/* The hash of the last serialized form of this object commited to the database */
|
||||
@@ -109,7 +109,7 @@ class CoreExport Serializable : public virtual Base
|
||||
* of class that inherits from Serialiable. Used for unserializing objects
|
||||
* of this type, as it requires a function pointer to a static member function.
|
||||
*/
|
||||
class CoreExport Serialize::Type
|
||||
class CoreExport Serialize::Type : public Base
|
||||
{
|
||||
typedef Serializable* (*unserialize_func)(Serializable *obj, Serialize::Data &);
|
||||
|
||||
@@ -188,7 +188,7 @@ class Serialize::Checker
|
||||
{
|
||||
Anope::string name;
|
||||
T obj;
|
||||
mutable Serialize::Type *type;
|
||||
mutable ::Reference<Serialize::Type> type;
|
||||
|
||||
inline void Check() const
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Uplink
|
||||
class UplinkSocket : public ConnectionSocket, public BufferedSocket
|
||||
{
|
||||
public:
|
||||
bool error;
|
||||
UplinkSocket();
|
||||
~UplinkSocket();
|
||||
bool ProcessRead() anope_override;
|
||||
|
||||
+87
-35
@@ -13,7 +13,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
static std::string get_git_hash(const std::string &git_dir)
|
||||
{
|
||||
@@ -45,29 +45,16 @@ static std::string get_git_hash(const std::string &git_dir)
|
||||
return "g" + filebuf.substr(0, 7);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static bool read_version_sh(const std::string &version_sh, std::map<std::string, std::string> &versions)
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
std::cerr << "Syntax: " << argv[0] << " <base> <version.h>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string version_sh = std::string(argv[1]) + "/src/version.sh";
|
||||
std::string git_dir = std::string(argv[1]) + "/.git";
|
||||
|
||||
std::fstream fd;
|
||||
|
||||
fd.clear();
|
||||
fd.open(version_sh.c_str(), std::ios::in);
|
||||
std::fstream fd(version_sh.c_str(), std::ios::in);
|
||||
if (!fd.is_open())
|
||||
{
|
||||
std::cerr << "Error: Unable to open src/version.sh for reading: " << version_sh << std::endl;
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string filebuf;
|
||||
std::list<std::pair<std::string, std::string> > versions;
|
||||
while (getline(fd, filebuf))
|
||||
{
|
||||
if (!filebuf.find("VERSION_"))
|
||||
@@ -75,24 +62,25 @@ int main(int argc, char *argv[])
|
||||
size_t eq = filebuf.find('=');
|
||||
|
||||
std::string type = filebuf.substr(0, eq);
|
||||
std::string value = filebuf.substr(eq + 2, filebuf.length() - eq - 3);
|
||||
versions.push_back(std::make_pair(type, value));
|
||||
std::string value = filebuf.substr(eq + 1);
|
||||
|
||||
versions[type] = value;
|
||||
}
|
||||
}
|
||||
|
||||
fd.close();
|
||||
|
||||
std::string git_version = get_git_hash(git_dir);
|
||||
if (!git_version.empty())
|
||||
versions.push_back(std::make_pair("VERSION_GIT", git_version));
|
||||
return true;
|
||||
}
|
||||
|
||||
fd.clear();
|
||||
fd.open(argv[2], std::ios::in);
|
||||
static bool write_build_h(const std::string &buildh, const std::string &git_version)
|
||||
{
|
||||
std::fstream fd(buildh.c_str(), std::ios::in);
|
||||
|
||||
std::string build = "#define BUILD 1";
|
||||
if (fd.is_open())
|
||||
{
|
||||
while (getline(fd, filebuf))
|
||||
for (std::string filebuf; getline(fd, filebuf);)
|
||||
{
|
||||
if (!filebuf.find("#define BUILD"))
|
||||
{
|
||||
@@ -110,27 +98,91 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
fd.clear();
|
||||
fd.open(argv[2], std::ios::out);
|
||||
|
||||
fd.open(buildh.c_str(), std::ios::out);
|
||||
if (!fd.is_open())
|
||||
{
|
||||
std::cerr << "Error: Unable to include/version.h for writing: " << argv[2] << std::endl;
|
||||
return 1;
|
||||
std::cerr << "Error: Unable to open build.h for writing: " << buildh << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
fd << "/* This file is automatically generated by version.cpp - do not edit it! */" << std::endl;
|
||||
fd << build << std::endl;
|
||||
if (!git_version.empty())
|
||||
fd << "#define VERSION_GIT \"" << git_version << "\"" << std::endl;
|
||||
fd.close();
|
||||
|
||||
for (std::list<std::pair<std::string, std::string> >::iterator it = versions.begin(), it_end = versions.end(); it != it_end; ++it)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void read_version_h(const std::string &versionh, std::map<std::string, std::string> &versions)
|
||||
{
|
||||
std::fstream fd(versionh.c_str(), std::ios::in);
|
||||
|
||||
if (!fd.is_open())
|
||||
return;
|
||||
|
||||
for (std::string filebuf; getline(fd, filebuf);)
|
||||
{
|
||||
if (it->first == "VERSION_EXTRA" || it->first == "VERSION_GIT")
|
||||
fd << "#define " << it->first << " \"" << it->second << "\"" << std::endl;
|
||||
else
|
||||
fd << "#define " << it->first << " " << it->second << std::endl;
|
||||
if (!filebuf.find("#define VERSION_"))
|
||||
{
|
||||
size_t space = filebuf.substr(8).find(' ');
|
||||
|
||||
std::string name = filebuf.substr(8).substr(0, space),
|
||||
version = filebuf.substr(8).substr(space + 1);
|
||||
|
||||
versions[name] = version;
|
||||
}
|
||||
}
|
||||
|
||||
fd << build << std::endl;
|
||||
fd.close();
|
||||
}
|
||||
|
||||
static bool write_version_h(const std::string &versionh, const std::map<std::string, std::string> &versions)
|
||||
{
|
||||
std::fstream fd(versionh.c_str(), std::ios::out);
|
||||
|
||||
if (!fd.is_open())
|
||||
return false;
|
||||
|
||||
for (std::map<std::string, std::string>::const_iterator it = versions.begin(); it != versions.end(); ++it)
|
||||
{
|
||||
fd << "#define " << it->first << " " << it->second << std::endl;
|
||||
}
|
||||
|
||||
fd.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 4)
|
||||
{
|
||||
std::cerr << "Syntax: " << argv[0] << " <base> <version.h> <build.h>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string version_sh = std::string(argv[1]) + "/src/version.sh";
|
||||
std::string git_dir = std::string(argv[1]) + "/.git";
|
||||
std::string versionh = argv[2];
|
||||
std::string buildh = argv[3];
|
||||
|
||||
std::map<std::string, std::string> versions, old_versions;
|
||||
|
||||
if (!read_version_sh(version_sh, versions))
|
||||
return -1;
|
||||
|
||||
std::string git_version = get_git_hash(git_dir);
|
||||
if (!write_build_h(buildh, git_version))
|
||||
return -1;
|
||||
|
||||
read_version_h(versionh, old_versions);
|
||||
|
||||
if (versions == old_versions)
|
||||
return 0;
|
||||
|
||||
if (!write_version_h(versionh, versions))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -11003,9 +11003,7 @@ msgstr "You are now an IRC Operator."
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
#, fuzzy
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"You are now identified for your nick. Change your password using \"/msg %s "
|
||||
"SET PASSWORD newpassword\" now."
|
||||
msgstr "You are now identified for your nick. Change your password now."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
@@ -6389,7 +6389,7 @@ msgstr "%s ist ein services operator vom Typ %s."
|
||||
#: modules/commands/ns_info.cpp:34
|
||||
#, c-format
|
||||
msgid "Nick %s is part of this Network's Services."
|
||||
msgstr "Der Nickname %s ist ein teil der Network Services."
|
||||
msgstr "Der Nickname %s ist ein Teil der Netzwerkdienste."
|
||||
|
||||
#: include/language.h:80
|
||||
#, fuzzy, c-format
|
||||
@@ -10693,9 +10693,7 @@ msgstr "Du bist jetzt ein IRC Operator."
|
||||
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"Du bist jetzt für deinen Nick angemeldet. Ändere jetzt dein Passwort mit \"/"
|
||||
"msg %s SET PASSWORD newpassword\" ."
|
||||
msgstr "Du bist jetzt für Deinen Nick angemeldet. Bitte ändere jetzt das Passwort."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
@@ -10917,7 +10917,7 @@ msgstr "Τώρα είστε IRC Operator."
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"Έχετε γίνει identify για το nick σας. Αλλάξτε τον κωδικό σας με την εντολή "
|
||||
"\"/msg %s SET PASSWORD #newpassword#\" τώρα."
|
||||
"\"/msg SET PASSWORD #newpassword#\" τώρα."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
+270
-279
File diff suppressed because it is too large
Load Diff
+1962
-1910
File diff suppressed because it is too large
Load Diff
@@ -10919,9 +10919,7 @@ msgstr "Most már IRC Operátor vagy!"
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
#, fuzzy
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"You are now identified for your nick. Change your password using \"/msg %s "
|
||||
"SET PASSWORD newpassword\" now."
|
||||
msgstr "You are now identified for your nick. Change your password now."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
@@ -4513,6 +4513,7 @@ msgstr ""
|
||||
"avranno l'accesso sul canale secondo le liste di accesso."
|
||||
|
||||
#: modules/commands/cs_set.cpp:944
|
||||
#, fuzzy, c-format
|
||||
msgid ""
|
||||
"Enables or disables signed kicks for a\n"
|
||||
"channel. When SIGNKICK is set, kicks issued with\n"
|
||||
@@ -10302,8 +10303,7 @@ msgstr "Ora sei un IRC Operator."
|
||||
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"Adesso sei identificato per il tuo nick. Cambia la tua password adesso."
|
||||
msgstr "Adesso sei identificato per il tuo nick. Cambia la tua password adesso."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
+557
-538
File diff suppressed because it is too large
Load Diff
@@ -10846,9 +10846,7 @@ msgstr "Jesteś teraz IRC operatorem."
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
#, fuzzy
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"You are now identified for your nick. Change your password using \"/msg %s "
|
||||
"SET PASSWORD newpassword\" now."
|
||||
msgstr "You are now identified for your nick. Change your password now."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
@@ -10872,7 +10872,7 @@ msgstr "Você agora é um Operador de IRC."
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
#, fuzzy
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr "You are now identified for your nick "
|
||||
msgstr "You are now identified for your nick. Change your password now."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
@@ -11155,9 +11155,7 @@ msgstr "Теперь вы IRC-оператор."
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
#, fuzzy
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"You are now identified for your nick. Change your password using \"/msg %s "
|
||||
"SET PASSWORD newpassword\" now."
|
||||
msgstr "You are now identified for your nick. Change your password now."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
@@ -10838,9 +10838,7 @@ msgstr "You are now an IRC Operator."
|
||||
#: modules/commands/ns_resetpass.cpp:108
|
||||
#, fuzzy
|
||||
msgid "You are now identified for your nick. Change your password now."
|
||||
msgstr ""
|
||||
"You are now identified for your nick. Change your password using \"/msg %s "
|
||||
"SET PASSWORD newpassword\" now."
|
||||
msgstr "You are now identified for your nick. Change your password now."
|
||||
|
||||
#: modules/commands/ns_group.cpp:50
|
||||
#, c-format
|
||||
|
||||
@@ -75,7 +75,7 @@ class CommandBSAssign : public Command
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Assigns a bot pointed out by nick to a channel. You\n"
|
||||
source.Reply(_("Assigns the specified bot to a channel. You\n"
|
||||
"can then configure the bot for the channel so it fits\n"
|
||||
"your needs."));
|
||||
return true;
|
||||
@@ -121,7 +121,7 @@ class CommandBSUnassign : public Command
|
||||
|
||||
if (ci->HasExt("PERSIST") && !ModeManager::FindChannelModeByName("PERM"))
|
||||
{
|
||||
source.Reply(_("You can not unassign bots while persist is set on the channel."));
|
||||
source.Reply(_("You cannot unassign bots while persist is set on the channel."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,9 +195,9 @@ class CommandBSSetNoBot : public Command
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(_(" \n"
|
||||
"This option makes a channel be unassignable. If a bot\n"
|
||||
"This option makes a channel unassignable. If a bot\n"
|
||||
"is already assigned to the channel, it is unassigned\n"
|
||||
"automatically when you enable the option."));
|
||||
"automatically when you enable it."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -138,7 +138,8 @@ Serializable* BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
bw->type = static_cast<BadWordType>(n);
|
||||
|
||||
BadWordsImpl *bws = ci->Require<BadWordsImpl>("badwords");
|
||||
bws->badwords->push_back(bw);
|
||||
if (!obj)
|
||||
bws->badwords->push_back(bw);
|
||||
|
||||
return bw;
|
||||
}
|
||||
@@ -400,7 +401,7 @@ class CommandBSBadwords : public Command
|
||||
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(_("Sorry, channel bad words list modification is temporarily disabled."));
|
||||
source.Reply(_("Sorry, bad words list modification is temporarily disabled."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -446,7 +447,7 @@ class CommandBSBadwords : public Command
|
||||
" Lists bad words entries numbered 2 through 5 and\n"
|
||||
" 7 through 9.\n"
|
||||
" \n"
|
||||
"The \002CLEAR\002 command clears all entries of the\n"
|
||||
"The \002CLEAR\002 command clears all entries from the\n"
|
||||
"bad words list."));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ class CommandBSBot : public Command
|
||||
*/
|
||||
if (nick.equals_cs(bi->nick) && (!user.empty() ? user.equals_cs(bi->GetIdent()) : 1) && (!host.empty() ? host.equals_cs(bi->host) : 1) && (!real.empty() ? real.equals_cs(bi->realname) : 1))
|
||||
{
|
||||
source.Reply(_("Old info is equal to the new one."));
|
||||
source.Reply(_("The old information is the same as the new information specified."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -341,13 +341,13 @@ class CommandBSBot : public Command
|
||||
"hostname and realname. Since no integrity checks are done\n"
|
||||
"for these settings, be really careful.\n"
|
||||
" \n"
|
||||
"\002BOT CHANGE\002 allows to change the nickname, username, hostname\n"
|
||||
"or realname of a bot without actually having to delete it (and\n"
|
||||
"\002BOT CHANGE\002 allows you to change the nickname, username, hostname\n"
|
||||
"or realname of a bot without deleting it (and\n"
|
||||
"all the data associated with it).\n"
|
||||
" \n"
|
||||
"\002BOT DEL\002 removes the given bot from the bot list.\n"
|
||||
" \n"
|
||||
"\002Note\002: you cannot create a bot that has a nick that is\n"
|
||||
"\002Note\002: You cannot create a bot with a nick that is\n"
|
||||
"currently registered. If an unregistered user is currently\n"
|
||||
"using the nick, they will be killed."));
|
||||
return true;
|
||||
|
||||
@@ -16,7 +16,7 @@ class CommandBSSay : public Command
|
||||
public:
|
||||
CommandBSSay(Module *creator) : Command(creator, "botserv/say", 2, 2)
|
||||
{
|
||||
this->SetDesc(_("Makes the bot say the given text on the given channel"));
|
||||
this->SetDesc(_("Makes the bot say the specified text on the specified channel"));
|
||||
this->SetSyntax(_("\037channel\037 \037text\037"));
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class CommandBSSay : public Command
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Makes the bot say the given text on the given channel."));
|
||||
source.Reply(_("Makes the bot say the specified text on the specified channel."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -125,7 +125,7 @@ class CommandBSAct : public Command
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Makes the bot do the equivalent of a \"/me\" command\n"
|
||||
"on the given channel using the given text."));
|
||||
"on the specified channel using the specified text."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -230,12 +230,12 @@ class CommandBSKickBase : public Command
|
||||
source.Reply(_("Bot will now kick for \002%s\002."), optname.c_str());
|
||||
|
||||
bool override = !source.AccessFor(ci).HasPriv("SET");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable the " << optname << "kicker";
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable the " << optname << " kicker";
|
||||
}
|
||||
else if (param.equals_ci("OFF"))
|
||||
{
|
||||
bool override = !source.AccessFor(ci).HasPriv("SET");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << "kicker";
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << " kicker";
|
||||
|
||||
val = false;
|
||||
source.Reply(_("Bot won't kick for \002%s\002 anymore."), optname.c_str());
|
||||
@@ -514,7 +514,7 @@ class CommandBSKickFlood : public CommandBSKickBase
|
||||
try
|
||||
{
|
||||
i = convertTo<int16_t>(ttb);
|
||||
if (i < 1)
|
||||
if (i < 0)
|
||||
throw ConvertException();
|
||||
}
|
||||
catch (const ConvertException &)
|
||||
|
||||
@@ -32,6 +32,8 @@ class CommandBSSet : public Command
|
||||
source.Reply(_("Configures bot options.\n"
|
||||
" \n"
|
||||
"Available options:"));
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
|
||||
Anope::string this_name = source.command;
|
||||
for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
|
||||
{
|
||||
@@ -42,6 +44,13 @@ class CommandBSSet : public Command
|
||||
ServiceReference<Command> command("Command", info.name);
|
||||
if (command)
|
||||
{
|
||||
// XXX dup
|
||||
if (hide_registered_commands && !command->AllowUnregistered() && !source.GetAccount())
|
||||
continue;
|
||||
|
||||
if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
|
||||
continue;
|
||||
|
||||
source.command = it->first;
|
||||
command->OnServHelp(source);
|
||||
}
|
||||
@@ -100,7 +109,7 @@ class CommandBSSetBanExpire : public Command
|
||||
|
||||
if (Anope::ReadOnly)
|
||||
{
|
||||
source.Reply(_("Sorry, bot option setting is temporarily disabled."));
|
||||
source.Reply(_("Sorry, changing bot options is temporarily disabled."));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ class CommandCSAccess : public Command
|
||||
tmp_access.level = level;
|
||||
|
||||
bool override = false;
|
||||
const NickAlias *na = NULL;
|
||||
|
||||
if ((!highest || *highest <= tmp_access) && !u_access.founder)
|
||||
{
|
||||
@@ -158,7 +159,8 @@ class CommandCSAccess : public Command
|
||||
}
|
||||
else
|
||||
{
|
||||
const NickAlias *na = NickAlias::Find(mask);
|
||||
na = NickAlias::Find(mask);
|
||||
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
@@ -175,12 +177,15 @@ class CommandCSAccess : public Command
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (na)
|
||||
mask = na->nick;
|
||||
}
|
||||
|
||||
for (unsigned i = ci->GetAccessCount(); i > 0; --i)
|
||||
{
|
||||
const ChanAccess *access = ci->GetAccess(i - 1);
|
||||
if (mask.equals_ci(access->Mask()))
|
||||
if ((na && na->nc == access->GetAccount()) || mask.equals_ci(access->Mask()))
|
||||
{
|
||||
/* Don't allow lowering from a level >= u_level */
|
||||
if ((!highest || *access >= *highest) && !u_access.founder && !source.HasPriv("chanserv/access/modify"))
|
||||
@@ -518,6 +523,8 @@ class CommandCSAccess : public Command
|
||||
bool has_access = false;
|
||||
if (source.HasPriv("chanserv/access/modify"))
|
||||
has_access = true;
|
||||
else if (is_list && source.HasPriv("chanserv/access/list"))
|
||||
has_access = true;
|
||||
else if (is_list && source.AccessFor(ci).HasPriv("ACCESS_LIST"))
|
||||
has_access = true;
|
||||
else if (source.AccessFor(ci).HasPriv("ACCESS_CHANGE"))
|
||||
|
||||
@@ -71,10 +71,10 @@ class CommandCSAKick : public Command
|
||||
/* Check excepts BEFORE we get this far */
|
||||
if (ci->c)
|
||||
{
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> modes = ci->c->GetModeList("EXCEPT");
|
||||
for (; modes.first != modes.second; ++modes.first)
|
||||
std::vector<Anope::string> modes = ci->c->GetModeList("EXCEPT");
|
||||
for (unsigned int i = 0; i < modes.size(); ++i)
|
||||
{
|
||||
if (Anope::Match(modes.first->second, mask))
|
||||
if (Anope::Match(modes[i], mask))
|
||||
{
|
||||
source.Reply(CHAN_EXCEPTED, mask.c_str(), ci->name.c_str());
|
||||
return;
|
||||
@@ -441,9 +441,17 @@ class CommandCSAKick : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_list = cmd.equals_ci("LIST") || cmd.equals_ci("VIEW");
|
||||
|
||||
bool has_access = false;
|
||||
if (source.AccessFor(ci).HasPriv("AKICK") || source.HasPriv("chanserv/access/modify"))
|
||||
has_access = true;
|
||||
else if (is_list && source.HasPriv("chanserv/access/list"))
|
||||
has_access = true;
|
||||
|
||||
if (mask.empty() && (cmd.equals_ci("ADD") || cmd.equals_ci("DEL")))
|
||||
this->OnSyntaxError(source, cmd);
|
||||
else if (!source.AccessFor(ci).HasPriv("AKICK") && !source.HasPriv("chanserv/access/modify"))
|
||||
else if (!has_access)
|
||||
source.Reply(ACCESS_DENIED);
|
||||
else if (!cmd.equals_ci("LIST") && !cmd.equals_ci("VIEW") && !cmd.equals_ci("ENFORCE") && Anope::ReadOnly)
|
||||
source.Reply(_("Sorry, channel autokick list modification is temporarily disabled."));
|
||||
|
||||
+25
-11
@@ -101,6 +101,9 @@ class CommandCSBan : public Command
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
|
||||
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
|
||||
|
||||
User *u = source.GetUser();
|
||||
User *u2 = User::Find(target, true);
|
||||
|
||||
@@ -146,7 +149,10 @@ class CommandCSBan : public Command
|
||||
if (block->Get<bool>("kick", "yes"))
|
||||
{
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
|
||||
{
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
|
||||
}
|
||||
else
|
||||
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
|
||||
}
|
||||
@@ -156,15 +162,18 @@ class CommandCSBan : public Command
|
||||
{
|
||||
bool founder = u_access.HasPriv("FOUNDER");
|
||||
bool override = !founder && !u_access.HasPriv("BAN");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << target;
|
||||
|
||||
if (!c->HasMode(mode, target))
|
||||
Anope::string mask = IRCD->NormalizeMask(target);
|
||||
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << mask;
|
||||
|
||||
if (!c->HasMode(mode, mask))
|
||||
{
|
||||
c->SetMode(NULL, mode, target);
|
||||
c->SetMode(NULL, mode, mask);
|
||||
if (ban_time)
|
||||
{
|
||||
new TempBan(ban_time, c, target, mode);
|
||||
source.Reply(_("Ban on \002%s\002 expires in %s."), target.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
|
||||
new TempBan(ban_time, c, mask, mode);
|
||||
source.Reply(_("Ban on \002%s\002 expires in %s."), mask.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +183,8 @@ class CommandCSBan : public Command
|
||||
ChanUserContainer *uc = it->second;
|
||||
++it;
|
||||
|
||||
if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
|
||||
Entry e(mode, mask);
|
||||
if (e.Matches(uc->user))
|
||||
{
|
||||
++matched;
|
||||
|
||||
@@ -193,17 +203,21 @@ class CommandCSBan : public Command
|
||||
{
|
||||
++kicked;
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
|
||||
{
|
||||
reason += " (Matches " + mask + ")";
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
|
||||
}
|
||||
else
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matched)
|
||||
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
|
||||
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, mask.c_str(), c->name.c_str());
|
||||
else
|
||||
source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
|
||||
source.Reply(_("No users on %s match %s."), c->name.c_str(), mask.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+115
-67
@@ -14,6 +14,100 @@
|
||||
|
||||
class CommandCSClone : public Command
|
||||
{
|
||||
void CopySetting(ChannelInfo *ci, ChannelInfo *target_ci, const Anope::string &setting)
|
||||
{
|
||||
if (ci->HasExt(setting))
|
||||
target_ci->Extend<bool>(setting);
|
||||
}
|
||||
|
||||
void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
|
||||
{
|
||||
std::set<Anope::string> masks;
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
|
||||
unsigned count = 0;
|
||||
|
||||
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
|
||||
masks.insert(target_ci->GetAccess(i)->Mask());
|
||||
|
||||
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
|
||||
{
|
||||
const ChanAccess *taccess = ci->GetAccess(i);
|
||||
AccessProvider *provider = taccess->provider;
|
||||
|
||||
if (access_max && target_ci->GetDeepAccessCount() >= access_max)
|
||||
break;
|
||||
|
||||
if (masks.count(taccess->Mask()))
|
||||
continue;
|
||||
masks.insert(taccess->Mask());
|
||||
|
||||
ChanAccess *newaccess = provider->Create();
|
||||
newaccess->SetMask(taccess->Mask(), target_ci);
|
||||
newaccess->creator = taccess->creator;
|
||||
newaccess->last_seen = taccess->last_seen;
|
||||
newaccess->created = taccess->created;
|
||||
newaccess->AccessUnserialize(taccess->AccessSerialize());
|
||||
|
||||
target_ci->AddAccess(newaccess);
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, ci->name.c_str(), target_ci->name.c_str());
|
||||
}
|
||||
|
||||
void CopyAkick(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
|
||||
{
|
||||
target_ci->ClearAkick();
|
||||
for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
|
||||
{
|
||||
const AutoKick *akick = ci->GetAkick(i);
|
||||
if (akick->nc)
|
||||
target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used);
|
||||
else
|
||||
target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used);
|
||||
}
|
||||
|
||||
source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
|
||||
}
|
||||
|
||||
void CopyBadwords(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
|
||||
{
|
||||
BadWords *target_badwords = target_ci->Require<BadWords>("badwords"),
|
||||
*badwords = ci->Require<BadWords>("badwords");
|
||||
|
||||
if (!target_badwords || !badwords)
|
||||
{
|
||||
source.Reply(ACCESS_DENIED); // BotServ doesn't exist/badwords isn't loaded
|
||||
return;
|
||||
}
|
||||
|
||||
target_badwords->ClearBadWords();
|
||||
|
||||
for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
|
||||
{
|
||||
const BadWord *bw = badwords->GetBadWord(i);
|
||||
target_badwords->AddBadWord(bw->word, bw->type);
|
||||
}
|
||||
|
||||
badwords->Check();
|
||||
target_badwords->Check();
|
||||
|
||||
source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
|
||||
}
|
||||
|
||||
void CopyLevels(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
|
||||
{
|
||||
const Anope::map<int16_t> &cilevels = ci->GetLevelEntries();
|
||||
|
||||
for (Anope::map<int16_t>::const_iterator it = cilevels.begin(); it != cilevels.end(); ++it)
|
||||
{
|
||||
target_ci->SetLevel(it->first, it->second);
|
||||
}
|
||||
|
||||
source.Reply(_("All level entries from \002%s\002 have been cloned into \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
|
||||
}
|
||||
|
||||
public:
|
||||
CommandCSClone(Module *creator) : Command(creator, "chanserv/clone", 2, 3)
|
||||
{
|
||||
@@ -100,82 +194,36 @@ public:
|
||||
else
|
||||
target_ci->last_topic_setter = source.service->nick;
|
||||
|
||||
const Anope::string settings[] = { "NOAUTOOP", "CS_KEEP_MODES", "PEACE", "PERSIST", "RESTRICTED",
|
||||
"CS_SECURE", "SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" };
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(settings) / sizeof(Anope::string); ++i)
|
||||
CopySetting(ci, target_ci, settings[i]);
|
||||
|
||||
CopyAccess(source, ci, target_ci);
|
||||
CopyAkick(source, ci, target_ci);
|
||||
CopyBadwords(source, ci, target_ci);
|
||||
CopyLevels(source, ci, target_ci);
|
||||
|
||||
FOREACH_MOD(OnChanRegistered, (target_ci));
|
||||
|
||||
source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
|
||||
source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
|
||||
}
|
||||
else if (what.equals_ci("ACCESS"))
|
||||
{
|
||||
std::set<Anope::string> masks;
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
|
||||
unsigned count = 0;
|
||||
|
||||
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
|
||||
masks.insert(target_ci->GetAccess(i)->Mask());
|
||||
|
||||
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
|
||||
{
|
||||
const ChanAccess *taccess = ci->GetAccess(i);
|
||||
AccessProvider *provider = taccess->provider;
|
||||
|
||||
if (access_max && target_ci->GetDeepAccessCount() >= access_max)
|
||||
break;
|
||||
|
||||
if (masks.count(taccess->Mask()))
|
||||
continue;
|
||||
masks.insert(taccess->Mask());
|
||||
|
||||
ChanAccess *newaccess = provider->Create();
|
||||
newaccess->SetMask(taccess->Mask(), target_ci);
|
||||
newaccess->creator = taccess->creator;
|
||||
newaccess->last_seen = taccess->last_seen;
|
||||
newaccess->created = taccess->created;
|
||||
newaccess->AccessUnserialize(taccess->AccessSerialize());
|
||||
|
||||
target_ci->AddAccess(newaccess);
|
||||
|
||||
++count;
|
||||
}
|
||||
|
||||
source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, channel.c_str(), target.c_str());
|
||||
CopyAccess(source, ci, target_ci);
|
||||
}
|
||||
else if (what.equals_ci("AKICK"))
|
||||
{
|
||||
target_ci->ClearAkick();
|
||||
for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
|
||||
{
|
||||
const AutoKick *akick = ci->GetAkick(i);
|
||||
if (akick->nc)
|
||||
target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used);
|
||||
else
|
||||
target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used);
|
||||
}
|
||||
|
||||
source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
|
||||
CopyAkick(source, ci, target_ci);
|
||||
}
|
||||
else if (what.equals_ci("BADWORDS"))
|
||||
{
|
||||
BadWords *target_badwords = target_ci->Require<BadWords>("badwords"),
|
||||
*badwords = ci->Require<BadWords>("badwords");
|
||||
|
||||
if (!target_badwords || !badwords)
|
||||
{
|
||||
source.Reply(ACCESS_DENIED); // BotServ doesn't exist/badwords isn't loaded
|
||||
return;
|
||||
}
|
||||
|
||||
target_badwords->ClearBadWords();
|
||||
|
||||
for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
|
||||
{
|
||||
const BadWord *bw = badwords->GetBadWord(i);
|
||||
target_badwords->AddBadWord(bw->word, bw->type);
|
||||
}
|
||||
|
||||
badwords->Check();
|
||||
target_badwords->Check();
|
||||
|
||||
source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
|
||||
CopyBadwords(source, ci, target_ci);
|
||||
}
|
||||
else if (what.equals_ci("LEVELS"))
|
||||
{
|
||||
CopyLevels(source, ci, target_ci);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -191,8 +239,8 @@ public:
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Copies all settings, access, akicks, etc from \002channel\002 to the\n"
|
||||
"\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, or \002BADWORDS\002\n"
|
||||
"then only the respective settings are cloned.\n"
|
||||
"\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, \002BADWORDS\002,\n"
|
||||
"or \002LEVELS\002 then only the respective settings are cloned.\n"
|
||||
"You must be the founder of \037channel\037 and \037target\037."));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -71,8 +71,8 @@ class CommandCSDrop : public Command
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
if (source.IsServicesOper())
|
||||
source.Reply(_("Unregisters the named channel. Only \002Services Operators\002\n"
|
||||
"can drop a channel of which they are not the founder."));
|
||||
source.Reply(_("Unregisters the specified channel. Only \002Services Operators\002\n"
|
||||
"can drop a channel of which they are not the founder of."));
|
||||
else
|
||||
source.Reply(_("Unregisters the named channel. Can only be used by\n"
|
||||
"the \002channel founder\002."));
|
||||
|
||||
@@ -143,7 +143,7 @@ class CommandEntryMessage : public Command
|
||||
else
|
||||
{
|
||||
(*messages)->push_back(new EntryMsgImpl(ci, source.GetNick(), message));
|
||||
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to add a message";
|
||||
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to add a message";
|
||||
source.Reply(_("Entry message added to \002%s\002"), ci->name.c_str());
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ class CommandEntryMessage : public Command
|
||||
delete (*messages)->at(i - 1);
|
||||
if ((*messages)->empty())
|
||||
ci->Shrink<EntryMessageList>("entrymsg");
|
||||
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
|
||||
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
|
||||
source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
|
||||
}
|
||||
else
|
||||
@@ -183,7 +183,7 @@ class CommandEntryMessage : public Command
|
||||
{
|
||||
ci->Shrink<EntryMessageList>("entrymsg");
|
||||
|
||||
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
|
||||
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
|
||||
source.Reply(_("Entry messages for \002%s\002 have been cleared."), ci->name.c_str());
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ class CommandEntryMessage : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
if (!source.IsFounder(ci) && !source.HasPriv("chanserv/administration"))
|
||||
if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("chanserv/administration"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
@@ -239,20 +239,23 @@ class CommandEntryMessage : public Command
|
||||
source.Reply(_("Controls what messages will be sent to users when they join the channel."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG ADD\002 command adds the given message to\n"
|
||||
"the list of messages to be shown to users when they join\n"
|
||||
"the list of messages shown to users when they join\n"
|
||||
"the channel."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG DEL\002 command removes the given message from\n"
|
||||
"the list of messages to be shown to users when they join\n"
|
||||
"the channel. You can remove the message by specifying its number\n"
|
||||
source.Reply(_("The \002ENTRYMSG DEL\002 command removes the specified message from\n"
|
||||
"the list of messages shown to users when they join\n"
|
||||
"the channel. You can remove a message by specifying its number\n"
|
||||
"which you can get by listing the messages as explained below."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG LIST\002 command displays a listing of messages\n"
|
||||
"to be shown to users when they join the channel."));
|
||||
"shown to users when they join the channel."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002ENTRYMSG CLEAR\002 command clears all entries from\n"
|
||||
"the list of messages to be shown to users when they join\n"
|
||||
"the list of messages shown to users when they join\n"
|
||||
"the channel, effectively disabling entry messages."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Adding, deleting, or clearing entry messages requires the\n"
|
||||
"SET permission."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -78,11 +78,8 @@ FlagsAccessProvider* FlagsAccessProvider::ap;
|
||||
|
||||
class CommandCSFlags : public Command
|
||||
{
|
||||
void DoModify(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags)
|
||||
{
|
||||
Anope::string mask = params.size() > 2 ? params[2] : "";
|
||||
Anope::string flags = params.size() > 3 ? params[3] : "";
|
||||
|
||||
if (flags.empty())
|
||||
{
|
||||
this->OnSyntaxError(source, "");
|
||||
@@ -91,6 +88,7 @@ class CommandCSFlags : public Command
|
||||
|
||||
AccessGroup u_access = source.AccessFor(ci);
|
||||
const ChanAccess *highest = u_access.Highest();
|
||||
const NickAlias *na = NULL;
|
||||
|
||||
if (IRCD->IsChannelValid(mask))
|
||||
{
|
||||
@@ -116,7 +114,7 @@ class CommandCSFlags : public Command
|
||||
}
|
||||
else
|
||||
{
|
||||
const NickAlias *na = NickAlias::Find(mask);
|
||||
na = NickAlias::Find(mask);
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
@@ -133,6 +131,9 @@ class CommandCSFlags : public Command
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (na)
|
||||
mask = na->nick;
|
||||
}
|
||||
|
||||
ChanAccess *current = NULL;
|
||||
@@ -142,7 +143,7 @@ class CommandCSFlags : public Command
|
||||
for (current_idx = ci->GetAccessCount(); current_idx > 0; --current_idx)
|
||||
{
|
||||
ChanAccess *access = ci->GetAccess(current_idx - 1);
|
||||
if (mask.equals_ci(access->Mask()))
|
||||
if ((na && na->nc == access->GetAccount()) || mask.equals_ci(access->Mask()))
|
||||
{
|
||||
// Flags allows removing others that have the same access as you,
|
||||
// but no other access system does.
|
||||
@@ -227,7 +228,7 @@ class CommandCSFlags : public Command
|
||||
override = true;
|
||||
else
|
||||
{
|
||||
source.Reply(_("You can not set the \002%c\002 flag."), f);
|
||||
source.Reply(_("You cannot set the \002%c\002 flag."), f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -370,7 +371,7 @@ class CommandCSFlags : public Command
|
||||
CommandCSFlags(Module *creator) : Command(creator, "chanserv/flags", 1, 4)
|
||||
{
|
||||
this->SetDesc(_("Modify the list of privileged users"));
|
||||
this->SetSyntax(_("\037channel\037 MODIFY \037mask\037 \037changes\037"));
|
||||
this->SetSyntax(_("\037channel\037 [MODIFY] \037mask\037 \037changes\037"));
|
||||
this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | +\037flags\037]"));
|
||||
this->SetSyntax(_("\037channel\037 CLEAR"));
|
||||
}
|
||||
@@ -391,6 +392,8 @@ class CommandCSFlags : public Command
|
||||
bool has_access = false;
|
||||
if (source.HasPriv("chanserv/access/modify"))
|
||||
has_access = true;
|
||||
else if (is_list && source.HasPriv("chanserv/access/list"))
|
||||
has_access = true;
|
||||
else if (is_list && source.AccessFor(ci).HasPriv("ACCESS_LIST"))
|
||||
has_access = true;
|
||||
else if (source.AccessFor(ci).HasPriv("ACCESS_CHANGE"))
|
||||
@@ -400,14 +403,26 @@ class CommandCSFlags : public Command
|
||||
source.Reply(ACCESS_DENIED);
|
||||
else if (Anope::ReadOnly && !is_list)
|
||||
source.Reply(_("Sorry, channel access list modification is temporarily disabled."));
|
||||
else if (cmd.equals_ci("MODIFY"))
|
||||
this->DoModify(source, ci, params);
|
||||
else if (is_list)
|
||||
this->DoList(source, ci, params);
|
||||
else if (cmd.equals_ci("CLEAR"))
|
||||
this->DoClear(source, ci);
|
||||
else
|
||||
this->OnSyntaxError(source, cmd);
|
||||
{
|
||||
Anope::string mask, flags;
|
||||
if (cmd.equals_ci("MODIFY"))
|
||||
{
|
||||
mask = params.size() > 2 ? params[2] : "";
|
||||
flags = params.size() > 3 ? params[3] : "";
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = cmd;
|
||||
flags = params.size() > 2 ? params[2] : "";
|
||||
}
|
||||
|
||||
this->DoModify(source, ci, mask, flags);
|
||||
}
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
|
||||
@@ -417,19 +432,19 @@ class CommandCSFlags : public Command
|
||||
source.Reply(_("%s is another way to modify the channel access list, similar to\n"
|
||||
"the XOP and ACCESS methods."), source.command.c_str());
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002MODIFY\002 command allows you to modify the access list. If mask is\n"
|
||||
"not already on the access list is it added, then the changes are applied.\n"
|
||||
source.Reply(_("The \002MODIFY\002 command allows you to modify the access list. If the mask is\n"
|
||||
"not already on the access list it is added, then the changes are applied.\n"
|
||||
"If the mask has no more flags, then the mask is removed from the access list.\n"
|
||||
"Additionally, you may use +* or -* to add or remove all flags, respectively. You are\n"
|
||||
"only able to modify the access list if you have the proper permission on the channel,\n"
|
||||
"and even then you can only give other people access to up what you already have."));
|
||||
"and even then you can only give other people access to the equivalent of what your access is."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002LIST\002 command allows you to list existing entries on the channel access list.\n"
|
||||
"If a mask is given, the mask is wildcard matched against all existing entries on the\n"
|
||||
"access list, and only those entries are returned. If a set of flags is given, only those\n"
|
||||
"on the access list with the specified flags are returned."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002CLEAR\002 command clears the channel access list, which requires channel founder."));
|
||||
source.Reply(_("The \002CLEAR\002 command clears the channel access list. This requires channel founder access."));
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The available flags are:"));
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class CommandCSInfo : public Command
|
||||
public:
|
||||
CommandCSInfo(Module *creator) : Command(creator, "chanserv/info", 1, 2)
|
||||
{
|
||||
this->SetDesc(_("Lists information about the named registered channel"));
|
||||
this->SetDesc(_("Lists information about the specified registered channel"));
|
||||
this->SetSyntax(_("\037channel\037"));
|
||||
this->AllowUnregistered(true);
|
||||
}
|
||||
@@ -73,12 +73,12 @@ class CommandCSInfo : public Command
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Lists information about the named registered channel,\n"
|
||||
"including its founder, time of registration, and last\n"
|
||||
"time used. If the user issuing the command has the\n"
|
||||
"appropriate access for it, then the description, successor,\n"
|
||||
"last topic set, settings and expiration time will also\n"
|
||||
"be displayed when applicable."));
|
||||
source.Reply(_("Lists information about the specified registered channel,\n"
|
||||
"including its founder, time of registration, last\n"
|
||||
"time used, and description. If the user issuing the\n"
|
||||
"command has the appropriate access for it, then the\n"
|
||||
"successor, last topic set, settings and expiration\n"
|
||||
"time will also be displayed when applicable."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +91,7 @@ class CommandCSInvite : public Command
|
||||
source.Reply(_("Tells %s to invite you or an optionally specified\n"
|
||||
"nick into the given channel.\n"
|
||||
" \n"
|
||||
"By default, limited to AOPs or those with level 5 and above\n"
|
||||
"By default, limited to AOPs or those with level 5 access and above\n"
|
||||
"on the channel."), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ class CommandCSKick : public Command
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
|
||||
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
|
||||
|
||||
AccessGroup u_access = source.AccessFor(ci);
|
||||
|
||||
if (!u_access.HasPriv("KICK") && !source.HasPriv("chanserv/kick"))
|
||||
@@ -66,14 +69,19 @@ class CommandCSKick : public Command
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick;
|
||||
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
|
||||
{
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
|
||||
}
|
||||
else
|
||||
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
|
||||
}
|
||||
}
|
||||
else if (u_access.HasPriv("FOUNDER"))
|
||||
{
|
||||
Log(LOG_COMMAND, source, this, ci) << "for " << target;
|
||||
Anope::string mask = IRCD->NormalizeMask(target);
|
||||
|
||||
Log(LOG_COMMAND, source, this, ci) << "for " << mask;
|
||||
|
||||
int matched = 0, kicked = 0;
|
||||
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;)
|
||||
@@ -81,7 +89,8 @@ class CommandCSKick : public Command
|
||||
ChanUserContainer *uc = it->second;
|
||||
++it;
|
||||
|
||||
if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
|
||||
Entry e("", mask);
|
||||
if (e.Matches(uc->user))
|
||||
{
|
||||
++matched;
|
||||
|
||||
@@ -93,16 +102,20 @@ class CommandCSKick : public Command
|
||||
|
||||
++kicked;
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
|
||||
{
|
||||
reason += " (Matches " + mask + ")";
|
||||
signkickformat = signkickformat.replace_all_cs("%m", reason);
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
|
||||
}
|
||||
else
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (matched)
|
||||
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
|
||||
source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, mask.c_str(), c->name.c_str());
|
||||
else
|
||||
source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
|
||||
source.Reply(_("No users on %s match %s."), c->name.c_str(), mask.c_str());
|
||||
}
|
||||
else
|
||||
source.Reply(NICK_X_NOT_IN_USE, target.c_str());
|
||||
@@ -115,7 +128,7 @@ class CommandCSKick : public Command
|
||||
source.Reply(_("Kicks a specified nick from a channel.\n"
|
||||
" \n"
|
||||
"By default, limited to AOPs or those with level 5 access\n"
|
||||
"and above on the channel. Channel founders may use masks too."));
|
||||
"and above on the channel. Channel founders can also specify masks."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -271,7 +271,7 @@ public:
|
||||
"To remove a logging method use the same syntax as you would to add it.\n"
|
||||
" \n"
|
||||
"Example:\n"
|
||||
" %s #anope chanserv/access MESSAGE @%\n"
|
||||
" %s #anope chanserv/access MESSAGE @\n"
|
||||
" Would message any channel operators whenever someone used the\n"
|
||||
" ACCESS command on ChanServ on the channel."),
|
||||
source.command.upper().c_str(), source.command.upper().c_str());
|
||||
|
||||
@@ -327,6 +327,8 @@ class CommandCSMode : public Command
|
||||
source.Reply(_("Missing parameter for mode %c."), cm->mchar);
|
||||
else if (cm->type == MODE_LIST && ci->c && IRCD->GetMaxListFor(ci->c) && ci->c->HasMode(cm->name) >= IRCD->GetMaxListFor(ci->c))
|
||||
source.Reply(_("List for mode %c is full."), cm->mchar);
|
||||
else if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32"))
|
||||
source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str());
|
||||
else
|
||||
{
|
||||
modelocks->SetMLock(cm, adding, mode_param, source.GetNick());
|
||||
@@ -485,7 +487,7 @@ class CommandCSMode : public Command
|
||||
case '*':
|
||||
if (adding == -1 || !has_access)
|
||||
break;
|
||||
for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j)
|
||||
for (unsigned j = 0; j < ModeManager::GetChannelModes().size() && ci->c; ++j)
|
||||
{
|
||||
ChannelMode *cm = ModeManager::GetChannelModes()[j];
|
||||
|
||||
@@ -613,15 +615,10 @@ class CommandCSMode : public Command
|
||||
}
|
||||
else
|
||||
{
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = ci->c->GetModeList(cm->name);
|
||||
for (; its.first != its.second;)
|
||||
{
|
||||
const Anope::string &mask = its.first->second;
|
||||
++its.first;
|
||||
|
||||
if (Anope::Match(mask, param))
|
||||
ci->c->RemoveMode(NULL, cm, mask);
|
||||
}
|
||||
std::vector<Anope::string> v = ci->c->GetModeList(cm->name);
|
||||
for (unsigned j = 0; j < v.size(); ++j)
|
||||
if (Anope::Match(v[j], param))
|
||||
ci->c->RemoveMode(NULL, cm, v[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -961,16 +958,40 @@ class CSMode : public Module
|
||||
for (unsigned i = 0; i < mlock.length(); ++i)
|
||||
{
|
||||
if (mlock[i] == '+')
|
||||
add = true;
|
||||
else if (mlock[i] == '-')
|
||||
add = false;
|
||||
else
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]);
|
||||
Anope::string param;
|
||||
if (cm && (cm->type == MODE_REGULAR || sep.GetToken(param)))
|
||||
ml->SetMLock(cm, add, param);
|
||||
add = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mlock[i] == '-')
|
||||
{
|
||||
add = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]);
|
||||
if (!cm)
|
||||
continue;
|
||||
|
||||
Anope::string param;
|
||||
if (cm->type == MODE_PARAM)
|
||||
{
|
||||
ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
|
||||
if (add || !cmp->minus_no_arg)
|
||||
{
|
||||
sep.GetToken(param);
|
||||
if (param.empty() || !cmp->IsValid(param))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (cm->type != MODE_REGULAR)
|
||||
{
|
||||
sep.GetToken(param);
|
||||
if (param.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
ml->SetMLock(cm, add, param);
|
||||
}
|
||||
}
|
||||
ml->Check();
|
||||
|
||||
@@ -45,7 +45,7 @@ class CommandCSRegister : public Command
|
||||
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
|
||||
else if (ci)
|
||||
source.Reply(_("Channel \002%s\002 is already registered!"), chan.c_str());
|
||||
else if (c && !c->HasUserStatus(u, "OP"))
|
||||
else if (c && u && !c->HasUserStatus(u, "OP"))
|
||||
source.Reply(_("You must be a channel operator to register the channel."));
|
||||
else if (maxregistered && nc->channelcount >= maxregistered && !source.HasPriv("chanserv/no-register-limit"))
|
||||
source.Reply(nc->channelcount > maxregistered ? CHAN_EXCEEDED_CHANNEL_LIMIT : CHAN_REACHED_CHANNEL_LIMIT, maxregistered);
|
||||
@@ -67,6 +67,8 @@ class CommandCSRegister : public Command
|
||||
Log(LOG_COMMAND, source, this, ci);
|
||||
source.Reply(_("Channel \002%s\002 registered under your account: %s"), chan.c_str(), nc->display.c_str());
|
||||
|
||||
FOREACH_MOD(OnChanRegistered, (ci));
|
||||
|
||||
/* Implement new mode lock */
|
||||
if (c)
|
||||
{
|
||||
@@ -74,8 +76,6 @@ class CommandCSRegister : public Command
|
||||
if (u)
|
||||
c->SetCorrectModes(u, true);
|
||||
}
|
||||
|
||||
FOREACH_MOD(OnChanRegistered, (ci));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ class CommandOSSeen : public Command
|
||||
source.Reply(" ");
|
||||
source.Reply(_("The \002STATS\002 command prints out statistics about stored nicks and memory usage."));
|
||||
source.Reply(_("The \002CLEAR\002 command lets you clean the database by removing all entries from the\n"
|
||||
"entries from the database that were added within \037time\037.\n"
|
||||
"database that were added within \037time\037.\n"
|
||||
" \n"
|
||||
"Example:\n"
|
||||
" %s CLEAR 30m\n"
|
||||
|
||||
@@ -35,7 +35,8 @@ class CommandCSSet : public Command
|
||||
" \n"
|
||||
"Available options:"));
|
||||
Anope::string this_name = source.command;
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands");
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
|
||||
for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
|
||||
{
|
||||
const Anope::string &c_name = it->first;
|
||||
@@ -44,13 +45,12 @@ class CommandCSSet : public Command
|
||||
{
|
||||
ServiceReference<Command> c("Command", info.name);
|
||||
|
||||
// XXX dup
|
||||
if (!c)
|
||||
continue;
|
||||
else if (!hide_privileged_commands)
|
||||
; // Always show with hide_privileged_commands disabled
|
||||
else if (!c->AllowUnregistered() && !source.GetAccount())
|
||||
else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
|
||||
continue;
|
||||
else if (!info.permission.empty() && !source.HasCommand(info.permission))
|
||||
else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
|
||||
continue;
|
||||
|
||||
source.command = it->first;
|
||||
@@ -1010,7 +1010,7 @@ class CommandCSSetSuccessor : public Command
|
||||
else
|
||||
nc = NULL;
|
||||
|
||||
Log(!source.permission.empty() ? LOG_ADMIN : LOG_COMMAND, source, this, ci) << "to change the successor from " << (ci->GetSuccessor() ? ci->GetSuccessor()->display : "(none)") << " to " << (nc ? nc->display : "(none)");
|
||||
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the successor from " << (ci->GetSuccessor() ? ci->GetSuccessor()->display : "(none)") << " to " << (nc ? nc->display : "(none)");
|
||||
|
||||
ci->SetSuccessor(nc);
|
||||
|
||||
@@ -1235,7 +1235,7 @@ class CSSet : public Module
|
||||
ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2");
|
||||
}
|
||||
|
||||
void OnChannelCreate(Channel *c) anope_override
|
||||
void OnChannelSync(Channel *c) anope_override
|
||||
{
|
||||
if (c->ci && keep_modes.HasExt(c->ci))
|
||||
{
|
||||
@@ -1245,11 +1245,6 @@ class CSSet : public Module
|
||||
}
|
||||
}
|
||||
|
||||
void OnChannelSync(Channel *c) anope_override
|
||||
{
|
||||
OnChannelCreate(c);
|
||||
}
|
||||
|
||||
EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
|
||||
{
|
||||
if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT"))
|
||||
|
||||
@@ -235,9 +235,9 @@ class CSSuspend : public Module
|
||||
if (!si->reason.empty() && (show_hidden || Show(source, "reason")))
|
||||
info[_("Suspend reason")] = si->reason;
|
||||
if (si->when && (show_hidden || Show(source, "on")))
|
||||
info[_("Suspended on")] = Anope::strftime(si->when, source.GetAccount(), true);
|
||||
info[_("Suspended on")] = Anope::strftime(si->when, source.GetAccount());
|
||||
if (si->expires && (show_hidden || Show(source, "expires")))
|
||||
info[_("Suspension expires")] = Anope::strftime(si->expires, source.GetAccount(), true);
|
||||
info[_("Suspension expires")] = Anope::strftime(si->expires, source.GetAccount());
|
||||
}
|
||||
|
||||
void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override
|
||||
|
||||
@@ -114,10 +114,8 @@ class CommandCSTopic : public Command
|
||||
source.Reply(_("Topic lock option for %s is now \002off\002."), ci->name.c_str());
|
||||
}
|
||||
|
||||
void Set(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms)
|
||||
void Set(CommandSource &source, ChannelInfo *ci, const Anope::string &topic)
|
||||
{
|
||||
const Anope::string &topic = params.size() > 2 ? params[2] : "";
|
||||
|
||||
bool has_topiclock = topiclock->HasExt(ci);
|
||||
topiclock->Unset(ci);
|
||||
ci->c->ChangeTopic(source.GetNick(), topic, Anope::CurTime);
|
||||
@@ -141,12 +139,7 @@ class CommandCSTopic : public Command
|
||||
else
|
||||
new_topic = topic;
|
||||
|
||||
std::vector<Anope::string> new_params;
|
||||
new_params.push_back("SET");
|
||||
new_params.push_back(ci->name);
|
||||
new_params.push_back(new_topic);
|
||||
|
||||
this->Set(source, ci, new_params);
|
||||
this->Set(source, ci, new_topic);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -154,7 +147,7 @@ class CommandCSTopic : public Command
|
||||
topiclock("TOPICLOCK")
|
||||
{
|
||||
this->SetDesc(_("Manipulate the topic of the specified channel"));
|
||||
this->SetSyntax(_("\037channel\037 SET [\037topic\037]"));
|
||||
this->SetSyntax(_("\037channel\037 [SET] [\037topic\037]"));
|
||||
this->SetSyntax(_("\037channel\037 APPEND \037topic\037"));
|
||||
this->SetSyntax(_("\037channel\037 [UNLOCK|LOCK]"));
|
||||
}
|
||||
@@ -174,12 +167,23 @@ class CommandCSTopic : public Command
|
||||
this->Unlock(source, ci, params);
|
||||
else if (!ci->c)
|
||||
source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str());
|
||||
else if (subcmd.equals_ci("SET"))
|
||||
this->Set(source, ci, params);
|
||||
else if (subcmd.equals_ci("APPEND") && params.size() > 2)
|
||||
this->Append(source, ci, params);
|
||||
else
|
||||
this->SendSyntax(source);
|
||||
{
|
||||
Anope::string topic;
|
||||
if (subcmd.equals_ci("SET"))
|
||||
{
|
||||
topic = params.size() > 2 ? params[2] : "";
|
||||
}
|
||||
else
|
||||
{
|
||||
topic = subcmd;
|
||||
if (params.size() > 2)
|
||||
topic += " " + params[2];
|
||||
}
|
||||
this->Set(source, ci, topic);
|
||||
}
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
|
||||
@@ -223,7 +227,7 @@ class CSTopic : public Module
|
||||
}
|
||||
}
|
||||
|
||||
void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
|
||||
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
|
||||
{
|
||||
if (!c->ci)
|
||||
return;
|
||||
@@ -233,7 +237,7 @@ class CSTopic : public Module
|
||||
* This desyncs what is really set with what we have stored, and we end up resetting the topic often when
|
||||
* it is not required
|
||||
*/
|
||||
if (topiclock.HasExt(c->ci) && c->ci->last_topic != c->topic)
|
||||
if (topiclock.HasExt(c->ci) && c->ci->last_topic != c->topic && (!source || !c->ci->AccessFor(source).HasPriv("TOPIC")))
|
||||
{
|
||||
c->ChangeTopic(c->ci->last_topic_setter, c->ci->last_topic, c->ci->last_topic_time);
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class CommandCSUnban : public Command
|
||||
"given, all bans affecting you in channels you have access\n"
|
||||
"in are removed.\n"
|
||||
" \n"
|
||||
"By default, limited to AOPs or those with level 5 and above\n"
|
||||
"By default, limited to AOPs or those with level 5 access and above\n"
|
||||
"on the channel."), source.service->nick.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ class CommandCSUp : public Command
|
||||
}
|
||||
|
||||
User *u = User::Find(nick, true);
|
||||
User *srcu = source.GetUser();
|
||||
bool override = false;
|
||||
|
||||
if (u == NULL)
|
||||
@@ -88,6 +89,11 @@ class CommandCSUp : public Command
|
||||
source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
|
||||
return;
|
||||
}
|
||||
else if (srcu && !srcu->FindChannel(c))
|
||||
{
|
||||
source.Reply(_("You must be in \002%s\002 to use this command."), c->name.c_str());
|
||||
return;
|
||||
}
|
||||
else if (!u->FindChannel(c))
|
||||
{
|
||||
source.Reply(NICK_X_NOT_ON_CHAN, nick.c_str(), channel.c_str());
|
||||
@@ -173,6 +179,7 @@ class CommandCSDown : public Command
|
||||
}
|
||||
|
||||
User *u = User::Find(nick, true);
|
||||
User *srcu = source.GetUser();
|
||||
bool override = false;
|
||||
|
||||
if (u == NULL)
|
||||
@@ -180,6 +187,11 @@ class CommandCSDown : public Command
|
||||
source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
|
||||
return;
|
||||
}
|
||||
else if (srcu && !srcu->FindChannel(c))
|
||||
{
|
||||
source.Reply(_("You must be in \002%s\002 to use this command."), c->name.c_str());
|
||||
return;
|
||||
}
|
||||
else if (!u->FindChannel(c))
|
||||
{
|
||||
source.Reply(NICK_X_NOT_ON_CHAN, nick.c_str(), channel.c_str());
|
||||
|
||||
@@ -120,6 +120,7 @@ class CommandCSXOP : public Command
|
||||
AccessGroup access = source.AccessFor(ci);
|
||||
const ChanAccess *highest = access.Highest();
|
||||
bool override = false;
|
||||
const NickAlias *na = NULL;
|
||||
|
||||
std::vector<Anope::string>::iterator cmd_it = std::find(order.begin(), order.end(), source.command.upper()),
|
||||
access_it = highest ? std::find(order.begin(), order.end(), XOPChanAccess::DetermineLevel(highest)) : order.end();
|
||||
@@ -159,7 +160,7 @@ class CommandCSXOP : public Command
|
||||
}
|
||||
else
|
||||
{
|
||||
const NickAlias *na = NickAlias::Find(mask);
|
||||
na = NickAlias::Find(mask);
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
@@ -176,13 +177,16 @@ class CommandCSXOP : public Command
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (na)
|
||||
mask = na->nick;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
|
||||
{
|
||||
const ChanAccess *a = ci->GetAccess(i);
|
||||
|
||||
if (a->Mask().equals_ci(mask))
|
||||
if ((na && na->nc == a->GetAccount()) || mask.equals_ci(a->Mask()))
|
||||
{
|
||||
if ((!highest || *a >= *highest) && !access.founder && !source.HasPriv("chanserv/access/modify"))
|
||||
{
|
||||
@@ -365,7 +369,7 @@ class CommandCSXOP : public Command
|
||||
|
||||
AccessGroup access = source.AccessFor(ci);
|
||||
|
||||
if (!access.HasPriv("ACCESS_LIST") && !source.HasCommand("chanserv/access/list"))
|
||||
if (!access.HasPriv("ACCESS_LIST") && !source.HasPriv("chanserv/access/list"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
@@ -562,11 +566,6 @@ class CommandCSXOP : public Command
|
||||
"The \002%s CLEAR\002 command clears all entries of the\n"
|
||||
"%s list."), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(),
|
||||
cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str());
|
||||
source.Reply(_(" \n"
|
||||
"The \002%s\002 commands are limited to founders\n"
|
||||
"(unless SECUREOPS is off). However, any user on the\n"
|
||||
"VOP list or above may use the \002%s LIST\002 command.\n"
|
||||
" \n"), cmd.c_str(), cmd.c_str());
|
||||
BotInfo *access_bi, *flags_bi;
|
||||
Anope::string access_cmd, flags_cmd;
|
||||
Command::FindCommandFromService("chanserv/access", access_bi, access_cmd);
|
||||
|
||||
@@ -56,7 +56,7 @@ class CommandHSDelAll : public Command
|
||||
public:
|
||||
CommandHSDelAll(Module *creator) : Command(creator, "hostserv/delall", 1, 1)
|
||||
{
|
||||
this->SetDesc(_("Delete the vhost for all nicks in a group"));
|
||||
this->SetDesc(_("Deletes the vhost for all nicks in a group"));
|
||||
this->SetSyntax(_("\037nick\037"));
|
||||
}
|
||||
|
||||
|
||||
@@ -133,8 +133,8 @@ class CommandHSList : public Command
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("This command lists registered vhosts to the operator\n"
|
||||
"if a \037key\037 is specified, only entries whos nick or vhost match\n"
|
||||
source.Reply(_("This command lists registered vhosts to the operator.\n"
|
||||
"If a \037key\037 is specified, only entries whose nick or vhost match\n"
|
||||
"the pattern given in \037key\037 are displayed e.g. Rob* for all\n"
|
||||
"entries beginning with \"Rob\"\n"
|
||||
"If a \037#X-Y\037 style is used, only entries between the range of \002X\002\n"
|
||||
|
||||
@@ -96,6 +96,12 @@ class CommandHSRequest : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.GetAccount()->HasExt("UNCONFIRMED"))
|
||||
{
|
||||
source.Reply(_("You must confirm your account before you may request a vhost."));
|
||||
return;
|
||||
}
|
||||
|
||||
Anope::string rawhostmask = params[0];
|
||||
|
||||
Anope::string user, host;
|
||||
@@ -171,7 +177,7 @@ class CommandHSRequest : public Command
|
||||
{
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Request the given vHost to be actived for your nick by the\n"
|
||||
source.Reply(_("Request the given vHost to be activated for your nick by the\n"
|
||||
"network administrators. Please be patient while your request\n"
|
||||
"is being considered."));
|
||||
return true;
|
||||
|
||||
@@ -67,7 +67,7 @@ class CommandMSCheck : public Command
|
||||
this->SendSyntax(source);
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Checks whether the _last_ memo you sent to \037nick\037 has been read\n"
|
||||
"or not. Note that this does only work with nicks, not with channels."));
|
||||
"or not. Note that this only works with nicks, not with channels."));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,6 +50,12 @@ class CommandMSIgnore : public Command
|
||||
source.Reply(ACCESS_DENIED);
|
||||
else if (command.equals_ci("ADD") && !param.empty())
|
||||
{
|
||||
if (mi->ignores.size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32"))
|
||||
{
|
||||
source.Reply(_("Sorry, the memo ignore list for \002%s\002 is full."), channel.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::find(mi->ignores.begin(), mi->ignores.end(), param.ci_str()) == mi->ignores.end())
|
||||
{
|
||||
mi->ignores.push_back(param.ci_str());
|
||||
|
||||
@@ -39,9 +39,18 @@ class CommandMSSend : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.GetAccount()->HasExt("UNCONFIRMED"))
|
||||
{
|
||||
source.Reply(_("You must confirm your account before you may send a memo."));
|
||||
return;
|
||||
}
|
||||
|
||||
MemoServService::MemoResult result = memoserv->Send(source.GetNick(), nick, text);
|
||||
if (result == MemoServService::MEMO_SUCCESS)
|
||||
{
|
||||
source.Reply(_("Memo sent to \002%s\002."), nick.c_str());
|
||||
Log(LOG_COMMAND, source, this) << "to send a memo to " << nick;
|
||||
}
|
||||
else if (result == MemoServService::MEMO_INVALID_TARGET)
|
||||
source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str());
|
||||
else if (result == MemoServService::MEMO_TOO_FAST)
|
||||
|
||||
@@ -318,19 +318,19 @@ class CommandNSCert : public Command
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Modifies or displays the certificate list for your nick.\n"
|
||||
"If you connect to IRC and provide a client certificate with a\n"
|
||||
"matching fingerprint in the cert list, your nick will be\n"
|
||||
"matching fingerprint in the cert list, you will be\n"
|
||||
"automatically identified to services. Services Operators\n"
|
||||
"may provide a nick to modify other users' certificate lists.\n"
|
||||
" \n"));
|
||||
source.Reply(_("Examples:\n"
|
||||
" \n"
|
||||
" \002CERT ADD <fingerprint>\002\n"
|
||||
" Adds this fingerprint to the certificate list and\n"
|
||||
" \002CERT ADD\002\n"
|
||||
" Adds your current fingerprint to the certificate list and\n"
|
||||
" automatically identifies you when you connect to IRC\n"
|
||||
" using this certificate.\n"
|
||||
" using this fingerprint.\n"
|
||||
" \n"
|
||||
" \002CERT DEL <fingerprint>\002\n"
|
||||
" Reverses the previous command.\n"
|
||||
" Removes the fingerprint <fingerprint> from your certificate list.\n"
|
||||
" \n"
|
||||
" \002CERT LIST\002\n"
|
||||
" Displays the current certificate list."));
|
||||
|
||||
@@ -72,7 +72,7 @@ class NSRecoverRequest : public IdentifyRequest
|
||||
source.GetNick().c_str(), source.GetNick().c_str());
|
||||
|
||||
Anope::string buf = source.command.upper() + " command used by " + source.GetNick();
|
||||
u->Kill(source.service->nick, buf);
|
||||
u->Kill(*source.service, buf);
|
||||
|
||||
source.Reply(_("Ghost with your nick has been killed."));
|
||||
|
||||
@@ -95,8 +95,10 @@ class NSRecoverRequest : public IdentifyRequest
|
||||
if (IRCD->CanSVSNick)
|
||||
{
|
||||
/* If we can svsnick then release our hold and svsnick the user using the command */
|
||||
nickserv->Release(na);
|
||||
if (nickserv)
|
||||
nickserv->Release(na);
|
||||
IRCD->SendForceNickChange(source.GetUser(), GetAccount(), Anope::CurTime);
|
||||
source.Reply(_("You have regained control of \002%s\002 and are now identified as \002%s\002."), GetAccount().c_str(), na->nc->display.c_str());
|
||||
}
|
||||
else
|
||||
source.Reply(_("The user with your nick has been removed. Use this command again\n"
|
||||
|
||||
@@ -37,6 +37,7 @@ class CommandNSConfirm : public Command
|
||||
else
|
||||
{
|
||||
na->nc->Shrink<bool>("UNCONFIRMED");
|
||||
FOREACH_MOD(OnNickConfirm, (source.GetUser(), na->nc));
|
||||
Log(LOG_ADMIN, source, this) << "to confirm nick " << na->nick << " (" << na->nc->display << ")";
|
||||
source.Reply(_("Nick \002%s\002 has been confirmed."), na->nick.c_str());
|
||||
}
|
||||
@@ -51,6 +52,7 @@ class CommandNSConfirm : public Command
|
||||
Log(LOG_COMMAND, source, this) << "to confirm their email";
|
||||
source.Reply(_("Your email address of \002%s\002 has been confirmed."), source.nc->email.c_str());
|
||||
nc->Shrink<bool>("UNCONFIRMED");
|
||||
FOREACH_MOD(OnNickConfirm, (source.GetUser(), nc));
|
||||
|
||||
if (source.GetUser())
|
||||
{
|
||||
@@ -168,6 +170,8 @@ class CommandNSRegister : public Command
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
|
||||
|
||||
if (Config->GetModule("nickserv")->Get<bool>("forceemail", "yes") && email.empty())
|
||||
this->OnSyntaxError(source, "");
|
||||
else if (u && Anope::CurTime < u->lastnickreg + reg_delay)
|
||||
@@ -176,8 +180,8 @@ class CommandNSRegister : public Command
|
||||
source.Reply(NICK_ALREADY_REGISTERED, u_nick.c_str());
|
||||
else if (pass.equals_ci(u_nick) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && pass.length() < 5))
|
||||
source.Reply(MORE_OBSCURE_PASSWORD);
|
||||
else if (pass.length() > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
|
||||
source.Reply(PASSWORD_TOO_LONG);
|
||||
else if (pass.length() > passlen)
|
||||
source.Reply(PASSWORD_TOO_LONG, passlen);
|
||||
else if (!email.empty() && !Mail::Validate(email))
|
||||
source.Reply(MAIL_X_INVALID, email.c_str());
|
||||
else
|
||||
@@ -198,8 +202,6 @@ class CommandNSRegister : public Command
|
||||
|
||||
Log(LOG_COMMAND, source, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")";
|
||||
|
||||
FOREACH_MOD(OnNickRegister, (source.GetUser(), na, pass));
|
||||
|
||||
if (na->nc->GetAccessCount())
|
||||
source.Reply(_("Nickname \002%s\002 registered under your user@host-mask: %s"), u_nick.c_str(), na->nc->GetAccess(0).c_str());
|
||||
else
|
||||
@@ -223,6 +225,8 @@ class CommandNSRegister : public Command
|
||||
}
|
||||
}
|
||||
|
||||
FOREACH_MOD(OnNickRegister, (source.GetUser(), na, pass));
|
||||
|
||||
if (u)
|
||||
{
|
||||
u->Identify(na);
|
||||
|
||||
+17
-10
@@ -33,7 +33,8 @@ class CommandNSSet : public Command
|
||||
source.Reply(_("Sets various nickname options. \037option\037 can be one of:"));
|
||||
|
||||
Anope::string this_name = source.command;
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands");
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
|
||||
for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it)
|
||||
{
|
||||
const Anope::string &c_name = it->first;
|
||||
@@ -42,13 +43,12 @@ class CommandNSSet : public Command
|
||||
if (c_name.find_ci(this_name + " ") == 0)
|
||||
{
|
||||
ServiceReference<Command> c("Command", info.name);
|
||||
// XXX dup
|
||||
if (!c)
|
||||
continue;
|
||||
else if (!hide_privileged_commands)
|
||||
; // Always show with hide_privileged_commands disabled
|
||||
else if (!c->AllowUnregistered() && !source.GetAccount())
|
||||
else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount())
|
||||
continue;
|
||||
else if (!info.permission.empty() && !source.HasCommand(info.permission))
|
||||
else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission))
|
||||
continue;
|
||||
|
||||
source.command = c_name;
|
||||
@@ -133,9 +133,11 @@ class CommandNSSetPassword : public Command
|
||||
source.Reply(MORE_OBSCURE_PASSWORD);
|
||||
return;
|
||||
}
|
||||
else if (len > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
|
||||
|
||||
unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
|
||||
if (len > passlen)
|
||||
{
|
||||
source.Reply(PASSWORD_TOO_LONG);
|
||||
source.Reply(PASSWORD_TOO_LONG, passlen);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -191,14 +193,17 @@ class CommandNSSASetPassword : public Command
|
||||
source.Reply(_("You may not change the password of other Services Operators."));
|
||||
return;
|
||||
}
|
||||
else if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
|
||||
|
||||
if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
|
||||
{
|
||||
source.Reply(MORE_OBSCURE_PASSWORD);
|
||||
return;
|
||||
}
|
||||
else if (len > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
|
||||
|
||||
unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
|
||||
if (len > passlen)
|
||||
{
|
||||
source.Reply(PASSWORD_TOO_LONG);
|
||||
source.Reply(PASSWORD_TOO_LONG, passlen);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -414,10 +419,12 @@ class CommandNSSetEmail : public Command
|
||||
message = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_message");
|
||||
|
||||
subject = subject.replace_all_cs("%e", u->Account()->email);
|
||||
subject = subject.replace_all_cs("%E", new_email);
|
||||
subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
|
||||
subject = subject.replace_all_cs("%c", code);
|
||||
|
||||
message = message.replace_all_cs("%e", u->Account()->email);
|
||||
message = message.replace_all_cs("%E", new_email);
|
||||
message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
|
||||
message = message.replace_all_cs("%c", code);
|
||||
|
||||
|
||||
@@ -249,9 +249,9 @@ class NSSuspend : public Module
|
||||
if (!s->reason.empty() && (show_hidden || Show(source, "reason")))
|
||||
info[_("Suspend reason")] = s->reason;
|
||||
if (s->when && (show_hidden || Show(source, "on")))
|
||||
info[_("Suspended on")] = Anope::strftime(s->when, source.GetAccount(), true);
|
||||
info[_("Suspended on")] = Anope::strftime(s->when, source.GetAccount());
|
||||
if (s->expires && (show_hidden || Show(source, "expires")))
|
||||
info[_("Suspension expires")] = Anope::strftime(s->expires, source.GetAccount(), true);
|
||||
info[_("Suspension expires")] = Anope::strftime(s->expires, source.GetAccount());
|
||||
}
|
||||
|
||||
void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
|
||||
|
||||
@@ -153,6 +153,9 @@ class CommandOSAKill : public Command
|
||||
if (targ)
|
||||
mask = "*@" + targ->host;
|
||||
|
||||
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
|
||||
reason = "[" + source.GetNick() + "] " + reason;
|
||||
|
||||
if (!akills->CanAdd(source, mask, expires, reason))
|
||||
return;
|
||||
else if (mask.find_first_not_of("/~@.*?") == Anope::string::npos)
|
||||
@@ -166,9 +169,6 @@ class CommandOSAKill : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
|
||||
reason = "[" + source.GetNick() + "] " + reason;
|
||||
|
||||
XLine *x = new XLine(mask, source.GetNick(), expires, reason);
|
||||
if (Config->GetModule("operserv")->Get<bool>("akillids"))
|
||||
x->id = XLineManager::GenerateUID();
|
||||
|
||||
@@ -439,7 +439,16 @@ class OSDefcon : public Module
|
||||
|
||||
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override
|
||||
{
|
||||
if (command->name == "nickserv/register" || command->name == "nickserv/group")
|
||||
if (DConfig.Check(DEFCON_OPER_ONLY) && !source.IsOper())
|
||||
{
|
||||
source.Reply(_("Services are in DefCon mode, please try again later."));
|
||||
return EVENT_STOP;
|
||||
}
|
||||
else if (DConfig.Check(DEFCON_SILENT_OPER_ONLY) && !source.IsOper())
|
||||
{
|
||||
return EVENT_STOP;
|
||||
}
|
||||
else if (command->name == "nickserv/register" || command->name == "nickserv/group")
|
||||
{
|
||||
if (DConfig.Check(DEFCON_NO_NEW_NICKS))
|
||||
{
|
||||
@@ -487,15 +496,10 @@ class OSDefcon : public Module
|
||||
XLine x("*@" + u->host, OperServ ? OperServ->nick : "defcon", Anope::CurTime + DConfig.akillexpire, DConfig.akillreason, XLineManager::GenerateUID());
|
||||
akills->Send(NULL, &x);
|
||||
}
|
||||
if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS))
|
||||
{
|
||||
u->Kill(OperServ ? OperServ->nick : "", DConfig.akillreason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS))
|
||||
{
|
||||
u->Kill(OperServ ? OperServ->nick : "", DConfig.akillreason);
|
||||
u->Kill(OperServ, DConfig.akillreason);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -520,13 +524,13 @@ class OSDefcon : public Module
|
||||
++session->hits;
|
||||
if (akills && DConfig.max_session_kill && session->hits >= DConfig.max_session_kill)
|
||||
{
|
||||
XLine x("*@" + u->host, OperServ ? OperServ->nick : "", Anope::CurTime + DConfig.session_autokill_expiry, "Defcon session limit exceeded", XLineManager::GenerateUID());
|
||||
XLine x("*@" + session->addr.mask(), OperServ ? OperServ->nick : "", Anope::CurTime + DConfig.session_autokill_expiry, "Defcon session limit exceeded", XLineManager::GenerateUID());
|
||||
akills->Send(NULL, &x);
|
||||
Log(OperServ, "akill/defcon") << "[DEFCON] Added a temporary AKILL for \002*@" << u->host << "\002 due to excessive connections";
|
||||
Log(OperServ, "akill/defcon") << "[DEFCON] Added a temporary AKILL for \002*@" << session->addr.mask() << "\002 due to excessive connections";
|
||||
}
|
||||
else
|
||||
{
|
||||
u->Kill(OperServ ? OperServ->nick : "", "Defcon session limit exceeded");
|
||||
u->Kill(OperServ, "Defcon session limit exceeded");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -573,7 +577,7 @@ static void runDefCon()
|
||||
{
|
||||
Log(OperServ, "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels";
|
||||
for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
|
||||
it->second->SetModes(OperServ, false, "%s", newmodes.c_str());
|
||||
it->second->SetModes(OperServ, true, "%s", newmodes.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,6 +455,7 @@ class CommandOSDNS : public Command
|
||||
}
|
||||
|
||||
z->servers.erase(s->GetName());
|
||||
s->zones.erase(z->name);
|
||||
source.Reply(_("Removed server %s from zone %s."), s->GetName().c_str(), z->name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,20 +33,26 @@ class CommandOSKick : public Command
|
||||
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
|
||||
return;
|
||||
}
|
||||
else if (c->bouncy_modes)
|
||||
|
||||
if (c->bouncy_modes)
|
||||
{
|
||||
source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?"));
|
||||
return;
|
||||
}
|
||||
else if (!(u2 = User::Find(nick, true)))
|
||||
|
||||
if (!(u2 = User::Find(nick, true)))
|
||||
{
|
||||
source.Reply(NICK_X_NOT_IN_USE, nick.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
c->Kick(source.service, u2, "%s (%s)", source.GetNick().c_str(), s.c_str());
|
||||
if (!c->Kick(source.service, u2, "%s (%s)", source.GetNick().c_str(), s.c_str()))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
Log(LOG_ADMIN, source, this) << "on " << u2->nick << " in " << c->name << " (" << s << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
|
||||
|
||||
@@ -37,7 +37,7 @@ class CommandOSKill : public Command
|
||||
if (Config->GetModule("operserv")->Get<bool>("addakiller"))
|
||||
reason = "(" + source.GetNick() + ") " + reason;
|
||||
Log(LOG_ADMIN, source, this) << "on " << u2->nick << " for " << reason;
|
||||
u2->Kill(source.service->nick, reason);
|
||||
u2->Kill(*source.service, reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class CommandOSMode : public Command
|
||||
const Anope::string &target = params[0];
|
||||
const Anope::string &modes = params[1];
|
||||
|
||||
Channel *c = Channel::Find(target);
|
||||
Reference<Channel> c = Channel::Find(target);
|
||||
if (!c)
|
||||
source.Reply(CHAN_X_NOT_IN_USE, target.c_str());
|
||||
else if (c->bouncy_modes)
|
||||
@@ -36,9 +36,15 @@ class CommandOSMode : public Command
|
||||
bool all = params.size() > 2 && params[2].equals_ci("ALL");
|
||||
|
||||
const Channel::ModeList chmodes = c->GetModes();
|
||||
for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end; ++it)
|
||||
for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end && c; ++it)
|
||||
c->RemoveMode(c->ci->WhoSends(), it->first, it->second, false);
|
||||
|
||||
if (!c)
|
||||
{
|
||||
source.Reply(_("Modes cleared on %s and the channel destroyed."), target.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (all)
|
||||
{
|
||||
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
|
||||
@@ -65,7 +71,7 @@ class CommandOSMode : public Command
|
||||
Anope::string log_modes, log_params;
|
||||
|
||||
sep.GetToken(mode);
|
||||
for (unsigned i = 0; i < mode.length(); ++i)
|
||||
for (unsigned i = 0; i < mode.length() && c; ++i)
|
||||
{
|
||||
char ch = mode[i];
|
||||
|
||||
@@ -116,7 +122,7 @@ class CommandOSMode : public Command
|
||||
}
|
||||
|
||||
if (!log_modes.replace_all_cs("+", "").replace_all_cs("-", "").empty())
|
||||
Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << c->name;
|
||||
Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << (c ? c->name : target);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class CommandOSNOOP : public Command
|
||||
User *u2 = it->second;
|
||||
|
||||
if (u2->server == s && u2->HasMode("OPER"))
|
||||
u2->Kill(source.service->nick, reason);
|
||||
u2->Kill(*source.service, reason);
|
||||
}
|
||||
}
|
||||
else if (cmd.equals_ci("REVOKE"))
|
||||
@@ -92,7 +92,7 @@ class OSNOOP : public Module
|
||||
{
|
||||
Anope::string reason = "NOOP command used by " + *setter;
|
||||
BotInfo *OperServ = Config->GetClient("OperServ");
|
||||
u->Kill(OperServ ? OperServ->nick : "", reason);
|
||||
u->Kill(OperServ, reason);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,7 +69,7 @@ class CommandOSOper : public Command
|
||||
this->SetDesc(_("View and change Services Operators"));
|
||||
this->SetSyntax(_("ADD \037oper\037 \037type\037"));
|
||||
this->SetSyntax(_("DEL \037oper\037"));
|
||||
this->SetSyntax(_("INFO \037type\037"));
|
||||
this->SetSyntax(_("INFO [\037type\037]"));
|
||||
this->SetSyntax("LIST");
|
||||
}
|
||||
|
||||
@@ -82,6 +82,12 @@ class CommandOSOper : public Command
|
||||
const Anope::string &oper = params[1];
|
||||
const Anope::string &otype = params[2];
|
||||
|
||||
if (!source.HasPriv("operserv/oper/modify"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
const NickAlias *na = NickAlias::Find(oper);
|
||||
if (na == NULL)
|
||||
source.Reply(NICK_X_NOT_REGISTERED, oper.c_str());
|
||||
@@ -103,6 +109,7 @@ class CommandOSOper : public Command
|
||||
}
|
||||
|
||||
na->nc->o = new MyOper(na->nc->display, ot);
|
||||
na->nc->o->require_oper = true;
|
||||
|
||||
if (Anope::ReadOnly)
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
@@ -115,6 +122,12 @@ class CommandOSOper : public Command
|
||||
{
|
||||
const Anope::string &oper = params[1];
|
||||
|
||||
if (!source.HasPriv("operserv/oper/modify"))
|
||||
{
|
||||
source.Reply(ACCESS_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
const NickAlias *na = NickAlias::Find(oper);
|
||||
if (na == NULL)
|
||||
source.Reply(NICK_X_NOT_REGISTERED, oper.c_str());
|
||||
@@ -154,8 +167,19 @@ class CommandOSOper : public Command
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (subcommand.equals_ci("INFO") && params.size() > 1)
|
||||
else if (subcommand.equals_ci("INFO"))
|
||||
{
|
||||
if (params.size() < 2)
|
||||
{
|
||||
source.Reply(_("Available opertypes:"));
|
||||
for (unsigned i = 0; i < Config->MyOperTypes.size(); ++i)
|
||||
{
|
||||
OperType *ot = Config->MyOperTypes[i];
|
||||
source.Reply("%s", ot->GetName().c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Anope::string fulltype = params[1];
|
||||
if (params.size() > 2)
|
||||
fulltype += " " + params[2];
|
||||
|
||||
@@ -424,44 +424,6 @@ class CommandOSException : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
void DoMove(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
const Anope::string &n1str = params.size() > 1 ? params[1] : ""; /* From position */
|
||||
const Anope::string &n2str = params.size() > 2 ? params[2] : ""; /* To position */
|
||||
int n1, n2;
|
||||
|
||||
if (n2str.empty())
|
||||
{
|
||||
this->OnSyntaxError(source, "MOVE");
|
||||
return;
|
||||
}
|
||||
|
||||
n1 = n2 = -1;
|
||||
try
|
||||
{
|
||||
n1 = convertTo<int>(n1str);
|
||||
n2 = convertTo<int>(n2str);
|
||||
}
|
||||
catch (const ConvertException &) { }
|
||||
|
||||
if (n1 >= 0 && static_cast<unsigned>(n1) < session_service->GetExceptions().size() && n2 >= 0 && static_cast<unsigned>(n2) < session_service->GetExceptions().size() && n1 != n2)
|
||||
{
|
||||
Exception *temp = session_service->GetExceptions()[n1];
|
||||
session_service->GetExceptions()[n1] = session_service->GetExceptions()[n2];
|
||||
session_service->GetExceptions()[n2] = temp;
|
||||
|
||||
Log(LOG_ADMIN, source, this) << "to move exception " << session_service->GetExceptions()[n1]->mask << " from position " << n1 + 1 << " to position " << n2 + 1;
|
||||
source.Reply(_("Exception for \002%s\002 (#%d) moved to position \002%d\002."), session_service->GetExceptions()[n1]->mask.c_str(), n1 + 1, n2 + 1);
|
||||
|
||||
if (Anope::ReadOnly)
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
}
|
||||
else
|
||||
this->OnSyntaxError(source, "MOVE");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ProcessList(CommandSource &source, const std::vector<Anope::string> ¶ms, ListFormatter &list)
|
||||
{
|
||||
const Anope::string &mask = params.size() > 1 ? params[1] : "";
|
||||
@@ -560,7 +522,6 @@ class CommandOSException : public Command
|
||||
this->SetDesc(_("Modify the session-limit exception list"));
|
||||
this->SetSyntax(_("ADD [\037+expiry\037] \037mask\037 \037limit\037 \037reason\037"));
|
||||
this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037}"));
|
||||
this->SetSyntax(_("MOVE \037num\037 \037position\037"));
|
||||
this->SetSyntax(_("LIST [\037mask\037 | \037list\037]"));
|
||||
this->SetSyntax(_("VIEW [\037mask\037 | \037list\037]"));
|
||||
}
|
||||
@@ -575,8 +536,6 @@ class CommandOSException : public Command
|
||||
return this->DoAdd(source, params);
|
||||
else if (cmd.equals_ci("DEL"))
|
||||
return this->DoDel(source, params);
|
||||
else if (cmd.equals_ci("MOVE"))
|
||||
return this->DoMove(source, params);
|
||||
else if (cmd.equals_ci("LIST"))
|
||||
return this->DoList(source, params);
|
||||
else if (cmd.equals_ci("VIEW"))
|
||||
@@ -610,9 +569,6 @@ class CommandOSException : public Command
|
||||
" \n"
|
||||
"\002EXCEPTION DEL\002 removes the given mask from the exception list.\n"
|
||||
" \n"
|
||||
"\002EXCEPTION MOVE\002 moves exception \037num\037 to \037position\037. The\n"
|
||||
"sessions inbetween will be shifted up or down to fill the gap.\n"
|
||||
" \n"
|
||||
"\002EXCEPTION LIST\002 and \002EXCEPTION VIEW\002 show all current\n"
|
||||
"sessions if the optional mask is given, the list is limited\n"
|
||||
"to those sessions matching the mask. The difference is that\n"
|
||||
@@ -639,7 +595,10 @@ class OSSession : public Module
|
||||
exception_type("Exception", Exception::Unserialize), ss(this), commandossession(this), commandosexception(this), akills("XLineManager", "xlinemanager/sgline")
|
||||
{
|
||||
this->SetPermanent(true);
|
||||
}
|
||||
|
||||
void Prioritize() anope_override
|
||||
{
|
||||
ModuleManager::SetPriority(this, PRIORITY_FIRST);
|
||||
}
|
||||
|
||||
@@ -713,9 +672,10 @@ class OSSession : public Module
|
||||
}
|
||||
|
||||
++session->hits;
|
||||
if (max_session_kill && session->hits >= max_session_kill && akills)
|
||||
|
||||
const Anope::string &akillmask = "*@" + session->addr.mask();
|
||||
if (max_session_kill && session->hits >= max_session_kill && akills && !akills->HasEntry(akillmask))
|
||||
{
|
||||
const Anope::string &akillmask = "*@" + session->addr.mask();
|
||||
XLine *x = new XLine(akillmask, OperServ ? OperServ->nick : "", Anope::CurTime + session_autokill_expiry, "Session limit exceeded", XLineManager::GenerateUID());
|
||||
akills->AddXLine(x);
|
||||
akills->Send(NULL, x);
|
||||
@@ -723,7 +683,7 @@ class OSSession : public Module
|
||||
}
|
||||
else
|
||||
{
|
||||
u->Kill(OperServ ? OperServ->nick : "", "Session limit exceeded");
|
||||
u->Kill(OperServ, "Session limit exceeded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,6 +351,9 @@ class CommandOSSNLine : public CommandOSSXLineBase
|
||||
if (mask[masklen - 1] == ' ')
|
||||
mask.erase(masklen - 1);
|
||||
|
||||
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
|
||||
reason = "[" + source.GetNick() + "] " + reason;
|
||||
|
||||
if (!this->xlm()->CanAdd(source, mask, expires, reason))
|
||||
return;
|
||||
else if (mask.find_first_not_of("/.*?") == Anope::string::npos)
|
||||
@@ -359,9 +362,6 @@ class CommandOSSNLine : public CommandOSSXLineBase
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
|
||||
reason = "[" + source.GetNick() + "] " + reason;
|
||||
|
||||
XLine *x = new XLine(mask, source.GetNick(), expires, reason);
|
||||
if (Config->GetModule("operserv")->Get<bool>("akillids"))
|
||||
x->id = XLineManager::GenerateUID();
|
||||
@@ -399,7 +399,7 @@ class CommandOSSNLine : public CommandOSSXLineBase
|
||||
User *user = it->second;
|
||||
|
||||
if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
|
||||
user->Kill(Me->GetName(), rreason);
|
||||
user->Kill(Me, rreason);
|
||||
}
|
||||
|
||||
this->xlm()->Send(NULL, x);
|
||||
@@ -558,6 +558,9 @@ class CommandOSSQLine : public CommandOSSXLineBase
|
||||
}
|
||||
}
|
||||
|
||||
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
|
||||
reason = "[" + source.GetNick() + "] " + reason;
|
||||
|
||||
if (!this->sqlines->CanAdd(source, mask, expires, reason))
|
||||
return;
|
||||
else if (mask.find_first_not_of("./?*") == Anope::string::npos)
|
||||
@@ -566,9 +569,6 @@ class CommandOSSQLine : public CommandOSSXLineBase
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty())
|
||||
reason = "[" + source.GetNick() + "] " + reason;
|
||||
|
||||
XLine *x = new XLine(mask, source.GetNick(), expires, reason);
|
||||
if (Config->GetModule("operserv")->Get<bool>("akillids"))
|
||||
x->id = XLineManager::GenerateUID();
|
||||
@@ -631,7 +631,7 @@ class CommandOSSQLine : public CommandOSSXLineBase
|
||||
User *user = it->second;
|
||||
|
||||
if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x))
|
||||
user->Kill(Me->GetName(), rreason);
|
||||
user->Kill(Me, rreason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +664,9 @@ class CommandOSSQLine : public CommandOSSXLineBase
|
||||
"connect, Services will not allow it to pursue his IRC\n"
|
||||
"session.\n"
|
||||
"If the first character of the mask is #, services will\n"
|
||||
"prevent the use of matching channels."));
|
||||
"prevent the use of matching channels. If the mask is a\n"
|
||||
"regular expression, the expression will be matched against\n"
|
||||
"channels too."));
|
||||
source.Reply(_(" \n"
|
||||
"\002SQLINE ADD\002 adds the given (nick's) mask to the SQLINE\n"
|
||||
"list for the given reason (which \002must\002 be given).\n"
|
||||
|
||||
@@ -146,10 +146,14 @@ class DBFlatFile : public Module, public Pipe
|
||||
Log(LOG_DEBUG) << "db_flatfile: Attempting to rename " << *it << " to " << newname;
|
||||
if (rename(oldname.c_str(), newname.c_str()))
|
||||
{
|
||||
Log(this) << "Unable to back up database " << *it << "!";
|
||||
Anope::string err = Anope::LastError();
|
||||
Log(this) << "Unable to back up database " << *it << " (" << err << ")!";
|
||||
|
||||
if (!Config->GetModule(this)->Get<bool>("nobackupok"))
|
||||
{
|
||||
Anope::Quitting = true;
|
||||
Anope::QuitReason = "Unable to back up database " + *it + " (" + err + ")";
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ class DBMySQL : public Module, public Pipe
|
||||
if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
|
||||
return;
|
||||
|
||||
Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` > " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
|
||||
Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` >= " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
|
||||
|
||||
obj->UpdateTimestamp();
|
||||
|
||||
@@ -228,7 +228,10 @@ class DBMySQL : public Module, public Pipe
|
||||
}
|
||||
else
|
||||
{
|
||||
delete s;
|
||||
if (!s)
|
||||
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + stringify(id));
|
||||
else
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,7 +873,7 @@ class EBCRYPT : public Module
|
||||
}
|
||||
|
||||
public:
|
||||
EBCRYPT(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR | EXTRA),
|
||||
EBCRYPT(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
|
||||
rounds(10)
|
||||
{
|
||||
// Test a pre-calculated hash
|
||||
|
||||
+349
-320
@@ -1,12 +1,139 @@
|
||||
/* RequiredLibraries: ldap,lber */
|
||||
/* RequiredWindowsLibraries: libldap,liblber */
|
||||
/*
|
||||
*
|
||||
* (C) 2011-2015 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.
|
||||
*/
|
||||
|
||||
/* RequiredLibraries: ldap_r,lber */
|
||||
/* RequiredWindowsLibraries: libldap_r,liblber */
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/ldap.h"
|
||||
#include <ldap.h>
|
||||
|
||||
class LDAPService;
|
||||
static Pipe *me;
|
||||
|
||||
class LDAPRequest
|
||||
{
|
||||
public:
|
||||
LDAPService *service;
|
||||
LDAPInterface *inter;
|
||||
LDAPMessage *message; /* message returned by ldap_ */
|
||||
LDAPResult *result; /* final result */
|
||||
struct timeval tv;
|
||||
QueryType type;
|
||||
|
||||
LDAPRequest(LDAPService *s, LDAPInterface *i)
|
||||
: service(s)
|
||||
, inter(i)
|
||||
, message(NULL)
|
||||
, result(NULL)
|
||||
{
|
||||
type = QUERY_UNKNOWN;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100000;
|
||||
}
|
||||
|
||||
virtual ~LDAPRequest()
|
||||
{
|
||||
delete result;
|
||||
if (inter != NULL)
|
||||
inter->OnDelete();
|
||||
if (message != NULL)
|
||||
ldap_msgfree(message);
|
||||
}
|
||||
|
||||
virtual int run() = 0;
|
||||
};
|
||||
|
||||
class LDAPBind : public LDAPRequest
|
||||
{
|
||||
Anope::string who, pass;
|
||||
|
||||
public:
|
||||
LDAPBind(LDAPService *s, LDAPInterface *i, const Anope::string &w, const Anope::string &p)
|
||||
: LDAPRequest(s, i)
|
||||
, who(w)
|
||||
, pass(p)
|
||||
{
|
||||
type = QUERY_BIND;
|
||||
}
|
||||
|
||||
int run() anope_override;
|
||||
};
|
||||
|
||||
class LDAPSearch : public LDAPRequest
|
||||
{
|
||||
Anope::string base;
|
||||
Anope::string filter;
|
||||
|
||||
public:
|
||||
LDAPSearch(LDAPService *s, LDAPInterface *i, const Anope::string &b, const Anope::string &f)
|
||||
: LDAPRequest(s, i)
|
||||
, base(b)
|
||||
, filter(f)
|
||||
{
|
||||
type = QUERY_SEARCH;
|
||||
}
|
||||
|
||||
int run() anope_override;
|
||||
};
|
||||
|
||||
class LDAPAdd : public LDAPRequest
|
||||
{
|
||||
Anope::string dn;
|
||||
LDAPMods attributes;
|
||||
|
||||
public:
|
||||
LDAPAdd(LDAPService *s, LDAPInterface *i, const Anope::string &d, const LDAPMods &attr)
|
||||
: LDAPRequest(s, i)
|
||||
, dn(d)
|
||||
, attributes(attr)
|
||||
{
|
||||
type = QUERY_ADD;
|
||||
}
|
||||
|
||||
int run() anope_override;
|
||||
};
|
||||
|
||||
class LDAPDel : public LDAPRequest
|
||||
{
|
||||
Anope::string dn;
|
||||
|
||||
public:
|
||||
LDAPDel(LDAPService *s, LDAPInterface *i, const Anope::string &d)
|
||||
: LDAPRequest(s, i)
|
||||
, dn(d)
|
||||
{
|
||||
type = QUERY_DELETE;
|
||||
}
|
||||
|
||||
int run() anope_override;
|
||||
};
|
||||
|
||||
class LDAPModify : public LDAPRequest
|
||||
{
|
||||
Anope::string base;
|
||||
LDAPMods attributes;
|
||||
|
||||
public:
|
||||
LDAPModify(LDAPService *s, LDAPInterface *i, const Anope::string &b, const LDAPMods &attr)
|
||||
: LDAPRequest(s, i)
|
||||
, base(b)
|
||||
, attributes(attr)
|
||||
{
|
||||
type = QUERY_MODIFY;
|
||||
}
|
||||
|
||||
int run() anope_override;
|
||||
};
|
||||
|
||||
class LDAPService : public LDAPProvider, public Thread, public Condition
|
||||
{
|
||||
Anope::string server;
|
||||
@@ -19,7 +146,8 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
|
||||
|
||||
time_t last_connect;
|
||||
|
||||
LDAPMod **BuildMods(const LDAPMods &attributes)
|
||||
public:
|
||||
static LDAPMod **BuildMods(const LDAPMods &attributes)
|
||||
{
|
||||
LDAPMod **mods = new LDAPMod*[attributes.size() + 1];
|
||||
memset(mods, 0, sizeof(LDAPMod*) * (attributes.size() + 1));
|
||||
@@ -46,7 +174,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
|
||||
return mods;
|
||||
}
|
||||
|
||||
void FreeMods(LDAPMod **mods)
|
||||
static void FreeMods(LDAPMod **mods)
|
||||
{
|
||||
for (int i = 0; mods[i] != NULL; ++i)
|
||||
{
|
||||
@@ -58,6 +186,7 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
|
||||
delete [] mods;
|
||||
}
|
||||
|
||||
private:
|
||||
void Reconnect()
|
||||
{
|
||||
/* Only try one connect a minute. It is an expensive blocking operation */
|
||||
@@ -71,11 +200,18 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
|
||||
throw LDAPException("Unable to connect to LDAP service " + this->name + ": " + ldap_err2string(i));
|
||||
}
|
||||
|
||||
void QueueRequest(LDAPRequest *r)
|
||||
{
|
||||
this->Lock();
|
||||
this->queries.push_back(r);
|
||||
this->Wakeup();
|
||||
this->Unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
typedef std::map<LDAPQuery, std::pair<time_t, LDAPInterface *> > query_queue;
|
||||
typedef std::vector<std::pair<LDAPInterface *, LDAPResult *> > result_queue;
|
||||
query_queue queries;
|
||||
result_queue results;
|
||||
typedef std::vector<LDAPRequest *> query_queue;
|
||||
query_queue queries, results;
|
||||
Mutex process_mutex; /* held when processing requests not in either queue */
|
||||
|
||||
LDAPService(Module *o, const Anope::string &n, const Anope::string &s, int po, const Anope::string &b, const Anope::string &p, time_t t) : LDAPProvider(o, n), server(s), port(po), admin_binddn(b), admin_pass(p), timeout(t), last_connect(0)
|
||||
{
|
||||
@@ -96,208 +232,178 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
|
||||
|
||||
~LDAPService()
|
||||
{
|
||||
/* At this point the thread has stopped so we don't need to hold process_mutex */
|
||||
|
||||
this->Lock();
|
||||
|
||||
for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end; ++it)
|
||||
for (unsigned int i = 0; i < this->queries.size(); ++i)
|
||||
{
|
||||
LDAPQuery msgid = it->first;
|
||||
LDAPInterface *i = it->second.second;
|
||||
LDAPRequest *req = this->queries[i];
|
||||
|
||||
ldap_abandon_ext(this->con, msgid, NULL, NULL);
|
||||
if (i)
|
||||
i->OnDelete();
|
||||
/* queries have no results yet */
|
||||
req->result = new LDAPResult();
|
||||
req->result->type = req->type;
|
||||
req->result->error = "LDAP Interface is going away";
|
||||
if (req->inter)
|
||||
req->inter->OnError(*req->result);
|
||||
|
||||
delete req;
|
||||
}
|
||||
this->queries.clear();
|
||||
|
||||
for (result_queue::iterator it = this->results.begin(), it_end = this->results.end(); it != it_end; ++it)
|
||||
for (unsigned int i = 0; i < this->results.size(); ++i)
|
||||
{
|
||||
LDAPInterface *i = it->first;
|
||||
LDAPResult *r = it->second;
|
||||
LDAPRequest *req = this->results[i];
|
||||
|
||||
r->error = "LDAP Interface is going away";
|
||||
if (i)
|
||||
i->OnError(*r);
|
||||
/* even though this may have already finished successfully we return that it didn't */
|
||||
req->result->error = "LDAP Interface is going away";
|
||||
if (req->inter)
|
||||
req->inter->OnError(*req->result);
|
||||
|
||||
delete r;
|
||||
delete req;
|
||||
}
|
||||
this->results.clear();
|
||||
|
||||
this->Unlock();
|
||||
|
||||
ldap_unbind_ext(this->con, NULL, NULL);
|
||||
}
|
||||
|
||||
LDAPQuery BindAsAdmin(LDAPInterface *i)
|
||||
void BindAsAdmin(LDAPInterface *i) anope_override
|
||||
{
|
||||
return this->Bind(i, this->admin_binddn, this->admin_pass);
|
||||
this->Bind(i, this->admin_binddn, this->admin_pass);
|
||||
}
|
||||
|
||||
LDAPQuery Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) anope_override
|
||||
void Bind(LDAPInterface *i, const Anope::string &who, const Anope::string &pass) anope_override
|
||||
{
|
||||
berval cred;
|
||||
cred.bv_val = strdup(pass.c_str());
|
||||
cred.bv_len = pass.length();
|
||||
|
||||
LDAPQuery msgid;
|
||||
int ret = ldap_sasl_bind(con, who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, &msgid);
|
||||
free(cred.bv_val);
|
||||
if (ret != LDAP_SUCCESS)
|
||||
{
|
||||
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
|
||||
{
|
||||
this->Reconnect();
|
||||
return this->Bind(i, who, pass);
|
||||
}
|
||||
else
|
||||
throw LDAPException(ldap_err2string(ret));
|
||||
}
|
||||
|
||||
if (i != NULL)
|
||||
{
|
||||
this->Lock();
|
||||
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
|
||||
this->Unlock();
|
||||
}
|
||||
this->Wakeup();
|
||||
|
||||
return msgid;
|
||||
LDAPBind *b = new LDAPBind(this, i, who, pass);
|
||||
QueueRequest(b);
|
||||
}
|
||||
|
||||
LDAPQuery Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) anope_override
|
||||
void Search(LDAPInterface *i, const Anope::string &base, const Anope::string &filter) anope_override
|
||||
{
|
||||
if (i == NULL)
|
||||
throw LDAPException("No interface");
|
||||
|
||||
LDAPQuery msgid;
|
||||
int ret = ldap_search_ext(this->con, base.c_str(), LDAP_SCOPE_SUBTREE, filter.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msgid);
|
||||
if (ret != LDAP_SUCCESS)
|
||||
{
|
||||
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
|
||||
{
|
||||
this->Reconnect();
|
||||
return this->Search(i, base, filter);
|
||||
}
|
||||
else
|
||||
throw LDAPException(ldap_err2string(ret));
|
||||
}
|
||||
|
||||
this->Lock();
|
||||
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
|
||||
this->Unlock();
|
||||
this->Wakeup();
|
||||
|
||||
return msgid;
|
||||
LDAPSearch *s = new LDAPSearch(this, i, base, filter);
|
||||
QueueRequest(s);
|
||||
}
|
||||
|
||||
LDAPQuery Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) anope_override
|
||||
void Add(LDAPInterface *i, const Anope::string &dn, LDAPMods &attributes) anope_override
|
||||
{
|
||||
LDAPMod **mods = this->BuildMods(attributes);
|
||||
LDAPQuery msgid;
|
||||
int ret = ldap_add_ext(this->con, dn.c_str(), mods, NULL, NULL, &msgid);
|
||||
this->FreeMods(mods);
|
||||
|
||||
if (ret != LDAP_SUCCESS)
|
||||
{
|
||||
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
|
||||
{
|
||||
this->Reconnect();
|
||||
return this->Add(i, dn, attributes);
|
||||
}
|
||||
else
|
||||
throw LDAPException(ldap_err2string(ret));
|
||||
}
|
||||
|
||||
if (i != NULL)
|
||||
{
|
||||
this->Lock();
|
||||
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
|
||||
this->Unlock();
|
||||
}
|
||||
this->Wakeup();
|
||||
|
||||
return msgid;
|
||||
LDAPAdd *add = new LDAPAdd(this, i, dn, attributes);
|
||||
QueueRequest(add);
|
||||
}
|
||||
|
||||
LDAPQuery Del(LDAPInterface *i, const Anope::string &dn) anope_override
|
||||
void Del(LDAPInterface *i, const Anope::string &dn) anope_override
|
||||
{
|
||||
LDAPQuery msgid;
|
||||
int ret = ldap_delete_ext(this->con, dn.c_str(), NULL, NULL, &msgid);
|
||||
|
||||
if (ret != LDAP_SUCCESS)
|
||||
{
|
||||
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
|
||||
{
|
||||
this->Reconnect();
|
||||
return this->Del(i, dn);
|
||||
}
|
||||
else
|
||||
throw LDAPException(ldap_err2string(ret));
|
||||
}
|
||||
|
||||
if (i != NULL)
|
||||
{
|
||||
this->Lock();
|
||||
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
|
||||
this->Unlock();
|
||||
}
|
||||
this->Wakeup();
|
||||
|
||||
return msgid;
|
||||
LDAPDel *del = new LDAPDel(this, i, dn);
|
||||
QueueRequest(del);
|
||||
}
|
||||
|
||||
LDAPQuery Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) anope_override
|
||||
void Modify(LDAPInterface *i, const Anope::string &base, LDAPMods &attributes) anope_override
|
||||
{
|
||||
LDAPMod **mods = this->BuildMods(attributes);
|
||||
LDAPQuery msgid;
|
||||
int ret = ldap_modify_ext(this->con, base.c_str(), mods, NULL, NULL, &msgid);
|
||||
this->FreeMods(mods);
|
||||
|
||||
if (ret != LDAP_SUCCESS)
|
||||
{
|
||||
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
|
||||
{
|
||||
this->Reconnect();
|
||||
return this->Modify(i, base, attributes);
|
||||
}
|
||||
else
|
||||
throw LDAPException(ldap_err2string(ret));
|
||||
}
|
||||
|
||||
if (i != NULL)
|
||||
{
|
||||
this->Lock();
|
||||
this->queries[msgid] = std::make_pair(Anope::CurTime, i);
|
||||
this->Unlock();
|
||||
}
|
||||
this->Wakeup();
|
||||
|
||||
return msgid;
|
||||
LDAPModify *mod = new LDAPModify(this, i, base, attributes);
|
||||
QueueRequest(mod);
|
||||
}
|
||||
|
||||
private:
|
||||
void Timeout()
|
||||
void BuildReply(int res, LDAPRequest *req)
|
||||
{
|
||||
this->Lock();
|
||||
for (query_queue::iterator it = this->queries.begin(), it_end = this->queries.end(); it != it_end;)
|
||||
LDAPResult *ldap_result = req->result = new LDAPResult();
|
||||
req->result->type = req->type;
|
||||
|
||||
if (res != LDAP_SUCCESS)
|
||||
{
|
||||
LDAPQuery msgid = it->first;
|
||||
time_t created = it->second.first;
|
||||
LDAPInterface *i = it->second.second;
|
||||
++it;
|
||||
|
||||
if (Anope::CurTime > created + timeout)
|
||||
{
|
||||
LDAPResult *ldap_result = new LDAPResult();
|
||||
ldap_result->id = msgid;
|
||||
ldap_result->error = "Query timed out";
|
||||
|
||||
this->queries.erase(msgid);
|
||||
this->results.push_back(std::make_pair(i, ldap_result));
|
||||
|
||||
me->Notify();
|
||||
}
|
||||
ldap_result->error = ldap_err2string(res);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->message == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* a search result */
|
||||
|
||||
for (LDAPMessage *cur = ldap_first_message(this->con, req->message); cur; cur = ldap_next_message(this->con, cur))
|
||||
{
|
||||
LDAPAttributes attributes;
|
||||
|
||||
char *dn = ldap_get_dn(this->con, cur);
|
||||
if (dn != NULL)
|
||||
{
|
||||
attributes["dn"].push_back(dn);
|
||||
ldap_memfree(dn);
|
||||
dn = NULL;
|
||||
}
|
||||
|
||||
BerElement *ber = NULL;
|
||||
|
||||
for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber))
|
||||
{
|
||||
berval **vals = ldap_get_values_len(this->con, cur, attr);
|
||||
int count = ldap_count_values_len(vals);
|
||||
|
||||
std::vector<Anope::string> attrs;
|
||||
for (int j = 0; j < count; ++j)
|
||||
attrs.push_back(vals[j]->bv_val);
|
||||
attributes[attr] = attrs;
|
||||
|
||||
ldap_value_free_len(vals);
|
||||
ldap_memfree(attr);
|
||||
}
|
||||
|
||||
if (ber != NULL)
|
||||
ber_free(ber, 0);
|
||||
|
||||
ldap_result->messages.push_back(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
void SendRequests()
|
||||
{
|
||||
process_mutex.Lock();
|
||||
|
||||
query_queue q;
|
||||
this->Lock();
|
||||
queries.swap(q);
|
||||
this->Unlock();
|
||||
|
||||
if (q.empty())
|
||||
{
|
||||
process_mutex.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < q.size(); ++i)
|
||||
{
|
||||
LDAPRequest *req = q[i];
|
||||
int ret = req->run();
|
||||
|
||||
if (ret == LDAP_SERVER_DOWN || ret == LDAP_TIMEOUT)
|
||||
{
|
||||
/* try again */
|
||||
try
|
||||
{
|
||||
Reconnect();
|
||||
}
|
||||
catch (const LDAPException &)
|
||||
{
|
||||
}
|
||||
|
||||
ret = req->run();
|
||||
}
|
||||
|
||||
BuildReply(ret, req);
|
||||
|
||||
this->Lock();
|
||||
results.push_back(req);
|
||||
this->Unlock();
|
||||
}
|
||||
|
||||
me->Notify();
|
||||
|
||||
process_mutex.Unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -305,154 +411,31 @@ class LDAPService : public LDAPProvider, public Thread, public Condition
|
||||
{
|
||||
while (!this->GetExitState())
|
||||
{
|
||||
if (this->queries.empty())
|
||||
{
|
||||
this->Lock();
|
||||
this->Lock();
|
||||
/* Queries can be non empty if one is pushed during SendRequests() */
|
||||
if (queries.empty())
|
||||
this->Wait();
|
||||
this->Unlock();
|
||||
continue;
|
||||
}
|
||||
else
|
||||
this->Timeout();
|
||||
|
||||
struct timeval tv = { 1, 0 };
|
||||
LDAPMessage *result;
|
||||
int rtype = ldap_result(this->con, LDAP_RES_ANY, 1, &tv, &result);
|
||||
if (rtype <= 0)
|
||||
continue;
|
||||
|
||||
int cur_id = ldap_msgid(result);
|
||||
|
||||
this->Lock();
|
||||
|
||||
query_queue::iterator it = this->queries.find(cur_id);
|
||||
if (it == this->queries.end())
|
||||
{
|
||||
this->Unlock();
|
||||
ldap_msgfree(result);
|
||||
continue;
|
||||
}
|
||||
LDAPInterface *i = it->second.second;
|
||||
this->queries.erase(it);
|
||||
|
||||
this->Unlock();
|
||||
|
||||
LDAPResult *ldap_result = new LDAPResult();
|
||||
ldap_result->id = cur_id;
|
||||
|
||||
for (LDAPMessage *cur = ldap_first_message(this->con, result); cur; cur = ldap_next_message(this->con, cur))
|
||||
{
|
||||
int cur_type = ldap_msgtype(cur);
|
||||
|
||||
LDAPAttributes attributes;
|
||||
|
||||
char *dn = ldap_get_dn(this->con, cur);
|
||||
if (dn != NULL)
|
||||
{
|
||||
attributes["dn"].push_back(dn);
|
||||
ldap_memfree(dn);
|
||||
dn = NULL;
|
||||
}
|
||||
|
||||
switch (cur_type)
|
||||
{
|
||||
case LDAP_RES_BIND:
|
||||
ldap_result->type = LDAPResult::QUERY_BIND;
|
||||
break;
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
ldap_result->type = LDAPResult::QUERY_SEARCH;
|
||||
break;
|
||||
case LDAP_RES_ADD:
|
||||
ldap_result->type = LDAPResult::QUERY_ADD;
|
||||
break;
|
||||
case LDAP_RES_DELETE:
|
||||
ldap_result->type = LDAPResult::QUERY_DELETE;
|
||||
break;
|
||||
case LDAP_RES_MODIFY:
|
||||
ldap_result->type = LDAPResult::QUERY_MODIFY;
|
||||
break;
|
||||
case LDAP_RES_SEARCH_RESULT:
|
||||
// If we get here and ldap_result->type is LDAPResult::QUERY_UNKNOWN
|
||||
// then the result set is empty
|
||||
ldap_result->type = LDAPResult::QUERY_SEARCH;
|
||||
break;
|
||||
default:
|
||||
Log(LOG_DEBUG) << "m_ldap: Unknown msg type " << cur_type;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cur_type)
|
||||
{
|
||||
case LDAP_RES_BIND:
|
||||
{
|
||||
int errcode = -1;
|
||||
int parse_result = ldap_parse_result(this->con, cur, &errcode, NULL, NULL, NULL, NULL, 0);
|
||||
if (parse_result != LDAP_SUCCESS)
|
||||
ldap_result->error = ldap_err2string(parse_result);
|
||||
else if (errcode != LDAP_SUCCESS)
|
||||
ldap_result->error = ldap_err2string(errcode);
|
||||
break;
|
||||
}
|
||||
case LDAP_RES_SEARCH_ENTRY:
|
||||
{
|
||||
BerElement *ber = NULL;
|
||||
for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber))
|
||||
{
|
||||
berval **vals = ldap_get_values_len(this->con, cur, attr);
|
||||
int count = ldap_count_values_len(vals);
|
||||
|
||||
std::vector<Anope::string> attrs;
|
||||
for (int j = 0; j < count; ++j)
|
||||
attrs.push_back(vals[j]->bv_val);
|
||||
attributes[attr] = attrs;
|
||||
|
||||
ldap_value_free_len(vals);
|
||||
ldap_memfree(attr);
|
||||
}
|
||||
if (ber != NULL)
|
||||
ber_free(ber, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
case LDAP_RES_ADD:
|
||||
case LDAP_RES_DELETE:
|
||||
case LDAP_RES_MODIFY:
|
||||
{
|
||||
int errcode = -1;
|
||||
int parse_result = ldap_parse_result(this->con, cur, &errcode, NULL, NULL, NULL, NULL, 0);
|
||||
if (parse_result != LDAP_SUCCESS)
|
||||
ldap_result->error = ldap_err2string(parse_result);
|
||||
else if (errcode != LDAP_SUCCESS)
|
||||
ldap_result->error = ldap_err2string(errcode);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
ldap_result->messages.push_back(attributes);
|
||||
}
|
||||
|
||||
ldap_msgfree(result);
|
||||
|
||||
this->Lock();
|
||||
this->results.push_back(std::make_pair(i, ldap_result));
|
||||
this->Unlock();
|
||||
|
||||
me->Notify();
|
||||
SendRequests();
|
||||
}
|
||||
}
|
||||
|
||||
LDAP* GetConnection()
|
||||
{
|
||||
return con;
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleLDAP : public Module, public Pipe
|
||||
{
|
||||
std::map<Anope::string, LDAPService *> LDAPServices;
|
||||
|
||||
public:
|
||||
|
||||
ModuleLDAP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR)
|
||||
{
|
||||
me = this;
|
||||
|
||||
}
|
||||
|
||||
~ModuleLDAP()
|
||||
@@ -489,6 +472,8 @@ class ModuleLDAP : public Module, public Pipe
|
||||
|
||||
s->SetExitState();
|
||||
s->Wakeup();
|
||||
s->Join();
|
||||
delete s;
|
||||
this->LDAPServices.erase(cname);
|
||||
}
|
||||
}
|
||||
@@ -513,7 +498,7 @@ class ModuleLDAP : public Module, public Pipe
|
||||
ss->Start();
|
||||
this->LDAPServices.insert(std::make_pair(connname, ss));
|
||||
|
||||
Log(LOG_NORMAL, "ldap") << "LDAP: Successfully connected to server " << connname << " (" << server << ")";
|
||||
Log(LOG_NORMAL, "ldap") << "LDAP: Successfully initialized server " << connname << " (" << server << ")";
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
@@ -528,32 +513,36 @@ class ModuleLDAP : public Module, public Pipe
|
||||
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end(); ++it)
|
||||
{
|
||||
LDAPService *s = it->second;
|
||||
s->Lock();
|
||||
for (LDAPService::query_queue::iterator it2 = s->queries.begin(); it2 != s->queries.end();)
|
||||
{
|
||||
LDAPQuery msgid = it2->first;
|
||||
LDAPInterface *i = it2->second.second;
|
||||
++it2;
|
||||
|
||||
if (i && i->owner == m)
|
||||
s->process_mutex.Lock();
|
||||
s->Lock();
|
||||
|
||||
for (unsigned int i = s->queries.size(); i > 0; --i)
|
||||
{
|
||||
LDAPRequest *req = s->queries[i - 1];
|
||||
LDAPInterface *li = req->inter;
|
||||
|
||||
if (li && li->owner == m)
|
||||
{
|
||||
i->OnDelete();
|
||||
s->queries.erase(msgid);
|
||||
s->queries.erase(s->queries.begin() + i - 1);
|
||||
delete req;
|
||||
}
|
||||
}
|
||||
for (unsigned i = s->results.size(); i > 0; --i)
|
||||
for (unsigned int i = s->results.size(); i > 0; --i)
|
||||
{
|
||||
LDAPInterface *li = s->results[i - 1].first;
|
||||
LDAPResult *r = s->results[i - 1].second;
|
||||
LDAPRequest *req = s->results[i - 1];
|
||||
LDAPInterface *li = req->inter;
|
||||
|
||||
if (li && li->owner == m)
|
||||
{
|
||||
s->results.erase(s->results.begin() + i - 1);
|
||||
delete r;
|
||||
delete req;
|
||||
}
|
||||
}
|
||||
|
||||
s->Unlock();
|
||||
}
|
||||
s->process_mutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void OnNotify() anope_override
|
||||
@@ -562,15 +551,16 @@ class ModuleLDAP : public Module, public Pipe
|
||||
{
|
||||
LDAPService *s = it->second;
|
||||
|
||||
LDAPService::result_queue results;
|
||||
LDAPService::query_queue results;
|
||||
s->Lock();
|
||||
results.swap(s->results);
|
||||
s->Unlock();
|
||||
|
||||
for (unsigned i = 0; i < results.size(); ++i)
|
||||
for (unsigned int i = 0; i < results.size(); ++i)
|
||||
{
|
||||
LDAPInterface *li = results[i].first;
|
||||
LDAPResult *r = results[i].second;
|
||||
LDAPRequest *req = results[i];
|
||||
LDAPInterface *li = req->inter;
|
||||
LDAPResult *r = req->result;
|
||||
|
||||
if (li != NULL)
|
||||
{
|
||||
@@ -583,11 +573,50 @@ class ModuleLDAP : public Module, public Pipe
|
||||
li->OnResult(*r);
|
||||
}
|
||||
|
||||
delete r;
|
||||
delete req;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int LDAPBind::run()
|
||||
{
|
||||
berval cred;
|
||||
cred.bv_val = strdup(pass.c_str());
|
||||
cred.bv_len = pass.length();
|
||||
|
||||
int i = ldap_sasl_bind_s(service->GetConnection(), who.c_str(), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL);
|
||||
|
||||
free(cred.bv_val);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int LDAPSearch::run()
|
||||
{
|
||||
return ldap_search_ext_s(service->GetConnection(), base.c_str(), LDAP_SCOPE_SUBTREE, filter.c_str(), NULL, 0, NULL, NULL, &tv, 0, &message);
|
||||
}
|
||||
|
||||
int LDAPAdd::run()
|
||||
{
|
||||
LDAPMod **mods = LDAPService::BuildMods(attributes);
|
||||
int i = ldap_add_ext_s(service->GetConnection(), dn.c_str(), mods, NULL, NULL);
|
||||
LDAPService::FreeMods(mods);
|
||||
return i;
|
||||
}
|
||||
|
||||
int LDAPDel::run()
|
||||
{
|
||||
return ldap_delete_ext_s(service->GetConnection(), dn.c_str(), NULL, NULL);
|
||||
}
|
||||
|
||||
int LDAPModify::run()
|
||||
{
|
||||
LDAPMod **mods = LDAPService::BuildMods(attributes);
|
||||
int i = ldap_modify_ext_s(service->GetConnection(), base.c_str(), mods, NULL, NULL);
|
||||
LDAPService::FreeMods(mods);
|
||||
return i;
|
||||
}
|
||||
|
||||
MODULE_INIT(ModuleLDAP)
|
||||
|
||||
|
||||
@@ -30,36 +30,29 @@ struct IdentifyInfo
|
||||
|
||||
class IdentifyInterface : public LDAPInterface
|
||||
{
|
||||
std::map<LDAPQuery, IdentifyInfo *> requests;
|
||||
IdentifyInfo *ii;
|
||||
|
||||
public:
|
||||
IdentifyInterface(Module *m) : LDAPInterface(m) { }
|
||||
IdentifyInterface(Module *m, IdentifyInfo *i) : LDAPInterface(m), ii(i) { }
|
||||
|
||||
void Add(LDAPQuery id, IdentifyInfo *ii)
|
||||
~IdentifyInterface()
|
||||
{
|
||||
std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(id);
|
||||
if (it != this->requests.end())
|
||||
delete it->second;
|
||||
this->requests[id] = ii;
|
||||
delete ii;
|
||||
}
|
||||
|
||||
void OnDelete() anope_override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void OnResult(const LDAPResult &r) anope_override
|
||||
{
|
||||
std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id);
|
||||
if (it == this->requests.end())
|
||||
return;
|
||||
IdentifyInfo *ii = it->second;
|
||||
this->requests.erase(it);
|
||||
|
||||
if (!ii->lprov)
|
||||
{
|
||||
delete ii;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (r.type)
|
||||
{
|
||||
case LDAPResult::QUERY_SEARCH:
|
||||
case QUERY_SEARCH:
|
||||
{
|
||||
if (!r.empty())
|
||||
{
|
||||
@@ -68,9 +61,9 @@ class IdentifyInterface : public LDAPInterface
|
||||
const LDAPAttributes &attr = r.get(0);
|
||||
ii->dn = attr.get("dn");
|
||||
Log(LOG_DEBUG) << "m_ldap_authenticationn: binding as " << ii->dn;
|
||||
LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->req->GetPassword());
|
||||
this->Add(id, ii);
|
||||
return;
|
||||
|
||||
ii->lprov->Bind(new IdentifyInterface(this->owner, ii), ii->dn, ii->req->GetPassword());
|
||||
ii = NULL;
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
@@ -79,7 +72,7 @@ class IdentifyInterface : public LDAPInterface
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LDAPResult::QUERY_BIND:
|
||||
case QUERY_BIND:
|
||||
{
|
||||
if (ii->admin_bind)
|
||||
{
|
||||
@@ -87,10 +80,9 @@ class IdentifyInterface : public LDAPInterface
|
||||
try
|
||||
{
|
||||
Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf;
|
||||
LDAPQuery id = ii->lprov->Search(this, basedn, sf);
|
||||
this->Add(id, ii);
|
||||
ii->lprov->Search(new IdentifyInterface(this->owner, ii), basedn, sf);
|
||||
ii->admin_bind = false;
|
||||
return;
|
||||
ii = NULL;
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
@@ -120,40 +112,28 @@ class IdentifyInterface : public LDAPInterface
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
delete ii;
|
||||
}
|
||||
|
||||
void OnError(const LDAPResult &r) anope_override
|
||||
{
|
||||
std::map<LDAPQuery, IdentifyInfo *>::iterator it = this->requests.find(r.id);
|
||||
if (it == this->requests.end())
|
||||
return;
|
||||
IdentifyInfo *ii = it->second;
|
||||
this->requests.erase(it);
|
||||
delete ii;
|
||||
}
|
||||
};
|
||||
|
||||
class OnIdentifyInterface : public LDAPInterface
|
||||
{
|
||||
std::map<LDAPQuery, Anope::string> requests;
|
||||
Anope::string uid;
|
||||
|
||||
public:
|
||||
OnIdentifyInterface(Module *m) : LDAPInterface(m) { }
|
||||
OnIdentifyInterface(Module *m, const Anope::string &i) : LDAPInterface(m), uid(i) { }
|
||||
|
||||
void Add(LDAPQuery id, const Anope::string &nick)
|
||||
void OnDelete() anope_override
|
||||
{
|
||||
this->requests[id] = nick;
|
||||
delete this;
|
||||
}
|
||||
|
||||
void OnResult(const LDAPResult &r) anope_override
|
||||
{
|
||||
std::map<LDAPQuery, Anope::string>::iterator it = this->requests.find(r.id);
|
||||
if (it == this->requests.end())
|
||||
return;
|
||||
User *u = User::Find(it->second);
|
||||
this->requests.erase(it);
|
||||
User *u = User::Find(uid);
|
||||
|
||||
if (!u || !u->Account() || r.empty())
|
||||
return;
|
||||
@@ -180,7 +160,6 @@ class OnIdentifyInterface : public LDAPInterface
|
||||
|
||||
void OnError(const LDAPResult &r) anope_override
|
||||
{
|
||||
this->requests.erase(r.id);
|
||||
Log(this->owner) << r.error;
|
||||
}
|
||||
};
|
||||
@@ -201,11 +180,9 @@ class OnRegisterInterface : public LDAPInterface
|
||||
}
|
||||
};
|
||||
|
||||
class NSIdentifyLDAP : public Module
|
||||
class ModuleLDAPAuthentication : public Module
|
||||
{
|
||||
ServiceReference<LDAPProvider> ldap;
|
||||
IdentifyInterface iinterface;
|
||||
OnIdentifyInterface oninterface;
|
||||
OnRegisterInterface orinterface;
|
||||
|
||||
PrimitiveExtensibleItem<Anope::string> dn;
|
||||
@@ -214,13 +191,15 @@ class NSIdentifyLDAP : public Module
|
||||
Anope::string disable_register_reason;
|
||||
Anope::string disable_email_reason;
|
||||
public:
|
||||
NSIdentifyLDAP(const Anope::string &modname, const Anope::string &creator) :
|
||||
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), iinterface(this), oninterface(this), orinterface(this),
|
||||
ModuleLDAPAuthentication(const Anope::string &modname, const Anope::string &creator) :
|
||||
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), orinterface(this),
|
||||
dn(this, "m_ldap_authentication_dn")
|
||||
{
|
||||
|
||||
me = this;
|
||||
}
|
||||
|
||||
void Prioritize() anope_override
|
||||
{
|
||||
ModuleManager::SetPriority(this, PRIORITY_FIRST);
|
||||
}
|
||||
|
||||
@@ -268,16 +247,7 @@ class NSIdentifyLDAP : public Module
|
||||
return;
|
||||
|
||||
IdentifyInfo *ii = new IdentifyInfo(u, req, this->ldap);
|
||||
try
|
||||
{
|
||||
LDAPQuery id = this->ldap->BindAsAdmin(&this->iinterface);
|
||||
this->iinterface.Add(id, ii);
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
delete ii;
|
||||
Log(this) << ex.GetReason();
|
||||
}
|
||||
this->ldap->BindAsAdmin(new IdentifyInterface(this, ii));
|
||||
}
|
||||
|
||||
void OnNickIdentify(User *u) anope_override
|
||||
@@ -289,15 +259,7 @@ class NSIdentifyLDAP : public Module
|
||||
if (!d || d->empty())
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
LDAPQuery id = this->ldap->Search(&this->oninterface, *d, "(" + email_attribute + "=*)");
|
||||
this->oninterface.Add(id, u->nick);
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
Log(this) << ex.GetReason();
|
||||
}
|
||||
this->ldap->Search(new OnIdentifyInterface(this, u->GetUID()), *d, "(" + email_attribute + "=*)");
|
||||
}
|
||||
|
||||
void OnNickRegister(User *, NickAlias *na, const Anope::string &pass) anope_override
|
||||
@@ -305,37 +267,30 @@ class NSIdentifyLDAP : public Module
|
||||
if (!this->disable_register_reason.empty() || !this->ldap)
|
||||
return;
|
||||
|
||||
try
|
||||
this->ldap->BindAsAdmin(NULL);
|
||||
|
||||
LDAPMods attributes;
|
||||
attributes.resize(4);
|
||||
|
||||
attributes[0].name = "objectClass";
|
||||
attributes[0].values.push_back("top");
|
||||
attributes[0].values.push_back(object_class);
|
||||
|
||||
attributes[1].name = username_attribute;
|
||||
attributes[1].values.push_back(na->nick);
|
||||
|
||||
if (!na->nc->email.empty())
|
||||
{
|
||||
this->ldap->BindAsAdmin(NULL);
|
||||
|
||||
LDAPMods attributes;
|
||||
attributes.resize(4);
|
||||
|
||||
attributes[0].name = "objectClass";
|
||||
attributes[0].values.push_back("top");
|
||||
attributes[0].values.push_back(object_class);
|
||||
|
||||
attributes[1].name = username_attribute;
|
||||
attributes[1].values.push_back(na->nick);
|
||||
|
||||
if (!na->nc->email.empty())
|
||||
{
|
||||
attributes[2].name = email_attribute;
|
||||
attributes[2].values.push_back(na->nc->email);
|
||||
}
|
||||
|
||||
attributes[3].name = this->password_attribute;
|
||||
attributes[3].values.push_back(pass);
|
||||
|
||||
Anope::string new_dn = username_attribute + "=" + na->nick + "," + basedn;
|
||||
this->ldap->Add(&this->orinterface, new_dn, attributes);
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
Log(this) << ex.GetReason();
|
||||
attributes[2].name = email_attribute;
|
||||
attributes[2].values.push_back(na->nc->email);
|
||||
}
|
||||
|
||||
attributes[3].name = this->password_attribute;
|
||||
attributes[3].values.push_back(pass);
|
||||
|
||||
Anope::string new_dn = username_attribute + "=" + na->nick + "," + basedn;
|
||||
this->ldap->Add(&this->orinterface, new_dn, attributes);
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSIdentifyLDAP)
|
||||
MODULE_INIT(ModuleLDAPAuthentication)
|
||||
|
||||
@@ -6,27 +6,15 @@ static Anope::string opertype_attribute;
|
||||
|
||||
class IdentifyInterface : public LDAPInterface
|
||||
{
|
||||
std::map<LDAPQuery, Anope::string> requests;
|
||||
Reference<User> u;
|
||||
|
||||
public:
|
||||
IdentifyInterface(Module *m) : LDAPInterface(m)
|
||||
IdentifyInterface(Module *m, User *user) : LDAPInterface(m), u(user)
|
||||
{
|
||||
}
|
||||
|
||||
void Add(LDAPQuery id, const Anope::string &nick)
|
||||
{
|
||||
this->requests[id] = nick;
|
||||
}
|
||||
|
||||
void OnResult(const LDAPResult &r) anope_override
|
||||
{
|
||||
std::map<LDAPQuery, Anope::string>::iterator it = this->requests.find(r.id);
|
||||
if (it == this->requests.end())
|
||||
return;
|
||||
User *u = User::Find(it->second);
|
||||
this->requests.erase(it);
|
||||
|
||||
|
||||
if (!u || !u->Account())
|
||||
return;
|
||||
|
||||
@@ -50,7 +38,7 @@ class IdentifyInterface : public LDAPInterface
|
||||
o = new Oper(u->nick, ot);
|
||||
my_opers.insert(o);
|
||||
nc->o = o;
|
||||
Log(this->owner) << "m_ldap_oper: Tied " << u->nick << " (" << nc->display << ") to opertype " << ot->GetName();
|
||||
Log(this->owner) << "Tied " << u->nick << " (" << nc->display << ") to opertype " << ot->GetName();
|
||||
}
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
@@ -64,21 +52,24 @@ class IdentifyInterface : public LDAPInterface
|
||||
}
|
||||
nc->o = NULL;
|
||||
|
||||
Log() << "Removed services operator from " << u->nick << " (" << nc->display << ")";
|
||||
Log(this->owner) << "Removed services operator from " << u->nick << " (" << nc->display << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnError(const LDAPResult &r) anope_override
|
||||
{
|
||||
this->requests.erase(r.id);
|
||||
}
|
||||
|
||||
void OnDelete() anope_override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
class LDAPOper : public Module
|
||||
{
|
||||
ServiceReference<LDAPProvider> ldap;
|
||||
IdentifyInterface iinterface;
|
||||
|
||||
Anope::string binddn;
|
||||
Anope::string password;
|
||||
@@ -86,7 +77,7 @@ class LDAPOper : public Module
|
||||
Anope::string filter;
|
||||
public:
|
||||
LDAPOper(const Anope::string &modname, const Anope::string &creator) :
|
||||
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), iinterface(this)
|
||||
Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main")
|
||||
{
|
||||
|
||||
}
|
||||
@@ -117,8 +108,7 @@ class LDAPOper : public Module
|
||||
|
||||
if (!this->binddn.empty())
|
||||
this->ldap->Bind(NULL, this->binddn.replace_all_cs("%a", u->Account()->display), this->password.c_str());
|
||||
LDAPQuery id = this->ldap->Search(&this->iinterface, this->basedn, this->filter.replace_all_cs("%a", u->Account()->display));
|
||||
this->iinterface.Add(id, u->nick);
|
||||
this->ldap->Search(new IdentifyInterface(this, u), this->basedn, this->filter.replace_all_cs("%a", u->Account()->display));
|
||||
}
|
||||
catch (const LDAPException &ex)
|
||||
{
|
||||
|
||||
@@ -157,7 +157,7 @@ class DHAES : public Mechanism
|
||||
std::string username = &decrypted[0];
|
||||
std::string password = &decrypted[username.length() + 1];
|
||||
|
||||
if (username.empty() || password.empty())
|
||||
if (username.empty() || password.empty() || !IRCD->IsNickValid(username) || password.find_first_of("\r\n") != Anope::string::npos)
|
||||
return Err(sess, pubkey);
|
||||
|
||||
SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password);
|
||||
|
||||
@@ -152,7 +152,7 @@ class DHBS : public Mechanism
|
||||
const Anope::string username = reinterpret_cast<const char*>(&data[pos]);
|
||||
// Check that the username is valid, and that we have at least one block of data
|
||||
// 2 + 1 + 8 = uint16_t size for keylen, \0 for username, 8 for one block of data
|
||||
if (username.empty() || username.length() + keysize + 2 + 1 + 8 > decodedlen)
|
||||
if (username.empty() || username.length() + keysize + 2 + 1 + 8 > decodedlen || !IRCD->IsNickValid(username))
|
||||
return Err(sess, pubkey);
|
||||
|
||||
pos += username.length() + 1;
|
||||
@@ -167,7 +167,7 @@ class DHBS : public Mechanism
|
||||
BF_ecb_encrypt(&data[pos + i], reinterpret_cast<unsigned char*>(&decrypted[i]), &BFKey, BF_DECRYPT);
|
||||
|
||||
std::string password = &decrypted[0];
|
||||
if (password.empty())
|
||||
if (password.empty() || password.find_first_of("\r\n") != Anope::string::npos)
|
||||
return Err(sess, pubkey);
|
||||
|
||||
SASL::IdentifyRequest* req = new SASL::IdentifyRequest(this->owner, m.source, username, password);
|
||||
|
||||
@@ -103,6 +103,10 @@ class SSLModule : public Module
|
||||
if (!client_ctx || !server_ctx)
|
||||
throw ModuleException("Error initializing SSL CTX");
|
||||
|
||||
long opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE;
|
||||
SSL_CTX_set_options(client_ctx, opts);
|
||||
SSL_CTX_set_options(server_ctx, opts);
|
||||
|
||||
SSL_CTX_set_mode(client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
SSL_CTX_set_mode(server_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
|
||||
@@ -158,6 +162,20 @@ class SSLModule : public Module
|
||||
Log() << "Unable to open private key " << this->keyfile;
|
||||
}
|
||||
|
||||
// Allow disabling SSLv3
|
||||
if (!config->Get<Anope::string>("sslv3").empty())
|
||||
{
|
||||
if (config->Get<bool>("sslv3"))
|
||||
{
|
||||
SSL_CTX_clear_options(client_ctx, SSL_OP_NO_SSLv3);
|
||||
SSL_CTX_clear_options(server_ctx, SSL_OP_NO_SSLv3);
|
||||
}
|
||||
else
|
||||
{
|
||||
SSL_CTX_set_options(client_ctx, SSL_OP_NO_SSLv3);
|
||||
SSL_CTX_set_options(server_ctx, SSL_OP_NO_SSLv3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnPreServerConnect() anope_override
|
||||
|
||||
@@ -243,7 +243,7 @@ void IRC2SQL::OnLeaveChannel(User *u, Channel *c)
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void IRC2SQL::OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic)
|
||||
void IRC2SQL::OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic)
|
||||
{
|
||||
query = "UPDATE `" + prefix + "chan` "
|
||||
"SET topic=@topic@, topicauthor=@author@, topictime=FROM_UNIXTIME(@time@) "
|
||||
|
||||
@@ -69,7 +69,7 @@ class IRC2SQL : public Module
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) anope_override;
|
||||
EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) anope_override;
|
||||
|
||||
void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override;
|
||||
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override;
|
||||
|
||||
void OnBotNotice(User *u, BotInfo *bi, Anope::string &message) anope_override;
|
||||
};
|
||||
|
||||
@@ -309,7 +309,7 @@ class MChanstats : public Module
|
||||
"KEY `nick` (`nick`),"
|
||||
"KEY `chan_` (`chan`),"
|
||||
"KEY `type` (`type`)"
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8;";
|
||||
") ENGINE=MyISAM DEFAULT CHARSET=utf8;";
|
||||
this->RunQuery(query);
|
||||
}
|
||||
/* There is no CREATE OR REPLACE PROCEDURE in MySQL */
|
||||
@@ -517,14 +517,13 @@ class MChanstats : public Module
|
||||
info.AddOption(_("Chanstats"));
|
||||
}
|
||||
|
||||
void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
|
||||
void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
|
||||
{
|
||||
User *u = User::Find(user);
|
||||
if (!u || !u->Account() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
if (!source || !source->Account() || !c->ci || !cs_stats.HasExt(c->ci))
|
||||
return;
|
||||
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
|
||||
query.SetValue("channel", c->name);
|
||||
query.SetValue("nick", GetDisplay(u));
|
||||
query.SetValue("nick", GetDisplay(source));
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
|
||||
+23
-7
@@ -103,12 +103,28 @@ class Fantasy : public Module
|
||||
std::vector<Anope::string> params;
|
||||
spacesepstream(msg).GetTokens(params);
|
||||
|
||||
if (!msg.find(c->ci->bi->nick))
|
||||
params.erase(params.begin());
|
||||
else if (!msg.find_first_of(Config->GetModule(this)->Get<const Anope::string>("fantasycharacter", "!")))
|
||||
params[0].erase(params[0].begin());
|
||||
else
|
||||
if (params.empty())
|
||||
return;
|
||||
|
||||
Anope::string normalized_param0 = Anope::NormalizeBuffer(params[0]);
|
||||
Anope::string fantasy_chars = Config->GetModule(this)->Get<Anope::string>("fantasycharacter", "!");
|
||||
|
||||
if (!normalized_param0.find(c->ci->bi->nick))
|
||||
{
|
||||
params.erase(params.begin());
|
||||
}
|
||||
else if (!normalized_param0.find_first_of(fantasy_chars))
|
||||
{
|
||||
size_t sz = params[0].find_first_of(fantasy_chars);
|
||||
if (sz == Anope::string::npos)
|
||||
return; /* normalized_param0 is a subset of params[0] so this can't happen */
|
||||
|
||||
params[0].erase(0, sz + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (params.empty())
|
||||
return;
|
||||
@@ -123,7 +139,7 @@ class Fantasy : public Module
|
||||
full_command.erase(full_command.begin());
|
||||
|
||||
++count;
|
||||
it = Config->Fantasy.find(full_command);
|
||||
it = Config->Fantasy.find(Anope::NormalizeBuffer(full_command));
|
||||
}
|
||||
|
||||
if (it == Config->Fantasy.end())
|
||||
@@ -163,7 +179,7 @@ class Fantasy : public Module
|
||||
source.permission = info.permission;
|
||||
|
||||
AccessGroup ag = c->ci->AccessFor(u);
|
||||
bool has_fantasia = ag.HasPriv("FANTASIA") || source.HasPriv("chanserv/administration");
|
||||
bool has_fantasia = ag.HasPriv("FANTASIA") || source.HasPriv("botserv/fantasy");
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
if (has_fantasia)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user