mirror of
https://github.com/anope/anope.git
synced 2026-06-28 16:36:39 +02:00
Made gettext work on most OSs. Tested on Debian, FreeBSD, Gentoo, and Windows.
Added a search path option to the Config script for cmake to use when finding libraries for modules or for gettext. Fixed m_mysql and m_ssl to work under Windows, made the Windows Config program remember the last used options, and fixed Windows release builds.
This commit is contained in:
@@ -207,6 +207,12 @@ else(CMAKE244_OR_BETTER)
|
||||
include(TestCXXAcceptsFlag)
|
||||
endif(CMAKE244_OR_BETTER)
|
||||
|
||||
# If extra directories were specified, tell cmake about them.
|
||||
if(EXTRA_INCLUDE)
|
||||
include_directories(${EXTRA_INCLUDE})
|
||||
link_directories(${EXTRA_INCLUDE})
|
||||
endif(EXTRA_INCLUDE)
|
||||
|
||||
# Find gettext
|
||||
find_package(Gettext)
|
||||
|
||||
|
||||
@@ -320,9 +320,10 @@ echo ""
|
||||
|
||||
####
|
||||
|
||||
echo "Are there any extra arguments you wish to pass to $BUILD_SYSTEM?"
|
||||
echo "(You may only need to do this if $BUILD_SYSTEM is unable to locate"
|
||||
echo "missing dependencies without hints)"
|
||||
echo "Are there any extra arguments you wish to pass to cmake?"
|
||||
echo "You may only need to do this if cmake is unable to locate"
|
||||
echo "missing dependencies without hints."
|
||||
echo "You can do this by: -DEXTRA_INCLUDE:STRING=/path/to/files;/path/to/more/files"
|
||||
echo2 "[$EXTRA_CONFIG_ARGS] "
|
||||
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
|
||||
if [ "$INPUT" ] ; then
|
||||
|
||||
BIN
Binary file not shown.
+4
-4
@@ -386,9 +386,9 @@ macro(calculate_depends SRC SKIP)
|
||||
if(CHECK_ANGLE_INCLUDES)
|
||||
# Find the path of the include file
|
||||
if(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
|
||||
find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/include $ENV{VCINSTALLDIR}/include)
|
||||
find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/include $ENV{VCINSTALLDIR}/include ${EXTRA_INCLUDE})
|
||||
else(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
|
||||
find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME})
|
||||
find_path(FOUND_${FILENAME}_INCLUDE NAMES ${FILENAME} ${EXTRA_INCLUDE})
|
||||
endif(DEFAULT_INCLUDE_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
|
||||
# If the include file was found, add it's path to the list of include paths, but only if it doesn't already exist and isn't in the defaults for the compiler
|
||||
if(FOUND_${FILENAME}_INCLUDE)
|
||||
@@ -437,9 +437,9 @@ macro(calculate_libraries SRC SKIP SRC_LDFLAGS EXTRA_DEPENDS)
|
||||
foreach(LIBRARY ${REQUIRED_LIBRARY})
|
||||
# Locate the library to see if it exists
|
||||
if(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
|
||||
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib)
|
||||
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib ${EXTRA_INCLUDE})
|
||||
else(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
|
||||
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY})
|
||||
find_library(FOUND_${LIBRARY}_LIBRARY NAMES ${LIBRARY} ${EXTRA_INCLUDE})
|
||||
endif(DEFAULT_LIBRARY_DIRS OR WSDK_PATH OR DEFINED $ENV{VCINSTALLDIR})
|
||||
# If the library was found, we will add it to the linker flags
|
||||
if(FOUND_${LIBRARY}_LIBRARY)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Find the header files, libs, and executables for gettext
|
||||
if(NOT WIN32)
|
||||
find_path(GETTEXT_INCLUDE libintl.h /usr/include /usr/local/include ${EXTRA_INCLUDE})
|
||||
find_library(GETTEXT_LIBRARY intl PATHS /usr/lib /usr/lib64 ${EXTRA_INCLUDE})
|
||||
find_program(GETTEXT_MSGFMT msgfmt PATHS /usr/bin/ /usr/local/bin ${EXTRA_INCLUDE})
|
||||
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_INCLUDE})
|
||||
find_library(ICONV_LIBRARY libiconv PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_INCLUDE})
|
||||
find_library(MINGWEX_LIBRARY libmingwex PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_INCLUDE})
|
||||
find_library(GCC_LIBRARY libgcc PATHS ${DEFAULT_LIBRARY_DIRS} ${WSDK_PATH}/lib $ENV{VCINSTALLDIR}/lib gettext/lib ${EXTRA_INCLUDE})
|
||||
find_program(GETTEXT_MSGFMT msgfmt PATHS ${DEFAULT_INCLUDE_DIRS} ${WSDK_PATH}/bin $ENV{VCINSTALLDIR}/bin gettext/bin ${EXTRA_INCLUDE})
|
||||
endif(NOT WIN32)
|
||||
|
||||
# If we found everything we need set variables correctly for lang/CMakeLists.txt to use
|
||||
if(GETTEXT_INCLUDE AND GETTEXT_MSGFMT AND (NOT WIN32 OR (ICONV_LIBRARY AND MINGWEX_LIBRARY AND GCC_LIBRARY)))
|
||||
set(GETTEXT_FOUND TRUE)
|
||||
set(LIBINTL_INCLUDE "${GETTEXT_INCLUDE}/libintl.h")
|
||||
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})
|
||||
endif(GETTEXT_LIBRARY)
|
||||
endif(WIN32)
|
||||
endif(GETTEXT_INCLUDE AND GETTEXT_MSGFMT AND (NOT WIN32 OR (ICONV_LIBRARY AND MINGWEX_LIBRARY AND GCC_LIBRARY)))
|
||||
@@ -1639,6 +1639,23 @@ module { name = "ns_maxemail" }
|
||||
*/
|
||||
module { name = "m_ssl" }
|
||||
|
||||
/*
|
||||
* m_mysql
|
||||
*
|
||||
* This module allows other modules (db_mysql) to use MySQL.
|
||||
* Be sure you have imported the table schema with mydbgen before
|
||||
* trying to use MySQL
|
||||
*/
|
||||
#module { name = "m_mysql" }
|
||||
mysql
|
||||
{
|
||||
database = "anope";
|
||||
server = "127.0.0.1";
|
||||
username = "anope";
|
||||
password = "mypassword";
|
||||
port = 3306;
|
||||
}
|
||||
|
||||
/*
|
||||
* db_plain
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ Anope Mutli Language Support
|
||||
install gettext and run `msginit -l language -o anope.language.po -i anope.pot`. For example if I was translating to
|
||||
Spanish I could run `msginit -l es_ES -o anope.es_ES.po -i anope.pot`. Open the newly generating .po file and start
|
||||
translating. Once you are done simply rerun ./Config; make && make install and add the language to your services.conf.
|
||||
Note that on Windows it is not quite this simple, windows.cpp must be edited and Anope recompiled and restarted.
|
||||
|
||||
Poedit (http://www.poedit.net/) is a popular po file editor, and we recommend using it or another editor designed to edit
|
||||
po files (especially on Windows).
|
||||
|
||||
@@ -91,6 +91,23 @@ Anope for Windows
|
||||
If you cannot find whats causing the error, please visit our forums or
|
||||
our IRC Support channel for assistance.
|
||||
|
||||
Some Anope modules require third party libraries, such as m_mysql and
|
||||
m_ssl. 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:
|
||||
|
||||
-DEXTRA_INCLUDES:STRING=c:/openssl/include;c:/openssl/lib
|
||||
|
||||
Which would have cmake search both C:\openssl\include and
|
||||
C:\openssl\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://someurlwhichidonthaveXXX.
|
||||
The OpenSSL and MySQL header files and libraries are also included in
|
||||
this package. Once downloaded and extracted, you should pass the include,
|
||||
bin, and lib paths to cmake as seen above.
|
||||
|
||||
5) You are now ready to compile. If you said you wanted to use NMake in step 4,
|
||||
at the prompt type:
|
||||
|
||||
|
||||
+3
-2
@@ -155,10 +155,11 @@ E void pmodule_ircd_var(IRCDVar *ircdvar);
|
||||
/**** language.cpp ****/
|
||||
E std::vector<Anope::string> languages;
|
||||
E void InitLanguages();
|
||||
E const Anope::string GetString(Anope::string language, LanguageString string);
|
||||
E const Anope::string GetString(const Anope::string &language, LanguageString string);
|
||||
E const Anope::string GetString(LanguageString string);
|
||||
E const Anope::string GetString(const NickCore *nc, LanguageString string);
|
||||
E const Anope::string GetString(const User *u, LanguageString string);
|
||||
E const Anope::string GetString(const char *domain, Anope::string language, const Anope::string &string);
|
||||
E Anope::string language_strings[LANG_STRING_COUNT];
|
||||
E void SyntaxError(BotInfo *bi, User *u, const Anope::string &command, LanguageString message);
|
||||
|
||||
@@ -190,7 +191,7 @@ E void sighandler(int signum);
|
||||
E void do_restart_services();
|
||||
|
||||
/* The socket to our uplink */
|
||||
class UplinkSocket : public ConnectionSocket
|
||||
class CoreExport UplinkSocket : public ConnectionSocket
|
||||
{
|
||||
public:
|
||||
UplinkSocket(bool ipv6 = false);
|
||||
|
||||
+4
-4
@@ -359,11 +359,11 @@ class StackerInfo
|
||||
BotInfo *bi;
|
||||
|
||||
/** Add a mode to this object
|
||||
* @param Mode The mode
|
||||
* @param mode The mode
|
||||
* @param Set true if setting, false if unsetting
|
||||
* @param Param The param for the mode
|
||||
*/
|
||||
void AddMode(Base *Mode, bool Set, const Anope::string &Param);
|
||||
void AddMode(Mode *mode, bool Set, const Anope::string &Param);
|
||||
};
|
||||
|
||||
/** This is mode manager
|
||||
@@ -393,12 +393,12 @@ class CoreExport ModeManager
|
||||
/** Really add a mode to the stacker, internal use only
|
||||
* @param bi The client to set the modes from
|
||||
* @param Object The object, user/channel
|
||||
* @param Mode The mode
|
||||
* @param mode The mode
|
||||
* @param Set Adding or removing?
|
||||
* @param Param A param, if there is one
|
||||
* @param Type The type this is, user or channel
|
||||
*/
|
||||
static void StackerAddInternal(BotInfo *bi, Base *Object, Base *Mode, bool Set, const Anope::string &Param, StackerType Type);
|
||||
static void StackerAddInternal(BotInfo *bi, Base *Object, Mode *mode, bool Set, const Anope::string &Param, StackerType Type);
|
||||
|
||||
public:
|
||||
/* List of all modes Anope knows about */
|
||||
|
||||
+1
-1
@@ -1223,7 +1223,7 @@ class CallBack : public Timer
|
||||
}
|
||||
};
|
||||
|
||||
class Service : public virtual Base
|
||||
class CoreExport Service : public virtual Base
|
||||
{
|
||||
public:
|
||||
Module *owner;
|
||||
|
||||
+2
-1
@@ -81,6 +81,7 @@
|
||||
# define unsetenv(x) SetEnvironmentVariable(x, NULL)
|
||||
# define MARK_DEPRECATED
|
||||
|
||||
extern CoreExport USHORT WindowsGetLanguage(const char *lang);
|
||||
extern CoreExport int inet_pton(int af, const char *src, void *dst);
|
||||
extern CoreExport const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
@@ -482,7 +483,7 @@ class Memo : public Flags<MemoFlag>
|
||||
Anope::string text;
|
||||
};
|
||||
|
||||
struct MemoInfo
|
||||
struct CoreExport MemoInfo
|
||||
{
|
||||
unsigned memomax;
|
||||
std::vector<Memo *> memos;
|
||||
|
||||
+2
-2
@@ -114,7 +114,7 @@ class ClientSocket;
|
||||
class ListenSocket;
|
||||
class ConnectionSocket;
|
||||
|
||||
class SocketIO
|
||||
class CoreExport SocketIO
|
||||
{
|
||||
public:
|
||||
/** Receive something from the buffer
|
||||
@@ -306,7 +306,7 @@ class CoreExport ListenSocket : public Socket
|
||||
virtual ClientSocket *OnAccept(int fd, const sockaddrs &addr);
|
||||
};
|
||||
|
||||
class ConnectionSocket : public BufferedSocket
|
||||
class CoreExport ConnectionSocket : public BufferedSocket
|
||||
{
|
||||
public:
|
||||
/* Sockaddrs for bindip (if there is one) */
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#cmakedefine HAVE_EVENTFD 1
|
||||
#cmakedefine GETTEXT_FOUND 1
|
||||
#cmakedefine RUNGROUP "@RUNGROUP@"
|
||||
#define LIBINTL "@LIBINTL_INCLUDE@"
|
||||
|
||||
#cmakedefine HAVE_UINT8_T 1
|
||||
#cmakedefine HAVE_U_INT8_T 1
|
||||
|
||||
@@ -17,7 +17,7 @@ class Thread;
|
||||
|
||||
extern CoreExport ThreadEngine threadEngine;
|
||||
|
||||
class ThreadEngine
|
||||
class CoreExport ThreadEngine
|
||||
{
|
||||
public:
|
||||
/* Vector of threads */
|
||||
@@ -41,7 +41,7 @@ class ThreadEngine
|
||||
void Process();
|
||||
};
|
||||
|
||||
class Thread : public Extensible
|
||||
class CoreExport Thread : public Extensible
|
||||
{
|
||||
private:
|
||||
/* Set to true to tell the thread to finish and we are waiting for it */
|
||||
@@ -77,7 +77,7 @@ class Thread : public Extensible
|
||||
virtual void Run();
|
||||
};
|
||||
|
||||
class Mutex
|
||||
class CoreExport Mutex
|
||||
{
|
||||
protected:
|
||||
/* A mutex, used to keep threads in sync */
|
||||
@@ -101,7 +101,7 @@ class Mutex
|
||||
void Unlock();
|
||||
};
|
||||
|
||||
class Condition : public Mutex
|
||||
class CoreExport Condition : public Mutex
|
||||
{
|
||||
private:
|
||||
/* A condition */
|
||||
|
||||
@@ -68,7 +68,7 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS})
|
||||
endif(MSVC)
|
||||
# Generate the module and set it's linker flags, also set it to depend on the main Anope executable to be built beforehand
|
||||
add_library(${SO} MODULE ${SRC})
|
||||
set_target_properties(${SO} PROPERTIES LINKER_LANGUAGE CXX PREFIX "" SUFFIX "" LINK_FLAGS "${TEMP_LDFLAGS}")
|
||||
set_target_properties(${SO} PROPERTIES LINKER_LANGUAGE CXX PREFIX "" SUFFIX "" LINK_FLAGS "${TEMP_LDFLAGS} /nodefaultlib:\"libcmt.lib\"")
|
||||
add_dependencies(${SO} ${PROGRAM_NAME})
|
||||
# For Windows only, have the module link to the export library of Anope as well as the wsock32 library (most of the modules probably don't need this, but this is to be on the safe side), also set it's version
|
||||
if(WIN32)
|
||||
|
||||
@@ -1429,7 +1429,7 @@ static void SaveDatabases()
|
||||
|
||||
for (std::vector<Anope::string>::iterator it = nc->access.begin(), it_end = nc->access.end(); it != it_end; ++it)
|
||||
{
|
||||
me->RunQuery("INSERT INTO `anope_ns_access` (display, access) VALUES(" + me->Escape(nc->display) + ", " + me->Escape(*it) + ")");
|
||||
me->RunQuery("INSERT INTO `anope_ns_access` (display, access) VALUES('" + me->Escape(nc->display) + "', '" + me->Escape(*it) + "')");
|
||||
}
|
||||
|
||||
for (unsigned j = 0, end = nc->memos.memos.size(); j < end; ++j)
|
||||
|
||||
+12
-12
@@ -24,21 +24,21 @@ struct QueryRequest
|
||||
/* The connection to the database */
|
||||
MySQLService *service;
|
||||
/* The interface to use once we have the result to send the data back */
|
||||
SQLInterface *interface;
|
||||
SQLInterface *sqlinterface;
|
||||
/* The actual query */
|
||||
Anope::string query;
|
||||
|
||||
QueryRequest(MySQLService *s, SQLInterface *i, const Anope::string &q) : service(s), interface(i), query(q) { }
|
||||
QueryRequest(MySQLService *s, SQLInterface *i, const Anope::string &q) : service(s), sqlinterface(i), query(q) { }
|
||||
};
|
||||
|
||||
struct QueryResult
|
||||
{
|
||||
/* The interface to send the data back on */
|
||||
SQLInterface *interface;
|
||||
SQLInterface *sqlinterface;
|
||||
/* The result */
|
||||
SQLResult result;
|
||||
|
||||
QueryResult(SQLInterface *i, SQLResult &r) : interface(i), result(r) { }
|
||||
QueryResult(SQLInterface *i, SQLResult &r) : sqlinterface(i), result(r) { }
|
||||
};
|
||||
|
||||
/** A MySQL result
|
||||
@@ -255,7 +255,7 @@ class ModuleSQL : public Module
|
||||
{
|
||||
QueryRequest &r = this->QueryRequests[i - 1];
|
||||
|
||||
if (r.interface && r.interface->owner == m)
|
||||
if (r.sqlinterface && r.sqlinterface->owner == m)
|
||||
{
|
||||
if (i == 1)
|
||||
{
|
||||
@@ -290,8 +290,8 @@ MySQLService::~MySQLService()
|
||||
|
||||
if (r.service == this)
|
||||
{
|
||||
if (r.interface)
|
||||
r.interface->OnError(SQLResult("", "SQL Interface is going away"));
|
||||
if (r.sqlinterface)
|
||||
r.sqlinterface->OnError(SQLResult("", "SQL Interface is going away"));
|
||||
me->QueryRequests.erase(me->QueryRequests.begin() + i - 1);
|
||||
}
|
||||
}
|
||||
@@ -377,8 +377,8 @@ void DispatcherThread::Run()
|
||||
this->Lock();
|
||||
if (!me->QueryRequests.empty() && me->QueryRequests.front().query == r.query)
|
||||
{
|
||||
if (r.interface)
|
||||
me->FinishedRequests.push_back(QueryResult(r.interface, sresult));
|
||||
if (r.sqlinterface)
|
||||
me->FinishedRequests.push_back(QueryResult(r.sqlinterface, sresult));
|
||||
me->QueryRequests.pop_front();
|
||||
}
|
||||
}
|
||||
@@ -401,13 +401,13 @@ void MySQLPipe::OnNotify()
|
||||
{
|
||||
const QueryResult &qr = *it;
|
||||
|
||||
if (!qr.interface)
|
||||
if (!qr.sqlinterface)
|
||||
throw SQLException("NULL qr.interface in MySQLPipe::OnNotify() ?");
|
||||
|
||||
if (qr.result.GetError().empty())
|
||||
qr.interface->OnResult(qr.result);
|
||||
qr.sqlinterface->OnResult(qr.result);
|
||||
else
|
||||
qr.interface->OnError(qr.result);
|
||||
qr.sqlinterface->OnError(qr.result);
|
||||
}
|
||||
me->FinishedRequests.clear();
|
||||
|
||||
|
||||
+5
-1
@@ -79,8 +79,12 @@ add_executable(${PROGRAM_NAME} ${SRC_SRCS})
|
||||
set_target_properties(${PROGRAM_NAME} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}" ENABLE_EXPORTS ON)
|
||||
# On Windows, also link Anope to the wsock32 and Ws2_32 library, as well as set the version
|
||||
if(WIN32)
|
||||
target_link_libraries(${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
|
||||
target_link_libraries(${PROGRAM_NAME} wsock32 Ws2_32 ${GETTEXT_LIBRARIES} ${WIN32_MEMORY})
|
||||
set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
|
||||
else(WIN32)
|
||||
if(GETTEXT_LIBRARIES)
|
||||
target_link_libraries(${PROGRAM_NAME} ${GETTEXT_LIBRARIES})
|
||||
endif(GETTEXT_LIBRARIES)
|
||||
endif(WIN32)
|
||||
# Building the Anope executable requires the language files to be compiled first as well as the version.h header to be generated
|
||||
add_dependencies(${PROGRAM_NAME} language headers)
|
||||
|
||||
+1
-10
@@ -138,16 +138,7 @@ if test "x$FAILED" = "x" ; then
|
||||
echo ""
|
||||
echo "Your MySQL setup is complete and your Anope schema is up to date. Make"
|
||||
echo "sure you configure MySQL on your services.conf file prior to launching"
|
||||
echo "Anope with MySQL support. Your configuration values are:"
|
||||
echo ""
|
||||
echo "mysql"
|
||||
echo "{"
|
||||
echo " database = \"$SQLDB\""
|
||||
echo " server = \"$SQLHOST\""
|
||||
echo " username = \"$SQLUSER\""
|
||||
echo " password = \"$SQLPASS\""
|
||||
echo " port = \"$SQLPORT\""
|
||||
echo "}"
|
||||
echo "Anope with MySQL support."
|
||||
echo ""
|
||||
else
|
||||
echo "The following operations failed:"
|
||||
|
||||
+51
-30
@@ -1,7 +1,7 @@
|
||||
#include "services.h"
|
||||
|
||||
#if GETTEXT_FOUND
|
||||
# include <libintl.h>
|
||||
# include LIBINTL
|
||||
# define _(x) gettext(x)
|
||||
#else
|
||||
# define _(x) x
|
||||
@@ -38,40 +38,14 @@ void InitLanguages()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if GETTEXT_FOUND
|
||||
/* Used by gettext to make it always dynamically load language strings (so we can drop them in while Anope is running) */
|
||||
extern "C" int _nl_msg_cat_cntr;
|
||||
#endif
|
||||
const Anope::string GetString(Anope::string language, LanguageString string)
|
||||
const Anope::string GetString(const Anope::string &language, LanguageString string)
|
||||
{
|
||||
#if GETTEXT_FOUND
|
||||
/* For older databases */
|
||||
if (language == "en")
|
||||
language.clear();
|
||||
|
||||
/* Apply def language */
|
||||
if (language.empty() && !Config->NSDefLanguage.empty())
|
||||
language = Config->NSDefLanguage;
|
||||
|
||||
if (language.empty())
|
||||
#endif
|
||||
return language_strings[string];
|
||||
|
||||
#if GETTEXT_FOUND
|
||||
++_nl_msg_cat_cntr;
|
||||
setenv("LANGUAGE", language.c_str(), 1);
|
||||
setlocale(LC_ALL, language.c_str()); // This is only required by some systems, but must not be C or POSIX
|
||||
const char *ret = dgettext("anope", language_strings[string].c_str());
|
||||
unsetenv("LANGUAGE");
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
return ret ? ret : "";
|
||||
#endif
|
||||
return GetString("anope", language, language_strings[string]);
|
||||
}
|
||||
|
||||
const Anope::string GetString(LanguageString string)
|
||||
{
|
||||
return GetString("", string);
|
||||
return GetString("anope", "", language_strings[string]);
|
||||
}
|
||||
|
||||
const Anope::string GetString(const NickCore *nc, LanguageString string)
|
||||
@@ -90,6 +64,53 @@ const Anope::string GetString(const User *u, LanguageString string)
|
||||
return GetString(nc ? nc : (na ? na->nc : NULL), string);
|
||||
}
|
||||
|
||||
#if GETTEXT_FOUND
|
||||
/* Used by gettext to make it always dynamically load language strings (so we can drop them in while Anope is running) */
|
||||
extern "C" int _nl_msg_cat_cntr;
|
||||
const Anope::string GetString(const char *domain, Anope::string language, const Anope::string &string)
|
||||
{
|
||||
if (language == "en")
|
||||
language.clear();
|
||||
|
||||
/* Apply def language */
|
||||
if (language.empty() && !Config->NSDefLanguage.empty())
|
||||
language = Config->NSDefLanguage;
|
||||
|
||||
if (language.empty())
|
||||
return string;
|
||||
|
||||
++_nl_msg_cat_cntr;
|
||||
#ifdef _WIN32
|
||||
SetThreadLocale(MAKELCID(MAKELANGID(WindowsGetLanguage(language.c_str()), SUBLANG_DEFAULT), SORT_DEFAULT));
|
||||
#else
|
||||
/* First, set LANGUAGE env variable.
|
||||
* Some systems (Debian) don't care about this, so we must setlocale LC_ALL aswell.
|
||||
* BUT if this call fails because the LANGUAGE env variable is set, setlocale resets
|
||||
* the locale to "C", which short circuits gettext and causes it to fail on systems that
|
||||
* use the LANGUAGE env variable. We must reset the locale to en_US (or, anything not
|
||||
* C or POSIX) then.
|
||||
*/
|
||||
setenv("LANGUAGE", language.c_str(), 1);
|
||||
if (setlocale(LC_ALL, language.c_str()) == NULL)
|
||||
setlocale(LC_ALL, "en_US");
|
||||
#endif
|
||||
const char *ret = dgettext(domain, string.c_str());
|
||||
#ifdef _WIN32
|
||||
SetThreadLocale(MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT));
|
||||
#else
|
||||
unsetenv("LANGUAGE");
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
|
||||
return ret ? ret : "";
|
||||
}
|
||||
#else
|
||||
const Anope::string GetString(const char *domain, const Anope::string &language, const Anope::string &string)
|
||||
{
|
||||
return language_strings[string];
|
||||
}
|
||||
#endif
|
||||
|
||||
void SyntaxError(BotInfo *bi, User *u, const Anope::string &command, LanguageString message)
|
||||
{
|
||||
if (!bi || !u || command.empty())
|
||||
|
||||
+16
-16
@@ -441,7 +441,7 @@ void ChannelModeInvex::DelMask(Channel *chan, const Anope::string &mask)
|
||||
}
|
||||
}
|
||||
|
||||
void StackerInfo::AddMode(Base *Mode, bool Set, const Anope::string &Param)
|
||||
void StackerInfo::AddMode(Mode *mode, bool Set, const Anope::string &Param)
|
||||
{
|
||||
ChannelMode *cm = NULL;
|
||||
UserMode *um = NULL;
|
||||
@@ -449,13 +449,13 @@ void StackerInfo::AddMode(Base *Mode, bool Set, const Anope::string &Param)
|
||||
|
||||
if (Type == ST_CHANNEL)
|
||||
{
|
||||
cm = debug_cast<ChannelMode *>(Mode);
|
||||
cm = debug_cast<ChannelMode *>(mode);
|
||||
if (cm->Type == MODE_PARAM)
|
||||
IsParam = true;
|
||||
}
|
||||
else if (Type == ST_USER)
|
||||
{
|
||||
um = debug_cast<UserMode *>(Mode);
|
||||
um = debug_cast<UserMode *>(mode);
|
||||
if (um->Type == MODE_PARAM)
|
||||
IsParam = true;
|
||||
}
|
||||
@@ -478,7 +478,7 @@ void StackerInfo::AddMode(Base *Mode, bool Set, const Anope::string &Param)
|
||||
/* The param must match too (can have multiple status or list modes), but
|
||||
* if it is a param mode it can match no matter what the param is
|
||||
*/
|
||||
if (it->first == Mode && (Param.equals_cs(it->second) || IsParam))
|
||||
if (it->first == mode && (Param.equals_cs(it->second) || IsParam))
|
||||
{
|
||||
list->erase(it);
|
||||
/* It can only be on this list once */
|
||||
@@ -491,7 +491,7 @@ void StackerInfo::AddMode(Base *Mode, bool Set, const Anope::string &Param)
|
||||
/* The param must match too (can have multiple status or list modes), but
|
||||
* if it is a param mode it can match no matter what the param is
|
||||
*/
|
||||
if (it->first == Mode && (Param.equals_cs(it->second) || IsParam))
|
||||
if (it->first == mode && (Param.equals_cs(it->second) || IsParam))
|
||||
{
|
||||
otherlist->erase(it);
|
||||
return;
|
||||
@@ -503,7 +503,7 @@ void StackerInfo::AddMode(Base *Mode, bool Set, const Anope::string &Param)
|
||||
}
|
||||
|
||||
/* Add this mode and its param to our list */
|
||||
list->push_back(std::make_pair(Mode, Param));
|
||||
list->push_back(std::make_pair(mode, Param));
|
||||
}
|
||||
|
||||
/** Get the stacker info for an item, if one doesnt exist it is created
|
||||
@@ -549,12 +549,12 @@ std::list<Anope::string> ModeManager::BuildModeStrings(StackerInfo *info)
|
||||
|
||||
if (info->Type == ST_CHANNEL)
|
||||
{
|
||||
cm = debug_cast<ChannelMode *>(it->first);
|
||||
cm = dynamic_cast<ChannelMode *>(it->first);
|
||||
buf += cm->ModeChar;
|
||||
}
|
||||
else if (info->Type == ST_USER)
|
||||
{
|
||||
um = debug_cast<UserMode *>(it->first);
|
||||
um = dynamic_cast<UserMode *>(it->first);
|
||||
buf += um->ModeChar;
|
||||
}
|
||||
|
||||
@@ -578,12 +578,12 @@ std::list<Anope::string> ModeManager::BuildModeStrings(StackerInfo *info)
|
||||
|
||||
if (info->Type == ST_CHANNEL)
|
||||
{
|
||||
cm = debug_cast<ChannelMode *>(it->first);
|
||||
cm = dynamic_cast<ChannelMode *>(it->first);
|
||||
buf += cm->ModeChar;
|
||||
}
|
||||
else if (info->Type == ST_USER)
|
||||
{
|
||||
um = debug_cast<UserMode *>(it->first);
|
||||
um = dynamic_cast<UserMode *>(it->first);
|
||||
buf += um->ModeChar;
|
||||
}
|
||||
|
||||
@@ -603,20 +603,20 @@ std::list<Anope::string> ModeManager::BuildModeStrings(StackerInfo *info)
|
||||
/** Really add a mode to the stacker, internal use only
|
||||
* @param bi The client to set the modes from
|
||||
* @param Object The object, user/channel
|
||||
* @param Mode The mode
|
||||
* @param mode The mode
|
||||
* @param Set Adding or removing?
|
||||
* @param Param A param, if there is one
|
||||
* @param Type The type this is, user or channel
|
||||
*/
|
||||
void ModeManager::StackerAddInternal(BotInfo *bi, Base *Object, Base *Mode, bool Set, const Anope::string &Param, StackerType Type)
|
||||
void ModeManager::StackerAddInternal(BotInfo *bi, Base *Object, Mode *mode, bool Set, const Anope::string &Param, StackerType Type)
|
||||
{
|
||||
StackerInfo *s = GetInfo(Object);
|
||||
s->Type = Type;
|
||||
s->AddMode(Mode, Set, Param);
|
||||
s->AddMode(mode, Set, Param);
|
||||
if (bi)
|
||||
s->bi = bi;
|
||||
else if (Type == ST_CHANNEL)
|
||||
s->bi = whosends(debug_cast<Channel *>(Object)->ci);
|
||||
s->bi = whosends(dynamic_cast<Channel *>(Object)->ci);
|
||||
else if (Type == ST_USER)
|
||||
s->bi = NULL;
|
||||
}
|
||||
@@ -803,9 +803,9 @@ void ModeManager::ProcessModes()
|
||||
Channel *c = NULL;
|
||||
|
||||
if (s->Type == ST_USER)
|
||||
u = debug_cast<User *>(it->first);
|
||||
u = dynamic_cast<User *>(it->first);
|
||||
else if (s->Type == ST_CHANNEL)
|
||||
c = debug_cast<Channel *>(it->first);
|
||||
c = dynamic_cast<Channel *>(it->first);
|
||||
else
|
||||
throw CoreException("ModeManager::ProcessModes got invalid Stacker Info type");
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
#include "modules.h"
|
||||
|
||||
#ifdef GETTEXT_FOUND
|
||||
# include <libintl.h>
|
||||
# include LIBINTL
|
||||
#endif
|
||||
|
||||
Module::Module(const Anope::string &mname, const Anope::string &creator)
|
||||
|
||||
+3
-27
@@ -12,10 +12,6 @@
|
||||
#include "modules.h"
|
||||
#include "version.h"
|
||||
|
||||
#if GETTEXT_FOUND
|
||||
# include <libintl.h>
|
||||
#endif
|
||||
|
||||
message_map MessageMap;
|
||||
std::list<Module *> Modules;
|
||||
|
||||
@@ -286,36 +282,16 @@ Version Module::GetVersion() const
|
||||
return Version(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
|
||||
}
|
||||
|
||||
#if GETTEXT_FOUND
|
||||
/* Used by gettext to make it always dynamically load language strings (so we can drop them in while Anope is running) */
|
||||
extern "C" int _nl_msg_cat_cntr;
|
||||
#endif
|
||||
void Module::SendMessage(BotInfo *from, User *to, const char *fmt, ...)
|
||||
{
|
||||
Anope::string language = (to && to->Account() ? to->Account()->language : "");
|
||||
/* For older databases */
|
||||
if (language == "en")
|
||||
language.clear();
|
||||
if (language.empty() && !Config->NSDefLanguage.empty())
|
||||
language = Config->NSDefLanguage;
|
||||
|
||||
const char *message = fmt;
|
||||
#if GETTEXT_FOUND
|
||||
if (!language.empty())
|
||||
{
|
||||
++_nl_msg_cat_cntr;
|
||||
setenv("LANGUAGE", language.c_str(), 1);
|
||||
setlocale(LC_ALL, language.c_str()); // This is only required by some systems, but must not be C or POSIX
|
||||
message = dgettext(this->name.c_str(), fmt);
|
||||
unsetenv("LANGUAGE");
|
||||
setlocale(LC_ALL, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
Anope::string message = GetString(this->name.c_str(), language, fmt);
|
||||
|
||||
va_list args;
|
||||
char buf[4096];
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof(buf) - 1, message, args);
|
||||
vsnprintf(buf, sizeof(buf) - 1, message.c_str(), args);
|
||||
va_end(args);
|
||||
|
||||
sepstream sep(buf, '\n');
|
||||
|
||||
+1
-1
@@ -494,7 +494,7 @@ XLine *SGLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_
|
||||
|
||||
Anope::string realreason = reason;
|
||||
if (u && Config->AddAkiller)
|
||||
realreason = "[" + u->nick + "]" + reason;
|
||||
realreason = "[" + u->nick + "] " + reason;
|
||||
|
||||
XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, realreason);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class PipeIO : public SocketIO
|
||||
int Recv(Socket *s, char *buf, size_t sz) const
|
||||
{
|
||||
static char dummy[512];
|
||||
return read(s->GetFD(), &dummy, 512);
|
||||
return recv(s->GetFD(), dummy, 512, 0);
|
||||
}
|
||||
|
||||
/** Write something to the socket
|
||||
@@ -38,7 +38,7 @@ class PipeIO : public SocketIO
|
||||
{
|
||||
static const char dummy = '*';
|
||||
Pipe *pipe = debug_cast<Pipe *>(s);
|
||||
return write(pipe->WritePipe, &dummy, 1);
|
||||
return send(pipe->WritePipe, &dummy, 1, 0);
|
||||
}
|
||||
} pipeSocketIO;
|
||||
|
||||
|
||||
+1
-1
@@ -225,7 +225,7 @@ void SocketIO::Accept(ListenSocket *s)
|
||||
{
|
||||
sockaddrs conaddr;
|
||||
|
||||
socklen_t size = conaddr.size();
|
||||
socklen_t size = sizeof(conaddr);
|
||||
int newsock = accept(s->GetFD(), &conaddr.sa, &size);
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
|
||||
+96
-4
@@ -13,7 +13,7 @@
|
||||
* Written by Scott <stealtharcher.scott@gmail.com>
|
||||
* Written by Adam <Adam@anope.org>
|
||||
*
|
||||
* Compile with: csc /out:Config.exe Config.cs
|
||||
* Compile with: csc /out:../../Config.exe /win32icon:anope-icon.ico Config.cs
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace Config
|
||||
{
|
||||
class Config
|
||||
{
|
||||
static string InstallDirectory, VSVersion, VSShortVer;
|
||||
static bool UseNMake, BuildDebug;
|
||||
static string InstallDirectory, VSVersion, VSShortVer, ExtraArguments;
|
||||
static bool UseNMake = true, BuildDebug = false;
|
||||
|
||||
static bool CheckResponse(string InstallerResponse)
|
||||
{
|
||||
@@ -36,6 +36,78 @@ namespace Config
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool LoadCache()
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] cache = File.ReadAllLines("config.cache");
|
||||
if (cache.Length > 0)
|
||||
Console.WriteLine("Using defaults from config.cache");
|
||||
foreach (string line in cache)
|
||||
{
|
||||
int e = line.IndexOf('=');
|
||||
string name = line.Substring(0, e);
|
||||
string value = line.Substring(e + 1);
|
||||
|
||||
if (name == "INSTDIR")
|
||||
InstallDirectory = value;
|
||||
else if (name == "DEBUG")
|
||||
BuildDebug = CheckResponse(value);
|
||||
else if (name == "USENMAKE")
|
||||
UseNMake = CheckResponse(value);
|
||||
else if (name == "EXTRAARGS")
|
||||
ExtraArguments = value;
|
||||
else if (name == "VSVERSION")
|
||||
VSVersion = value;
|
||||
else if (name == "VSSHORTVER")
|
||||
VSShortVer = value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void SaveCache()
|
||||
{
|
||||
TextWriter tw = new StreamWriter("config.cache");
|
||||
tw.WriteLine("INSTDIR=" + InstallDirectory);
|
||||
tw.WriteLine("DEBUG=" + (BuildDebug ? "yes" : "no"));
|
||||
tw.WriteLine("USENMAKE=" + (UseNMake ? "yes" : "no"));
|
||||
tw.WriteLine("EXTRAARGS=" + ExtraArguments);
|
||||
tw.WriteLine("VSVERSION=" + VSVersion);
|
||||
tw.WriteLine("VSSHORTVER=" + VSShortVer);
|
||||
tw.Close();
|
||||
}
|
||||
|
||||
static string HandleCache(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
Console.Write("[" + InstallDirectory + "] ");
|
||||
return InstallDirectory;
|
||||
case 1:
|
||||
Console.Write("[" + UseNMake + "] ");
|
||||
return (UseNMake ? "yes" : "no");
|
||||
case 2:
|
||||
Console.Write("[" + VSShortVer + "] ");
|
||||
return VSShortVer;
|
||||
case 3:
|
||||
Console.Write("[" + BuildDebug + "] ");
|
||||
return (BuildDebug ? "yes" : "no");
|
||||
case 4:
|
||||
Console.Write("[" + ExtraArguments + "] ");
|
||||
return ExtraArguments;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static string FindAnopeVersion()
|
||||
{
|
||||
@@ -126,18 +198,27 @@ namespace Config
|
||||
Console.WriteLine("Press Enter to begin");
|
||||
Console.WriteLine("");
|
||||
Console.ReadKey();
|
||||
|
||||
bool UseCache = LoadCache();
|
||||
|
||||
Dictionary<int, string> InstallerQuestions = new Dictionary<int, string>();
|
||||
InstallerQuestions.Add(0, "Where do you want Anope to be installed?");
|
||||
InstallerQuestions.Add(1, "Would you like to build using NMake instead of using Visual Studio?\r\nNOTE: If you decide to use NMake, you must be in an environment where\r\nNMake can function, such as the Visual Studio command line. If you say\r\nyes to this while not in an environment that can run NMake, it can\r\ncause the CMake configuration to enter an endless loop. [y/n]");
|
||||
InstallerQuestions.Add(2, "Are you using Visual Studio 2008 or 2010? You can leave this blank\nand have CMake try and auto detect it, but this usually doesn't\nwork correctly. [2008/2010]");
|
||||
InstallerQuestions.Add(3, "Would you like to build a debug version of Anope? [y/n]");
|
||||
InstallerQuestions.Add(4, "Are there any extra arguments you wish to pass to cmake?\nYou may only need to do this if cmake is unable to locate missing dependencies without hints.\nTo do this, set the variable EXTRA_INCLUDE like this: -DEXTRA_INCLUDE:STRING=c:/some/path/include;c:/some/path/bin;c:/some/path/lib");
|
||||
|
||||
for (int i = 0; i < InstallerQuestions.Count; ++i)
|
||||
{
|
||||
Console.WriteLine(InstallerQuestions[i]);
|
||||
string CacheResponse = null;
|
||||
if (UseCache)
|
||||
CacheResponse = HandleCache(i);
|
||||
string InstallerResponse = Console.ReadLine();
|
||||
Console.WriteLine("");
|
||||
|
||||
if (CacheResponse != null && (InstallerResponse == null || InstallerResponse.Length < 1))
|
||||
InstallerResponse = CacheResponse;
|
||||
|
||||
if (InstallerResponse == null || InstallerResponse.Length < 1)
|
||||
{
|
||||
@@ -192,6 +273,9 @@ namespace Config
|
||||
case 3:
|
||||
BuildDebug = CheckResponse(InstallerResponse);
|
||||
break;
|
||||
case 4:
|
||||
ExtraArguments = InstallerResponse;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -206,12 +290,20 @@ namespace Config
|
||||
Console.WriteLine("Using Visual Studio: No");
|
||||
Console.WriteLine("Build debug: {0}", BuildDebug ? "Yes" : "No");
|
||||
Console.WriteLine("Anope Version: {0}", AnopeVersion); ;
|
||||
if (ExtraArguments != null)
|
||||
Console.WriteLine("Extra Arguments: {0}", ExtraArguments);
|
||||
Console.WriteLine("Press Enter to continue...");
|
||||
Console.ReadKey();
|
||||
|
||||
SaveCache();
|
||||
|
||||
if (ExtraArguments != null)
|
||||
ExtraArguments += " ";
|
||||
|
||||
InstallDirectory = "-DINSTDIR:STRING=\"" + InstallDirectory.Replace('\\', '/') + "\" ";
|
||||
string NMake = UseNMake ? "-G\"NMake Makefiles\" " : "";
|
||||
string Debug = BuildDebug ? "-DCMAKE_BUILD_TYPE:STRING=DEBUG " : "-DCMAKE_BUILD_TYPE:STRING=RELEASE ";
|
||||
string cMake = InstallDirectory + NMake + Debug + VSVersion + Environment.CurrentDirectory.Replace('\\','/');
|
||||
string cMake = InstallDirectory + NMake + Debug + VSVersion + ExtraArguments + Environment.CurrentDirectory.Replace('\\','/');
|
||||
RunCMake(cMake);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -12,6 +12,36 @@
|
||||
#ifdef _WIN32
|
||||
#include "services.h"
|
||||
|
||||
struct WindowsLanguage
|
||||
{
|
||||
const char *languageName;
|
||||
USHORT windowsLanguageName;
|
||||
};
|
||||
|
||||
WindowsLanguage WindowsLanguages[] = {
|
||||
{"ca_ES", LANG_CATALAN},
|
||||
{"de_DE", LANG_GERMAN},
|
||||
{"el_GR", LANG_GREEK},
|
||||
{"es_ES", LANG_SPANISH},
|
||||
{"fr_FR", LANG_FRENCH},
|
||||
{"hu_HU", LANG_HUNGARIAN},
|
||||
{"it_IT", LANG_ITALIAN},
|
||||
{"nl_NL", LANG_DUTCH},
|
||||
{"pl_PL", LANG_POLISH},
|
||||
{"pt_PT", LANG_PORTUGUESE},
|
||||
{"ru_RU", LANG_RUSSIAN},
|
||||
{"tr_TR", LANG_TURKISH},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
USHORT WindowsGetLanguage(const char *lang)
|
||||
{
|
||||
for (int i = 0; WindowsLanguages[i].languageName; ++i)
|
||||
if (!strcmp(lang, WindowsLanguages[i].languageName))
|
||||
return WindowsLanguages[i].windowsLanguageName;
|
||||
return LANG_NEUTRAL;
|
||||
}
|
||||
|
||||
/** This is inet_pton, but it works on Windows
|
||||
* @param af The protocol type, AF_INET or AF_INET6
|
||||
* @param src The address
|
||||
|
||||
Reference in New Issue
Block a user