summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt89
-rw-r--r--src/access.cpp476
-rw-r--r--src/accessgroup.cpp125
-rw-r--r--src/account.cpp91
-rw-r--r--src/base.cpp40
-rw-r--r--src/base64.cpp20
-rw-r--r--src/bots.cpp278
-rw-r--r--src/channels.cpp141
-rw-r--r--src/command.cpp103
-rw-r--r--src/config.cpp596
-rw-r--r--src/event.cpp35
-rw-r--r--src/extensible.cpp61
-rw-r--r--src/hashcomp.cpp134
-rw-r--r--src/init.cpp94
-rw-r--r--src/language.cpp40
-rw-r--r--src/logger.cpp73
-rw-r--r--src/mail.cpp47
-rw-r--r--src/main.cpp37
-rw-r--r--src/memos.cpp141
-rw-r--r--src/messages.cpp88
-rw-r--r--src/misc.cpp140
-rw-r--r--src/modes.cpp166
-rw-r--r--src/module.cpp31
-rw-r--r--src/modulemanager.cpp260
-rw-r--r--src/nickalias.cpp217
-rw-r--r--src/nickcore.cpp270
-rw-r--r--src/opertype.cpp98
-rw-r--r--src/pipeengine.cpp25
-rw-r--r--src/process.cpp54
-rw-r--r--src/protocol.cpp102
-rw-r--r--src/regchannel.cpp695
-rw-r--r--src/serialize.cpp328
-rw-r--r--src/servers.cpp182
-rw-r--r--src/service.cpp67
-rw-r--r--src/service_manager.cpp138
-rw-r--r--src/socket_clients.cpp18
-rw-r--r--src/socket_transport.cpp22
-rw-r--r--src/socketengines/socketengine_epoll.cpp8
-rw-r--r--src/socketengines/socketengine_kqueue.cpp6
-rw-r--r--src/socketengines/socketengine_poll.cpp4
-rw-r--r--src/socketengines/socketengine_select.cpp4
-rw-r--r--src/sockets.cpp20
-rw-r--r--src/threadengine.cpp119
-rw-r--r--src/timers.cpp19
-rw-r--r--src/tools/CMakeLists.txt44
-rw-r--r--src/tools/anoperc.in6
-rw-r--r--src/tools/anopesmtp.cpp492
-rw-r--r--src/uplink.cpp79
-rw-r--r--src/users.cpp259
-rw-r--r--src/version.sh6
-rw-r--r--src/win32/Config.cs363
-rw-r--r--src/win32/anope_windows.h12
-rw-r--r--src/win32/dir/dir.cpp7
-rw-r--r--src/win32/dir/dir.h7
-rw-r--r--src/win32/dl/dl.cpp5
-rw-r--r--src/win32/dl/dl.h5
-rw-r--r--src/win32/pipe/pipe.cpp8
-rw-r--r--src/win32/pipe/pipe.h5
-rw-r--r--src/win32/pthread/pthread.cpp119
-rw-r--r--src/win32/pthread/pthread.h35
-rw-r--r--src/win32/resource.h10
-rw-r--r--src/win32/sigaction/sigaction.cpp17
-rw-r--r--src/win32/sigaction/sigaction.h28
-rw-r--r--src/win32/socket.cpp7
-rw-r--r--src/win32/socket.h5
-rw-r--r--src/win32/win32.rc.cmake2
-rw-r--r--src/win32/windows.cpp12
-rw-r--r--src/xline.cpp423
68 files changed, 2715 insertions, 4943 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b390d164b..007e3605a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,72 +2,37 @@
file(GLOB SRC_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
if(WIN32)
- append_to_list(SRC_SRCS win32/dir/dir.cpp)
- append_to_list(SRC_SRCS win32/socket.cpp)
- append_to_list(SRC_SRCS win32/windows.cpp)
- append_to_list(SRC_SRCS win32/dl/dl.cpp)
- append_to_list(SRC_SRCS win32/pipe/pipe.cpp)
- append_to_list(SRC_SRCS win32/pthread/pthread.cpp)
- append_to_list(SRC_SRCS win32/sigaction/sigaction.cpp)
-endif(WIN32)
+ list(APPEND SRC_SRCS win32/dir/dir.cpp)
+ list(APPEND SRC_SRCS win32/socket.cpp)
+ list(APPEND SRC_SRCS win32/windows.cpp)
+ list(APPEND SRC_SRCS win32/dl/dl.cpp)
+ list(APPEND SRC_SRCS win32/pipe/pipe.cpp)
+ list(APPEND SRC_SRCS win32/sigaction/sigaction.cpp)
+endif()
if(HAVE_EPOLL)
- append_to_list(SRC_SRCS socketengines/socketengine_epoll.cpp)
-else(HAVE_EPOLL)
- if(HAVE_KQUEUE)
- append_to_list(SRC_SRCS socketengines/socketengine_kqueue.cpp)
- else(HAVE_KQUEUE)
- if(HAVE_POLL)
- append_to_list(SRC_SRCS socketengines/socketengine_poll.cpp)
- else(HAVE_POLL)
- append_to_list(SRC_SRCS socketengines/socketengine_select.cpp)
- endif(HAVE_POLL)
- endif(HAVE_KQUEUE)
-endif(HAVE_EPOLL)
+ list(APPEND SRC_SRCS socketengines/socketengine_epoll.cpp)
+elseif(HAVE_KQUEUE)
+ list(APPEND SRC_SRCS socketengines/socketengine_kqueue.cpp)
+elseif(HAVE_POLL)
+ list(APPEND SRC_SRCS socketengines/socketengine_poll.cpp)
+else()
+ list(APPEND SRC_SRCS socketengines/socketengine_select.cpp)
+endif()
-sort_list(SRC_SRCS)
+list(SORT SRC_SRCS)
# Set all the files to use C++ as well as set their compile flags (use the module-specific compile flags, though)
set_source_files_properties(${SRC_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
-# Create an empty list to store extra include directories
-set(EXTRA_INCLUDES)
-# Iterate through all the source files
-foreach(SRC ${SRC_SRCS})
- # Temporary variable for the current source's include directories
- set(TEMP_INCLUDES)
- # Calculate the header file dependencies for the given source file
- calculate_depends(${SRC} TEMP_INCLUDES)
- # If there were some extra include directories, add them to the list
- if(TEMP_INCLUDES)
- append_to_list(EXTRA_INCLUDES ${TEMP_INCLUDES})
- endif(TEMP_INCLUDES)
-endforeach(SRC)
-# If there were extra include directories, remove the duplicates and add the directories to the include path
-if(EXTRA_INCLUDES)
- remove_list_duplicates(EXTRA_INCLUDES)
- include_directories(${EXTRA_INCLUDES})
-endif(EXTRA_INCLUDES)
-
# Under Windows, we also include a resource file to the build
if(WIN32)
# Make sure that the resource file is seen as an RC file to be compiled with a resource compiler, not a C++ compiler
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc LANGUAGE RC)
# Add the resource file to the list of sources
- append_to_list(SRC_SRCS ${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc)
- # For MinGW, we have to change the compile flags
- if(MINGW)
- set(RC_CFLAGS "-DMINGW -Ocoff -I${Anope_SOURCE_DIR}/include")
- # If any sort of debugging is being enabled, add a _DEBUG define to the flags for the resource compiler
- if(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
- set(RC_CFLAGS "${RC_CFLAGS} -D_DEBUG")
- endif(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
- set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc COMPILE_FLAGS "${RC_CFLAGS}")
- # For anything else, assumingly Visual Studio at this point, use a different set of compile flags
- else(MINGW)
- set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc COMPILE_FLAGS "/i\"${Anope_SOURCE_DIR}/include\"")
- endif(MINGW)
-endif(WIN32)
+ list(APPEND SRC_SRCS ${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc)
+ set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/win32/win32.rc COMPILE_FLAGS "/i\"${Anope_SOURCE_DIR}/include\"")
+endif()
# If compiling with Visual Studio, create a static library out of win32/win32_memory.cpp to be included with everything else, needed to override its override of new/delete operators
if(MSVC)
@@ -75,26 +40,26 @@ if(MSVC)
add_library(win32_memory STATIC win32/win32_memory.cpp)
set(WIN32_MEMORY win32_memory)
set(EXTRA_LDFLAGS "/OPT:NOREF") # https://sourceware.org/bugzilla/show_bug.cgi?id=12633
-else(MSVC)
+else()
set(WIN32_MEMORY)
-endif(MSVC)
+endif()
# Generate the Anope executable and set it's linker flags, also set it to export it's symbols even though it's not a module
add_executable(${PROGRAM_NAME} ${SRC_SRCS})
set_target_properties(${PROGRAM_NAME} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS} ${EXTRA_LDFLAGS}" ENABLE_EXPORTS ON INSTALL_RPATH_USE_LINK_PATH ON BUILD_WITH_INSTALL_RPATH 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 ${LINK_LIBS} ${GETTEXT_LIBRARIES} ${WIN32_MEMORY})
+ target_link_libraries(${PROGRAM_NAME} wsock32 Ws2_32 ${LINK_LIBS} ${GETTEXT_LIBRARIES} ${Boost_LIBRARIES} ${WIN32_MEMORY})
set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
-else(WIN32)
- target_link_libraries(${PROGRAM_NAME} ${LINK_LIBS} ${GETTEXT_LIBRARIES})
-endif(WIN32)
+else()
+ target_link_libraries(${PROGRAM_NAME} ${LINK_LIBS} ${GETTEXT_LIBRARIES} ${Boost_LIBRARIES})
+endif()
# Building the Anope executable requires the version.h header to be generated
add_dependencies(${PROGRAM_NAME} headers)
# Also require the language files if we have gettext
if(GETTEXT_FOUND)
add_dependencies(${PROGRAM_NAME} language)
-endif(GETTEXT_FOUND)
+endif()
# Get the filename of the Anope executable as it is in on this system
get_target_property(SERVICES_BINARY ${PROGRAM_NAME} LOCATION)
@@ -108,7 +73,7 @@ configure_file(${Anope_SOURCE_DIR}/include/sysconf.h.cmake ${Anope_BINARY_DIR}/i
# Go into the following directories and run their CMakeLists.txt as well
if(NOT DISABLE_TOOLS)
add_subdirectory(tools)
-endif(NOT DISABLE_TOOLS)
+endif()
# Set Anope to be installed to the bin directory
install(TARGETS ${PROGRAM_NAME}
diff --git a/src/access.cpp b/src/access.cpp
deleted file mode 100644
index 007e6d281..000000000
--- a/src/access.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "service.h"
-#include "access.h"
-#include "regchannel.h"
-#include "users.h"
-#include "account.h"
-#include "protocol.h"
-
-static struct
-{
- Anope::string name;
- Anope::string desc;
-} descriptions[] = {
- {"ACCESS_CHANGE", _("Allowed to modify the access list")},
- {"ACCESS_LIST", _("Allowed to view the access list")},
- {"AKICK", _("Allowed to use the AKICK command")},
- {"ASSIGN", _("Allowed to assign/unassign a bot")},
- {"AUTOHALFOP", _("Automatic halfop upon join")},
- {"AUTOOP", _("Automatic channel operator status upon join")},
- {"AUTOOWNER", _("Automatic owner upon join")},
- {"AUTOPROTECT", _("Automatic protect upon join")},
- {"AUTOVOICE", _("Automatic voice on join")},
- {"BADWORDS", _("Allowed to modify channel badwords list")},
- {"BAN", _("Allowed to ban users")},
- {"FANTASIA", _("Allowed to use fantasy commands")},
- {"FOUNDER", _("Allowed to issue commands restricted to channel founders")},
- {"GETKEY", _("Allowed to use GETKEY command")},
- {"GREET", _("Greet message displayed on join")},
- {"HALFOP", _("Allowed to (de)halfop users")},
- {"HALFOPME", _("Allowed to (de)halfop him/herself")},
- {"INFO", _("Allowed to get full INFO output")},
- {"INVITE", _("Allowed to use the INVITE command")},
- {"KICK", _("Allowed to use the KICK command")},
- {"MEMO", _("Allowed to read channel memos")},
- {"MODE", _("Allowed to use the MODE command")},
- {"NOKICK", _("Prevents users being kicked by Services")},
- {"OP", _("Allowed to (de)op users")},
- {"OPME", _("Allowed to (de)op him/herself")},
- {"OWNER", _("Allowed to (de)owner users")},
- {"OWNERME", _("Allowed to (de)owner him/herself")},
- {"PROTECT", _("Allowed to (de)protect users")},
- {"PROTECTME", _("Allowed to (de)protect him/herself")},
- {"SAY", _("Allowed to use SAY and ACT commands")},
- {"SET", _("Allowed to set channel settings")},
- {"SIGNKICK", _("No signed kick when SIGNKICK LEVEL is used")},
- {"TOPIC", _("Allowed to change channel topics")},
- {"UNBAN", _("Allowed to unban users")},
- {"VOICE", _("Allowed to (de)voice users")},
- {"VOICEME", _("Allowed to (de)voice him/herself")}
-};
-
-Privilege::Privilege(const Anope::string &n, const Anope::string &d, int r) : name(n), desc(d), rank(r)
-{
- if (this->desc.empty())
- for (unsigned j = 0; j < sizeof(descriptions) / sizeof(*descriptions); ++j)
- if (descriptions[j].name.equals_ci(name))
- this->desc = descriptions[j].desc;
-}
-
-bool Privilege::operator==(const Privilege &other) const
-{
- return this->name.equals_ci(other.name);
-}
-
-std::vector<Privilege> PrivilegeManager::Privileges;
-
-void PrivilegeManager::AddPrivilege(Privilege p)
-{
- unsigned i;
- for (i = 0; i < Privileges.size(); ++i)
- {
- Privilege &priv = Privileges[i];
-
- if (priv.rank > p.rank)
- break;
- }
-
- Privileges.insert(Privileges.begin() + i, p);
-}
-
-void PrivilegeManager::RemovePrivilege(Privilege &p)
-{
- std::vector<Privilege>::iterator it = std::find(Privileges.begin(), Privileges.end(), p);
- if (it != Privileges.end())
- Privileges.erase(it);
-
- for (registered_channel_map::const_iterator cit = RegisteredChannelList->begin(), cit_end = RegisteredChannelList->end(); cit != cit_end; ++cit)
- {
- cit->second->QueueUpdate();
- cit->second->RemoveLevel(p.name);
- }
-}
-
-Privilege *PrivilegeManager::FindPrivilege(const Anope::string &name)
-{
- for (unsigned i = Privileges.size(); i > 0; --i)
- if (Privileges[i - 1].name.equals_ci(name))
- return &Privileges[i - 1];
- return NULL;
-}
-
-std::vector<Privilege> &PrivilegeManager::GetPrivileges()
-{
- return Privileges;
-}
-
-void PrivilegeManager::ClearPrivileges()
-{
- Privileges.clear();
-}
-
-AccessProvider::AccessProvider(Module *o, const Anope::string &n) : Service(o, "AccessProvider", n)
-{
- Providers.push_back(this);
-}
-
-AccessProvider::~AccessProvider()
-{
- std::list<AccessProvider *>::iterator it = std::find(Providers.begin(), Providers.end(), this);
- if (it != Providers.end())
- Providers.erase(it);
-}
-
-std::list<AccessProvider *> AccessProvider::Providers;
-
-const std::list<AccessProvider *>& AccessProvider::GetProviders()
-{
- return Providers;
-}
-
-ChanAccess::ChanAccess(AccessProvider *p) : Serializable("ChanAccess"), provider(p)
-{
-}
-
-ChanAccess::~ChanAccess()
-{
- if (this->ci)
- {
- std::vector<ChanAccess *>::iterator it = std::find(this->ci->access->begin(), this->ci->access->end(), this);
- if (it != this->ci->access->end())
- this->ci->access->erase(it);
-
- if (*nc != NULL)
- nc->RemoveChannelReference(this->ci);
- else
- {
- ChannelInfo *c = ChannelInfo::Find(this->mask);
- if (c)
- c->RemoveChannelReference(this->ci->name);
- }
- }
-}
-
-void ChanAccess::SetMask(const Anope::string &m, ChannelInfo *c)
-{
- if (*nc != NULL)
- nc->RemoveChannelReference(this->ci);
- else if (!this->mask.empty())
- {
- ChannelInfo *targc = ChannelInfo::Find(this->mask);
- if (targc)
- targc->RemoveChannelReference(this->ci->name);
- }
-
- ci = c;
- mask.clear();
- nc = NULL;
-
- const NickAlias *na = NickAlias::Find(m);
- if (na != NULL)
- {
- nc = na->nc;
- nc->AddChannelReference(ci);
- }
- else
- {
- mask = m;
-
- ChannelInfo *targci = ChannelInfo::Find(mask);
- if (targci != NULL)
- targci->AddChannelReference(ci->name);
- }
-}
-
-const Anope::string &ChanAccess::Mask() const
-{
- if (nc)
- return nc->display;
- else
- return mask;
-}
-
-NickCore *ChanAccess::GetAccount() const
-{
- return nc;
-}
-
-void ChanAccess::Serialize(Serialize::Data &data) const
-{
- data["provider"] << this->provider->name;
- data["ci"] << this->ci->name;
- data["mask"] << this->Mask();
- data["creator"] << this->creator;
- data.SetType("last_seen", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
- data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
- data["data"] << this->AccessSerialize();
-}
-
-Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string provider, chan;
-
- data["provider"] >> provider;
- data["ci"] >> chan;
-
- ServiceReference<AccessProvider> aprovider("AccessProvider", provider);
- ChannelInfo *ci = ChannelInfo::Find(chan);
- if (!aprovider || !ci)
- return NULL;
-
- ChanAccess *access;
- if (obj)
- access = anope_dynamic_static_cast<ChanAccess *>(obj);
- else
- access = aprovider->Create();
- access->ci = ci;
- Anope::string m;
- data["mask"] >> m;
- access->SetMask(m, ci);
- data["creator"] >> access->creator;
- data["last_seen"] >> access->last_seen;
- data["created"] >> access->created;
-
- Anope::string adata;
- data["data"] >> adata;
- access->AccessUnserialize(adata);
-
- if (!obj)
- ci->AddAccess(access);
- return access;
-}
-
-bool ChanAccess::Matches(const User *u, const NickCore *acc, ChannelInfo* &next) const
-{
- next = NULL;
-
- if (this->nc)
- return this->nc == acc;
-
- if (u)
- {
- bool is_mask = this->mask.find_first_of("!@?*") != Anope::string::npos;
- if (is_mask && Anope::Match(u->nick, this->mask))
- return true;
- else if (Anope::Match(u->GetDisplayedMask(), this->mask))
- return true;
- }
-
- if (acc)
- {
- for (unsigned i = 0; i < acc->aliases->size(); ++i)
- {
- const NickAlias *na = acc->aliases->at(i);
- if (Anope::Match(na->nick, this->mask))
- return true;
- }
- }
-
- if (IRCD->IsChannelValid(this->mask))
- {
- next = ChannelInfo::Find(this->mask);
- }
-
- return false;
-}
-
-bool ChanAccess::operator>(const ChanAccess &other) const
-{
- const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
- for (unsigned i = privs.size(); i > 0; --i)
- {
- bool this_p = this->HasPriv(privs[i - 1].name),
- other_p = other.HasPriv(privs[i - 1].name);
-
- if (!this_p && !other_p)
- continue;
-
- return this_p && !other_p;
- }
-
- return false;
-}
-
-bool ChanAccess::operator<(const ChanAccess &other) const
-{
- const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
- for (unsigned i = privs.size(); i > 0; --i)
- {
- bool this_p = this->HasPriv(privs[i - 1].name),
- other_p = other.HasPriv(privs[i - 1].name);
-
- if (!this_p && !other_p)
- continue;
-
- return !this_p && other_p;
- }
-
- return false;
-}
-
-bool ChanAccess::operator>=(const ChanAccess &other) const
-{
- return !(*this < other);
-}
-
-bool ChanAccess::operator<=(const ChanAccess &other) const
-{
- return !(*this > other);
-}
-
-AccessGroup::AccessGroup()
-{
- this->ci = NULL;
- this->nc = NULL;
- this->super_admin = this->founder = false;
-}
-
-static bool HasPriv(const ChanAccess::Path &path, const Anope::string &name)
-{
- if (path.empty())
- return false;
-
- for (unsigned int i = 0; i < path.size(); ++i)
- {
- ChanAccess *access = path[i];
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name));
-
- if (MOD_RESULT != EVENT_ALLOW && !access->HasPriv(name))
- return false;
- }
-
- return true;
-}
-
-bool AccessGroup::HasPriv(const Anope::string &name) const
-{
- if (this->super_admin)
- return true;
- else if (!ci || ci->GetLevel(name) == ACCESS_INVALID)
- return false;
-
- /* Privileges prefixed with auto are understood to be given
- * automatically. Sometimes founders want to not automatically
- * obtain privileges, so we will let them */
- bool auto_mode = !name.find("AUTO");
-
- /* Only grant founder privilege if this isn't an auto mode or if they don't match any entries in this group */
- if ((!auto_mode || paths.empty()) && this->founder)
- return true;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnGroupCheckPriv, MOD_RESULT, (this, name));
- if (MOD_RESULT != EVENT_CONTINUE)
- return MOD_RESULT == EVENT_ALLOW;
-
- for (unsigned int i = paths.size(); i > 0; --i)
- {
- const ChanAccess::Path &path = paths[i - 1];
-
- if (::HasPriv(path, name))
- return true;
- }
-
- return false;
-}
-
-static ChanAccess *HighestInPath(const ChanAccess::Path &path)
-{
- ChanAccess *highest = NULL;
-
- for (unsigned int i = 0; i < path.size(); ++i)
- if (highest == NULL || *path[i] > *highest)
- highest = path[i];
-
- return highest;
-}
-
-const ChanAccess *AccessGroup::Highest() const
-{
- ChanAccess *highest = NULL;
-
- for (unsigned int i = 0; i < paths.size(); ++i)
- {
- ChanAccess *hip = HighestInPath(paths[i]);
-
- if (highest == NULL || *hip > *highest)
- highest = hip;
- }
-
- return highest;
-}
-
-bool AccessGroup::operator>(const AccessGroup &other) const
-{
- if (other.super_admin)
- return false;
- else if (this->super_admin)
- return true;
- else if (other.founder)
- return false;
- else if (this->founder)
- return true;
-
- const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
- for (unsigned i = privs.size(); i > 0; --i)
- {
- bool this_p = this->HasPriv(privs[i - 1].name),
- other_p = other.HasPriv(privs[i - 1].name);
-
- if (!this_p && !other_p)
- continue;
-
- return this_p && !other_p;
- }
-
- return false;
-}
-
-bool AccessGroup::operator<(const AccessGroup &other) const
-{
- if (this->super_admin)
- return false;
- else if (other.super_admin)
- return true;
- else if (this->founder)
- return false;
- else if (other.founder)
- return true;
-
- const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
- for (unsigned i = privs.size(); i > 0; --i)
- {
- bool this_p = this->HasPriv(privs[i - 1].name),
- other_p = other.HasPriv(privs[i - 1].name);
-
- if (!this_p && !other_p)
- continue;
-
- return !this_p && other_p;
- }
-
- return false;
-}
-
-bool AccessGroup::operator>=(const AccessGroup &other) const
-{
- return !(*this < other);
-}
-
-bool AccessGroup::operator<=(const AccessGroup &other) const
-{
- return !(*this > other);
-}
-
diff --git a/src/accessgroup.cpp b/src/accessgroup.cpp
new file mode 100644
index 000000000..a674f4723
--- /dev/null
+++ b/src/accessgroup.cpp
@@ -0,0 +1,125 @@
+/*
+ * Anope IRC Services
+ *
+ * Copyright (C) 2011-2016 Anope Team <team@anope.org>
+ *
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
+ */
+
+#include "modules/chanserv.h"
+#include "accessgroup.h"
+
+using namespace ChanServ;
+
+bool AccessGroup::HasPriv(const Anope::string &priv)
+{
+ if (this->super_admin)
+ return true;
+ else if (!ci || ci->GetLevel(priv) == ACCESS_INVALID)
+ return false;
+
+ /* Privileges prefixed with auto are understood to be given
+ * automatically. Sometimes founders want to not automatically
+ * obtain privileges, so we will let them */
+ bool auto_mode = !priv.find("AUTO");
+
+ /* Only grant founder privilege if this isn't an auto mode or if they don't match any entries in this group */
+ if ((!auto_mode || this->empty()) && this->founder)
+ return true;
+
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&::Event::GroupCheckPriv::OnGroupCheckPriv, this, priv);
+ if (MOD_RESULT != EVENT_CONTINUE)
+ return MOD_RESULT == EVENT_ALLOW;
+
+ for (unsigned i = this->size(); i > 0; --i)
+ {
+ ChanAccess *access = this->at(i - 1);
+
+ if (access->HasPriv(priv))
+ return true;
+ }
+
+ return false;
+}
+
+ChanAccess *AccessGroup::Highest()
+{
+ ChanAccess *highest = NULL;
+ for (unsigned i = 0; i < this->size(); ++i)
+ if (highest == NULL || *this->at(i) > *highest)
+ highest = this->at(i);
+ return highest;
+}
+
+bool AccessGroup::operator>(AccessGroup &other)
+{
+ if (other.super_admin)
+ return false;
+ else if (this->super_admin)
+ return true;
+ else if (other.founder)
+ return false;
+ else if (this->founder)
+ return true;
+
+ const std::vector<Privilege> &privs = service->GetPrivileges();
+ for (unsigned i = privs.size(); i > 0; --i)
+ {
+ bool this_p = this->HasPriv(privs[i - 1].name),
+ other_p = other.HasPriv(privs[i - 1].name);
+
+ if (!this_p && !other_p)
+ continue;
+
+ return this_p && !other_p;
+ }
+
+ return false;
+}
+
+bool AccessGroup::operator<(AccessGroup &other)
+{
+ if (this->super_admin)
+ return false;
+ else if (other.super_admin)
+ return true;
+ else if (this->founder)
+ return false;
+ else if (other.founder)
+ return true;
+
+ const std::vector<Privilege> &privs = service->GetPrivileges();
+ for (unsigned i = privs.size(); i > 0; --i)
+ {
+ bool this_p = this->HasPriv(privs[i - 1].name),
+ other_p = other.HasPriv(privs[i - 1].name);
+
+ if (!this_p && !other_p)
+ continue;
+
+ return !this_p && other_p;
+ }
+
+ return false;
+}
+
+bool AccessGroup::operator>=(AccessGroup &other)
+{
+ return !(*this < other);
+}
+
+bool AccessGroup::operator<=(AccessGroup &other)
+{
+ return !(*this > other);
+} \ No newline at end of file
diff --git a/src/account.cpp b/src/account.cpp
deleted file mode 100644
index f23f81242..000000000
--- a/src/account.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "services.h"
-#include "account.h"
-#include "modules.h"
-#include "users.h"
-#include "protocol.h"
-#include "regchannel.h"
-
-std::set<IdentifyRequest *> IdentifyRequest::Requests;
-
-IdentifyRequest::IdentifyRequest(Module *o, const Anope::string &acc, const Anope::string &pass) : owner(o), account(acc), password(pass), dispatched(false), success(false)
-{
- Requests.insert(this);
-}
-
-IdentifyRequest::~IdentifyRequest()
-{
- Requests.erase(this);
-}
-
-void IdentifyRequest::Hold(Module *m)
-{
- holds.insert(m);
-}
-
-void IdentifyRequest::Release(Module *m)
-{
- holds.erase(m);
- if (holds.empty() && dispatched)
- {
- if (!success)
- this->OnFail();
- delete this;
- }
-}
-
-void IdentifyRequest::Success(Module *m)
-{
- if (!success)
- {
- this->OnSuccess();
- success = true;
- }
-}
-
-void IdentifyRequest::Dispatch()
-{
- if (holds.empty())
- {
- if (!success)
- this->OnFail();
- delete this;
- }
- else
- dispatched = true;
-}
-
-void IdentifyRequest::ModuleUnload(Module *m)
-{
- for (std::set<IdentifyRequest *>::iterator it = Requests.begin(), it_end = Requests.end(); it != it_end;)
- {
- IdentifyRequest *ir = *it;
- ++it;
-
- ir->holds.erase(m);
- if (ir->holds.empty() && ir->dispatched)
- {
- if (!ir->success)
- ir->OnFail();
- delete ir;
- continue;
- }
-
- if (ir->owner == m)
- {
- if (!ir->success)
- ir->OnFail();
- delete ir;
- }
- }
-}
diff --git a/src/base.cpp b/src/base.cpp
index 5e4ecc9e3..c35a654b4 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -1,17 +1,47 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2010-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "anope.h"
#include "service.h"
+#include "base.h"
+
+std::set<ReferenceBase *> *ReferenceBase::references = NULL;
+
+ReferenceBase::ReferenceBase()
+{
+ if (references == NULL)
+ references = new std::set<ReferenceBase *>();
+ references->insert(this);
+}
-std::map<Anope::string, std::map<Anope::string, Service *> > Service::Services;
-std::map<Anope::string, std::map<Anope::string, Anope::string> > Service::Aliases;
+ReferenceBase::~ReferenceBase()
+{
+ references->erase(this);
+}
+
+void ReferenceBase::ResetAll()
+{
+ if (references)
+ for (ReferenceBase *b : *references)
+ b->Reset();
+}
Base::Base() : references(NULL)
{
diff --git a/src/base64.cpp b/src/base64.cpp
index 3096d9c3f..5c2d721ad 100644
--- a/src/base64.cpp
+++ b/src/base64.cpp
@@ -1,12 +1,20 @@
-/* base64 routines.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2004-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
diff --git a/src/bots.cpp b/src/bots.cpp
index 7654bb247..07d6ec858 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -1,9 +1,21 @@
/*
+ * Anope IRC Services
*
- * (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
- * (C) 2008-2016 Anope Team <team@anope.org>
+ * Copyright (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
+ * Copyright (C) 2008-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -12,25 +24,29 @@
#include "servers.h"
#include "protocol.h"
#include "xline.h"
-#include "regchannel.h"
#include "channels.h"
#include "config.h"
#include "language.h"
#include "serialize.h"
+#include "event.h"
+#include "modules/chanserv.h"
-Serialize::Checker<botinfo_map> BotListByNick("BotInfo"), BotListByUID("BotInfo");
-
-BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : User(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), Serializable("BotInfo"), channels("ChannelInfo"), botmodes(bmodes)
+ServiceBot::ServiceBot(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal, const Anope::string &bmodes) : LocalUser(nnick, nuser, nhost, "", "", Me, nreal, Anope::CurTime, "", IRCD ? IRCD->UID_Retrieve() : "", NULL), botmodes(bmodes)
{
- this->lastmsg = this->created = Anope::CurTime;
+ this->type = UserType::BOT;
+ this->lastmsg = Anope::CurTime;
this->introduced = false;
- this->oper_only = this->conf = false;
- (*BotListByNick)[this->nick] = this;
- if (!this->uid.empty())
- (*BotListByUID)[this->uid] = this;
-
- FOREACH_MOD(OnCreateBot, (this));
+ bi = Serialize::New<BotInfo *>();
+ bi->bot = this;
+
+ bi->SetNick(nnick);
+ bi->SetUser(nuser);
+ bi->SetHost(nhost);
+ bi->SetRealName(nreal);
+ bi->SetCreated(Anope::CurTime);
+
+ EventManager::Get()->Dispatch(&Event::CreateBot::OnCreateBot, this);
// If we're synchronised with the uplink already, send the bot.
if (Me && Me->IsSynced())
@@ -39,92 +55,46 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A
if (!tmodes.empty())
this->SetModesInternal(this, tmodes.c_str());
- XLine x(this->nick, "Reserved for services");
- IRCD->SendSQLine(NULL, &x);
+ //XXX
+ //XLine x(this->nick, "Reserved for services");
+ //IRCD->SendSQLine(NULL, &x);
IRCD->SendClientIntroduction(this);
this->introduced = true;
}
}
-BotInfo::~BotInfo()
+ServiceBot::~ServiceBot()
{
- UnsetExtensibles();
+ bi->bot = nullptr;
+ bi->Delete();
- FOREACH_MOD(OnDelBot, (this));
+ EventManager::Get()->Dispatch(&Event::DelBot::OnDelBot, this);
// If we're synchronised with the uplink already, send the bot.
if (Me && Me->IsSynced())
{
IRCD->SendQuit(this, "");
- FOREACH_MOD(OnUserQuit, (this, ""));
+ EventManager::Get()->Dispatch(&Event::UserQuit::OnUserQuit, this, "");
this->introduced = false;
- XLine x(this->nick);
- IRCD->SendSQLineDel(&x);
- }
-
- for (std::set<ChannelInfo *>::iterator it = this->channels->begin(), it_end = this->channels->end(); it != it_end; ++it)
- {
- ChannelInfo *ci = *it;
- this->UnAssign(NULL, ci);
+ // XXX ?
+ //XLine x(this->nick);
+ //IRCD->SendSQLineDel(&x);
}
-
- BotListByNick->erase(this->nick);
- if (!this->uid.empty())
- BotListByUID->erase(this->uid);
}
-void BotInfo::Serialize(Serialize::Data &data) const
-{
- data["nick"] << this->nick;
- data["user"] << this->ident;
- data["host"] << this->host;
- data["realname"] << this->realname;
- data["created"] << this->created;
- data["oper_only"] << this->oper_only;
-
- Extensible::ExtensibleSerialize(this, this, data);
-}
-Serializable* BotInfo::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string nick, user, host, realname, flags;
-
- data["nick"] >> nick;
- data["user"] >> user;
- data["host"] >> host;
- data["realname"] >> realname;
-
- BotInfo *bi;
- if (obj)
- bi = anope_dynamic_static_cast<BotInfo *>(obj);
- else if (!(bi = BotInfo::Find(nick, true)))
- bi = new BotInfo(nick, user, host, realname);
-
- data["created"] >> bi->created;
- data["oper_only"] >> bi->oper_only;
-
- Extensible::ExtensibleUnserialize(bi, bi, data);
-
- return bi;
-}
-
-void BotInfo::GenerateUID()
+void ServiceBot::GenerateUID()
{
if (this->introduced)
throw CoreException("Changing bot UID when it is introduced?");
if (!this->uid.empty())
- {
- BotListByUID->erase(this->uid);
UserListByUID.erase(this->uid);
- }
-
this->uid = IRCD->UID_Retrieve();
- (*BotListByUID)[this->uid] = this;
UserListByUID[this->uid] = this;
}
-void BotInfo::OnKill()
+void ServiceBot::OnKill()
{
this->introduced = false;
this->GenerateUID();
@@ -135,63 +105,60 @@ void BotInfo::OnKill()
IRCD->SendJoin(this, cit->second->chan, &cit->second->status);
}
-void BotInfo::SetNewNick(const Anope::string &newnick)
+void ServiceBot::SetNewNick(const Anope::string &newnick)
{
UserListByNick.erase(this->nick);
- BotListByNick->erase(this->nick);
+ bi->SetNick(newnick);
this->nick = newnick;
UserListByNick[this->nick] = this;
- (*BotListByNick)[this->nick] = this;
}
-const std::set<ChannelInfo *> &BotInfo::GetChannels() const
+std::vector<ChanServ::Channel *> ServiceBot::GetChannels() const
{
- return this->channels;
+ return bi->GetRefs<ChanServ::Channel *>();
}
-void BotInfo::Assign(User *u, ChannelInfo *ci)
+void ServiceBot::Assign(User *u, ChanServ::Channel *ci)
{
EventReturn MOD_RESULT;
- FOREACH_RESULT(OnPreBotAssign, MOD_RESULT, (u, ci, this));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::PreBotAssign::OnPreBotAssign, u, ci, this);
if (MOD_RESULT == EVENT_STOP)
return;
- if (ci->bi)
- ci->bi->UnAssign(u, ci);
-
- ci->bi = this;
- this->channels->insert(ci);
+ if (ci->GetBot())
+ ci->GetBot()->UnAssign(u, ci);
+
+ ci->SetBot(this);
- FOREACH_MOD(OnBotAssign, (u, ci, this));
+ EventManager::Get()->Dispatch(&Event::BotAssign::OnBotAssign, u, ci, this);
}
-void BotInfo::UnAssign(User *u, ChannelInfo *ci)
+void ServiceBot::UnAssign(User *u, ChanServ::Channel *ci)
{
EventReturn MOD_RESULT;
- FOREACH_RESULT(OnBotUnAssign, MOD_RESULT, (u, ci));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::BotUnAssign::OnBotUnAssign, u, ci);
if (MOD_RESULT == EVENT_STOP)
return;
- if (ci->c && ci->c->FindUser(ci->bi))
+ if (ci->c && ci->c->FindUser(ci->GetBot()))
{
if (u)
- ci->bi->Part(ci->c, "UNASSIGN from " + u->nick);
+ ci->GetBot()->Part(ci->c, "UNASSIGN from " + u->nick);
else
- ci->bi->Part(ci->c);
+ ci->GetBot()->Part(ci->c);
}
- ci->bi = NULL;
- this->channels->erase(ci);
+ ci->SetBot(nullptr);
}
-unsigned BotInfo::GetChannelCount() const
+unsigned ServiceBot::GetChannelCount() const
{
- return this->channels->size();
+ return GetChannels().size();
}
-void BotInfo::Join(Channel *c, ChannelStatus *status)
+void ServiceBot::Join(Channel *c, ChannelStatus *status)
{
if (c->FindUser(this) != NULL)
return;
@@ -200,30 +167,30 @@ void BotInfo::Join(Channel *c, ChannelStatus *status)
if (IRCD)
IRCD->SendJoin(this, c, status);
- FOREACH_MOD(OnJoinChannel, (this, c));
+ EventManager::Get()->Dispatch(&Event::JoinChannel::OnJoinChannel, this, c);
}
-void BotInfo::Join(const Anope::string &chname, ChannelStatus *status)
+void ServiceBot::Join(const Anope::string &chname, ChannelStatus *status)
{
bool c;
return this->Join(Channel::FindOrCreate(chname, c), status);
}
-void BotInfo::Part(Channel *c, const Anope::string &reason)
+void ServiceBot::Part(Channel *c, const Anope::string &reason)
{
if (c->FindUser(this) == NULL)
return;
- FOREACH_MOD(OnPrePartChannel, (this, c));
+ EventManager::Get()->Dispatch(&Event::PrePartChannel::OnPrePartChannel, this, c);
IRCD->SendPart(this, c, "%s", !reason.empty() ? reason.c_str() : "");
c->DeleteUser(this);
- FOREACH_MOD(OnPartChannel, (this, c, c->name, reason));
+ EventManager::Get()->Dispatch(&Event::PartChannel::OnPartChannel, this, c, c->name, reason);
}
-void BotInfo::OnMessage(User *u, const Anope::string &message)
+void ServiceBot::OnMessage(User *u, const Anope::string &message)
{
if (this->commands.empty())
return;
@@ -232,16 +199,17 @@ void BotInfo::OnMessage(User *u, const Anope::string &message)
Command::Run(source, message);
}
-CommandInfo& BotInfo::SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission)
+CommandInfo& ServiceBot::SetCommand(const Anope::string &cname, const Anope::string &sname, const Anope::string &permission)
{
CommandInfo ci;
ci.name = sname;
+ ci.cname = cname;
ci.permission = permission;
this->commands[cname] = ci;
return this->commands[cname];
}
-CommandInfo *BotInfo::GetCommand(const Anope::string &cname)
+CommandInfo *ServiceBot::GetCommand(const Anope::string &cname)
{
CommandInfo::map::iterator it = this->commands.find(cname);
if (it != this->commands.end())
@@ -249,30 +217,96 @@ CommandInfo *BotInfo::GetCommand(const Anope::string &cname)
return NULL;
}
-BotInfo* BotInfo::Find(const Anope::string &nick, bool nick_only)
+CommandInfo *ServiceBot::FindCommand(const Anope::string &service)
{
- if (!nick_only && IRCD != NULL && IRCD->RequiresID)
+ for (auto& it : commands)
{
- botinfo_map::iterator it = BotListByUID->find(nick);
- if (it != BotListByUID->end())
- {
- BotInfo *bi = it->second;
- bi->QueueUpdate();
- return bi;
- }
-
- if (IRCD->AmbiguousID)
- return NULL;
+ CommandInfo &ci = it.second;
+
+ if (ci.name == service)
+ return &ci;
}
- botinfo_map::iterator it = BotListByNick->find(nick);
- if (it != BotListByNick->end())
+ return nullptr;
+}
+
+ServiceBot* ServiceBot::Find(const Anope::string &nick, bool nick_only)
+{
+ User *u = User::Find(nick, nick_only);
+ if (u && u->type == UserType::BOT)
+ return anope_dynamic_static_cast<ServiceBot *>(u);
+ return nullptr;
+}
+
+void BotInfo::Delete()
+{
+ if (bot)
{
- BotInfo *bi = it->second;
- bi->QueueUpdate();
- return bi;
+ ServiceBot *b = bot;
+ bot = nullptr;
+ delete b;
}
- return NULL;
+ return Serialize::Object::Delete();
+}
+
+void BotInfo::SetCreated(const time_t &t)
+{
+ Set(&BotInfoType::created, t);
+}
+
+time_t BotInfo::GetCreated()
+{
+ return Get(&BotInfoType::created);
+}
+
+void BotInfo::SetOperOnly(const bool &b)
+{
+ Set(&BotInfoType::operonly, b);
+}
+
+bool BotInfo::GetOperOnly()
+{
+ return Get(&BotInfoType::operonly);
+}
+
+void BotInfo::SetNick(const Anope::string &n)
+{
+ Set(&BotInfoType::nick, n);
+}
+
+Anope::string BotInfo::GetNick()
+{
+ return Get(&BotInfoType::nick);
+}
+
+void BotInfo::SetUser(const Anope::string &u)
+{
+ Set(&BotInfoType::user, u);
+}
+
+Anope::string BotInfo::GetUser()
+{
+ return Get(&BotInfoType::user);
+}
+
+void BotInfo::SetHost(const Anope::string &h)
+{
+ Set(&BotInfoType::host, h);
+}
+
+Anope::string BotInfo::GetHost()
+{
+ return Get(&BotInfoType::host);
+}
+
+void BotInfo::SetRealName(const Anope::string &r)
+{
+ Set(&BotInfoType::realname, r);
+}
+
+Anope::string BotInfo::GetRealName()
+{
+ return Get(&BotInfoType::realname);
}
diff --git a/src/channels.cpp b/src/channels.cpp
index 3d824f0d8..98ecfe127 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -1,29 +1,36 @@
-/* Channel-handling routines.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "channels.h"
-#include "regchannel.h"
#include "logger.h"
#include "modules.h"
#include "users.h"
-#include "bots.h"
#include "servers.h"
#include "protocol.h"
#include "users.h"
#include "config.h"
-#include "access.h"
#include "sockets.h"
#include "language.h"
#include "uplink.h"
+#include "event.h"
+#include "modules/chanserv.h"
channel_map ChannelList;
std::vector<Channel *> Channel::deleting;
@@ -40,21 +47,15 @@ Channel::Channel(const Anope::string &nname, time_t ts)
this->server_modetime = this->chanserv_modetime = 0;
this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_ts = this->topic_time = 0;
- this->ci = ChannelInfo::Find(this->name);
- if (this->ci)
- this->ci->c = this;
-
if (Me && Me->IsSynced())
Log(NULL, this, "create");
- FOREACH_MOD(OnChannelCreate, (this));
+ EventManager::Get()->Dispatch(&Event::ChannelCreate::OnChannelCreate, this);
}
Channel::~Channel()
{
- UnsetExtensibles();
-
- FOREACH_MOD(OnChannelDelete, (this));
+ EventManager::Get()->Dispatch(&Event::ChannelDelete::OnChannelDelete, this);
ModeManager::StackerDel(this);
@@ -90,7 +91,7 @@ void Channel::Reset()
for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
this->SetCorrectModes(it->second->user, true);
-
+
// If the channel is syncing now, do not force a sync due to Reset(), as we are probably iterating over users in Message::SJoin
// A sync will come soon
if (!syncing)
@@ -100,7 +101,7 @@ void Channel::Reset()
void Channel::Sync()
{
syncing = false;
- FOREACH_MOD(OnChannelSync, (this));
+ EventManager::Get()->Dispatch(&Event::ChannelSync::OnChannelSync, this);
CheckModes();
}
@@ -118,7 +119,7 @@ void Channel::CheckModes()
}
Reference<Channel> ref = this;
- FOREACH_MOD(OnCheckModes, (ref));
+ EventManager::Get()->Dispatch(&Event::CheckModes::OnCheckModes, ref);
}
bool Channel::CheckDelete()
@@ -128,13 +129,13 @@ bool Channel::CheckDelete()
*/
if (this->syncing)
return false;
-
+
/* Permanent channels never get deleted */
if (this->HasMode("PERM"))
return false;
EventReturn MOD_RESULT;
- FOREACH_RESULT(OnCheckDelete, MOD_RESULT, (this));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::CheckDelete::OnCheckDelete, this);
return MOD_RESULT != EVENT_STOP && this->users.empty();
}
@@ -158,7 +159,7 @@ void Channel::DeleteUser(User *user)
if (user->server && user->server->IsSynced() && !user->Quitting())
Log(user, this, "leave");
- FOREACH_MOD(OnLeaveChannel, (user, this));
+ EventManager::Get()->Dispatch(&Event::LeaveChannel::OnLeaveChannel, user, this);
ChanUserContainer *cu = user->FindChannel(this);
if (!this->users.erase(user))
@@ -257,7 +258,7 @@ std::vector<Anope::string> Channel::GetModeList(const Anope::string &mname)
return r;
}
-void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
+void Channel::SetModeInternal(const MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
{
if (!ocm)
return;
@@ -291,7 +292,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Ano
if (cc)
cc->status.AddMode(cm->mchar);
- FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::ChannelModeSet::OnChannelModeSet, this, setter, cm, param);
/* Enforce secureops, etc */
if (enforce_mlock && MOD_RESULT != EVENT_STOP)
@@ -312,13 +313,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Ano
return;
}
- if (cm->type == MODE_LIST)
- {
- ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
- cml->OnAdd(this, param);
- }
-
- FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::ChannelModeSet::OnChannelModeSet, this, setter, cm, param);
/* Check if we should enforce mlock */
if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
@@ -327,7 +322,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Ano
this->CheckModes();
}
-void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
+void Channel::RemoveModeInternal(const MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
{
if (!ocm)
return;
@@ -346,8 +341,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const
return;
}
- BotInfo *bi = BotInfo::Find(param);
- User *u = bi ? bi : User::Find(param);
+ User *u = User::Find(param);
if (!u)
{
@@ -362,7 +356,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const
if (cc)
cc->status.DelMode(cm->mchar);
- FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::ChannelModeUnset::OnChannelModeUnset, this, setter, cm, param);
if (enforce_mlock && MOD_RESULT != EVENT_STOP)
this->SetCorrectModes(u, false);
@@ -381,14 +375,8 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const
}
else
this->modes.erase(cm->name);
-
- if (cm->type == MODE_LIST)
- {
- ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
- cml->OnDel(this, param);
- }
- FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::ChannelModeUnset::OnChannelModeUnset, this, setter, cm, param);
if (cm->name == "PERM")
{
@@ -406,7 +394,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const
this->CheckModes();
}
-void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
+void Channel::SetMode(User *bi, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
{
Anope::string wparam = param;
if (!cm)
@@ -455,16 +443,15 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param,
ChannelMode *wcm = cm->Wrap(wparam);
ModeManager::StackerAdd(bi, this, wcm, true, wparam);
- MessageSource ms(bi);
- SetModeInternal(ms, wcm, wparam, enforce_mlock);
+ SetModeInternal(bi, wcm, wparam, enforce_mlock);
}
-void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
+void Channel::SetMode(User *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
{
SetMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
}
-void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
+void Channel::RemoveMode(User *bi, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
{
if (!cm)
return;
@@ -509,11 +496,10 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &para
ChannelMode *wcm = cm->Wrap(wparam);
ModeManager::StackerAdd(bi, this, wcm, false, wparam);
- MessageSource ms(bi);
- RemoveModeInternal(ms, wcm, wparam, enforce_mlock);
+ RemoveModeInternal(bi, wcm, wparam, enforce_mlock);
}
-void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
+void Channel::RemoveMode(User *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
{
RemoveMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
}
@@ -533,7 +519,7 @@ bool Channel::GetParam(const Anope::string &mname, Anope::string &target) const
return false;
}
-void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...)
+void Channel::SetModes(User *bi, bool enforce_mlock, const char *cmodes, ...)
{
char buf[BUFSIZE] = "";
va_list args;
@@ -713,7 +699,7 @@ void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode,
Log(setter, this, "mode") << modestring << paramstring;
else
Log(LOG_DEBUG) << source.GetName() << " is setting " << this->name << " to " << modestring << paramstring;
-
+
if (enforce_mlock)
this->CheckModes();
}
@@ -734,14 +720,14 @@ bool Channel::MatchesList(User *u, const Anope::string &mode)
return false;
}
-void Channel::KickInternal(const MessageSource &source, const Anope::string &nick, const Anope::string &reason)
+bool Channel::KickInternal(const MessageSource &source, const Anope::string &nick, const Anope::string &reason)
{
User *sender = source.GetUser();
User *target = User::Find(nick);
if (!target)
{
Log(LOG_DEBUG) << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason;
- return;
+ return false;
}
if (sender)
@@ -755,17 +741,22 @@ void Channel::KickInternal(const MessageSource &source, const Anope::string &nic
if (cu == NULL)
{
Log(LOG_DEBUG) << "Channel::KickInternal got kick for user " << target->nick << " from " << source.GetSource() << " who isn't on channel " << this->name;
- return;
+ return false;
}
ChannelStatus status = cu->status;
- FOREACH_MOD(OnPreUserKicked, (source, cu, reason));
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::PreUserKicked::OnPreUserKicked, source, cu, reason);
+ if ((sender && sender->server == Me) || source.GetServer() == Me)
+ if (MOD_RESULT == EVENT_STOP)
+ return false;
+
this->DeleteUser(target);
- FOREACH_MOD(OnUserKicked, (source, target, this->name, status, reason));
+ EventManager::Get()->Dispatch(&Event::UserKicked::OnUserKicked, source, target, this->name, status, reason);
+ return true;
}
-bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
+bool Channel::Kick(User *source, User *u, const char *reason, ...)
{
va_list args;
char buf[BUFSIZE] = "";
@@ -776,16 +767,13 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
/* Do not kick protected clients or Ulines */
if (u->IsProtected())
return false;
-
- if (bi == NULL)
- bi = this->ci->WhoSends();
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnBotKick, MOD_RESULT, (bi, this, u, buf));
- if (MOD_RESULT == EVENT_STOP)
+ if (source == NULL)
+ source = this->ci->WhoSends();
+
+ if (!this->KickInternal(source, u->nick, buf))
return false;
- IRCD->SendKick(bi, this, u, "%s", buf);
- this->KickInternal(bi, u->nick, buf);
+ IRCD->SendKick(source, this, u, "%s", buf);
return true;
}
@@ -798,7 +786,7 @@ void Channel::ChangeTopicInternal(User *u, const Anope::string &user, const Anop
Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << this->topic_setter << " to " << newtopic;
- FOREACH_MOD(OnTopicUpdated, (u, this, user, this->topic));
+ EventManager::Get()->Dispatch(&Event::TopicUpdated::OnTopicUpdated, u, this, user, this->topic);
}
void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts)
@@ -812,25 +800,25 @@ void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtop
/* Now that the topic is set update the time set. This is *after* we set it so the protocol modules are able to tell the old last set time */
this->topic_time = Anope::CurTime;
- FOREACH_MOD(OnTopicUpdated, (NULL, this, user, this->topic));
+ EventManager::Get()->Dispatch(&Event::TopicUpdated::OnTopicUpdated, nullptr, this, user, this->topic);
}
void Channel::SetCorrectModes(User *user, bool give_modes)
{
if (user == NULL)
return;
-
+
if (!this->ci)
return;
Log(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << this->name << " (" << (give_modes ? "" : "not ") << "giving modes)";
- AccessGroup u_access = ci->AccessFor(user);
+ ChanServ::AccessGroup u_access = ci->AccessFor(user);
/* Initially only take modes if the channel is being created by a non netmerge */
bool take_modes = this->syncing && user->server->IsSynced();
- FOREACH_MOD(OnSetCorrectModes, (user, this, u_access, give_modes, take_modes));
+ EventManager::Get()->Dispatch(&Event::SetCorrectModes::OnSetCorrectModes, user, this, u_access, give_modes, take_modes);
/* Never take modes from ulines */
if (user->server->IsULined())
@@ -857,7 +845,7 @@ void Channel::SetCorrectModes(User *user, bool give_modes)
}
}
/* modes that have no privileges assigned shouldn't be removed (like operprefix, ojoin) */
- else if (take_modes && !has_priv && ci->GetLevel(cm->name + "ME") != ACCESS_INVALID && !u_access.HasPriv(cm->name + "ME"))
+ else if (take_modes && !has_priv && ci->GetLevel(cm->name + "ME") != ChanServ::ACCESS_INVALID && !u_access.HasPriv(cm->name + "ME"))
{
/* Only remove modes if they are > voice */
if (cm->name == "VOICE")
@@ -901,15 +889,14 @@ bool Channel::CheckKick(User *user)
Anope::string mask, reason;
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnCheckKick, MOD_RESULT, (user, this, mask, reason));
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::CheckKick::OnCheckKick, user, this, mask, reason);
if (MOD_RESULT != EVENT_STOP)
return false;
-
+
if (mask.empty())
mask = this->ci->GetIdealBan(user);
if (reason.empty())
- reason = Language::Translate(user->Account(), CHAN_NOT_ALLOWED_TO_JOIN);
+ reason = Language::Translate(user->Account(), _("You are not permitted to be on this channel."));
Log(LOG_DEBUG) << "Autokicking " << user->nick << " (" << mask << ") from " << this->name;
diff --git a/src/command.cpp b/src/command.cpp
index 35a99eb80..ade17fd45 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -1,9 +1,21 @@
/*
+ * Anope IRC Services
*
- * (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
- * (C) 2008-2016 Anope Team <team@anope.org>
+ * Copyright (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
+ * Copyright (C) 2008-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -11,13 +23,15 @@
#include "users.h"
#include "language.h"
#include "config.h"
-#include "bots.h"
#include "opertype.h"
-#include "access.h"
-#include "regchannel.h"
#include "channels.h"
+#include "event.h"
+#include "bots.h"
+#include "protocol.h"
+#include "modules/botserv.h"
+#include "modules/chanserv.h"
-CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r),
+CommandSource::CommandSource(const Anope::string &n, User *user, NickServ::Account *core, CommandReply *r, ServiceBot *bi) : nick(n), u(user), nc(core), reply(r),
c(NULL), service(bi)
{
}
@@ -32,25 +46,25 @@ User *CommandSource::GetUser()
return this->u;
}
-NickCore *CommandSource::GetAccount()
+NickServ::Account *CommandSource::GetAccount()
{
return this->nc;
}
-AccessGroup CommandSource::AccessFor(ChannelInfo *ci)
+ChanServ::AccessGroup CommandSource::AccessFor(ChanServ::Channel *ci)
{
if (this->u)
return ci->AccessFor(this->u);
else if (this->nc)
return ci->AccessFor(this->nc);
else
- return AccessGroup();
+ return ChanServ::AccessGroup();
}
-bool CommandSource::IsFounder(ChannelInfo *ci)
+bool CommandSource::IsFounder(ChanServ::Channel *ci)
{
if (this->u)
- return ::IsFounder(this->u, ci);
+ return ci->IsFounder(this->u);
else if (this->nc)
return *this->nc == ci->GetFounder();
return false;
@@ -61,7 +75,7 @@ bool CommandSource::HasCommand(const Anope::string &cmd)
if (this->u)
return this->u->HasCommand(cmd);
else if (this->nc && this->nc->o)
- return this->nc->o->ot->HasCommand(cmd);
+ return this->nc->o->GetType()->HasCommand(cmd);
return false;
}
@@ -70,7 +84,7 @@ bool CommandSource::HasPriv(const Anope::string &cmd)
if (this->u)
return this->u->HasPriv(cmd);
else if (this->nc && this->nc->o)
- return this->nc->o->ot->HasPriv(cmd);
+ return this->nc->o->GetType()->HasPriv(cmd);
return false;
}
@@ -92,21 +106,6 @@ bool CommandSource::IsOper()
return false;
}
-void CommandSource::Reply(const char *message, ...)
-{
- va_list args;
- char buf[4096]; // Messages can be really big.
-
- const char *translated_message = Language::Translate(this->nc, message);
-
- va_start(args, message);
- vsnprintf(buf, sizeof(buf), translated_message, args);
-
- this->Reply(Anope::string(buf));
-
- va_end(args);
-}
-
void CommandSource::Reply(const Anope::string &message)
{
const char *translated_message = Language::Translate(this->nc, message.c_str());
@@ -114,7 +113,7 @@ void CommandSource::Reply(const Anope::string &message)
sepstream sep(translated_message, '\n', true);
Anope::string tok;
while (sep.GetToken(tok))
- this->reply->SendMessage(this->service, tok);
+ this->reply->SendMessage(*this->service, tok);
}
Command::Command(Module *o, const Anope::string &sname, size_t minparams, size_t maxparams) : Service(o, "Command", sname), max_params(maxparams), min_params(minparams), module(o)
@@ -146,13 +145,13 @@ void Command::SendSyntax(CommandSource &source)
Anope::string s = Language::Translate(source.GetAccount(), _("Syntax"));
if (!this->syntax.empty())
{
- source.Reply("%s: \002%s %s\002", s.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[0].c_str()));
+ source.Reply("{0}: \002{1} {2}\002", s, source.command, Language::Translate(source.GetAccount(), this->syntax[0].c_str()));
Anope::string spaces(s.length(), ' ');
for (unsigned i = 1, j = this->syntax.size(); i < j; ++i)
- source.Reply("%s \002%s %s\002", spaces.c_str(), source.command.c_str(), Language::Translate(source.GetAccount(), this->syntax[i].c_str()));
+ source.Reply("{0} \002{1} {2}\002", spaces, source.command, Language::Translate(source.GetAccount(), this->syntax[i].c_str()));
}
else
- source.Reply("%s: \002%s\002", s.c_str(), source.command.c_str());
+ source.Reply("{0}: \002{1}\002", s, source.command);
}
bool Command::AllowUnregistered() const
@@ -182,7 +181,7 @@ const Anope::string Command::GetDesc(CommandSource &) const
void Command::OnServHelp(CommandSource &source)
{
- source.Reply(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc(source).c_str()));
+ source.Reply(Anope::printf(" %-14s %s", source.command.c_str(), Language::Translate(source.nc, this->GetDesc(source).c_str())));
}
bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; }
@@ -192,7 +191,7 @@ void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcomma
this->SendSyntax(source);
bool has_help = source.service->commands.find("HELP") != source.service->commands.end();
if (has_help)
- source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str());
+ source.Reply(_("\002{0}{1} HELP {2}\002 for more information."), Config->StrictPrivmsg, source.service->nick, source.command);
}
void Command::Run(CommandSource &source, const Anope::string &message)
@@ -217,20 +216,20 @@ void Command::Run(CommandSource &source, const Anope::string &message)
if (it == source.service->commands.end())
{
if (has_help)
- source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
+ source.Reply(_("Unknown command \002{0}\002. \"{1}{2} HELP\" for help."), message, Config->StrictPrivmsg, source.service->nick);
else
- source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ source.Reply(_("Unknown command \002{0}\002."), message);
return;
}
const CommandInfo &info = it->second;
- ServiceReference<Command> c("Command", info.name);
+ ServiceReference<Command> c(info.name);
if (!c)
{
if (has_help)
- source.Reply(_("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str());
+ source.Reply(_("Unknown command \002{0}\002. \"{1}{2} HELP\" for help."), message, Config->StrictPrivmsg, source.service->nick);
else
- source.Reply(_("Unknown command \002%s\002."), message.c_str());
+ source.Reply(_("Unknown command \002{0}\002."), message);
Log(source.service) << "Command " << it->first << " exists on me, but its service " << info.name << " was not found!";
return;
}
@@ -255,7 +254,7 @@ void Command::Run(CommandSource &source, const Anope::string &cmdname, const Com
// Command requires registered users only
if (!this->AllowUnregistered() && !source.nc)
{
- source.Reply(NICK_IDENTIFY_REQUIRED);
+ source.Reply(_("Password authentication required for that command."));
if (source.GetUser())
Log(LOG_NORMAL, "access_denied_unreg", source.service) << "Access denied for unregistered user " << source.GetUser()->GetMask() << " with command " << cmdname;
return;
@@ -264,8 +263,7 @@ void Command::Run(CommandSource &source, const Anope::string &cmdname, const Com
source.command = cmdname;
source.permission = info.permission;
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnPreCommand, MOD_RESULT, (source, this, params));
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::PreCommand::OnPreCommand, source, this, params);
if (MOD_RESULT == EVENT_STOP)
return;
@@ -278,23 +276,30 @@ void Command::Run(CommandSource &source, const Anope::string &cmdname, const Com
// If the command requires a permission, and they aren't registered or don't have the required perm, DENIED
if (!info.permission.empty() && !source.HasCommand(info.permission))
{
- source.Reply(ACCESS_DENIED);
+ if (!source.IsOper())
+ source.Reply(_("Access denied. You are not a Services Operator."));
+ else
+ source.Reply(_("Access denied. You do not have access to command \002{0}\002."), info.permission);
if (source.GetUser())
Log(LOG_NORMAL, "access_denied", source.service) << "Access denied for user " << source.GetUser()->GetMask() << " with command " << cmdname;
return;
}
this->Execute(source, params);
- FOREACH_MOD(OnPostCommand, (source, this, params));
+ EventManager::Get()->Dispatch(&Event::PostCommand::OnPostCommand, source, this, params);
}
-bool Command::FindCommandFromService(const Anope::string &command_service, BotInfo* &bot, Anope::string &name)
+bool Command::FindCommandFromService(const Anope::string &command_service, ServiceBot* &bot, Anope::string &name)
{
bot = NULL;
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ for (std::pair<Anope::string, User *> p : UserListByNick)
{
- BotInfo *bi = it->second;
+ User *u = p.second;
+ if (u->type != UserType::BOT)
+ continue;
+
+ ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit)
{
@@ -309,7 +314,7 @@ bool Command::FindCommandFromService(const Anope::string &command_service, BotIn
return true;
}
}
-
+
return false;
}
diff --git a/src/config.cpp b/src/config.cpp
index c9a4a53c8..6d9cef04d 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -1,25 +1,37 @@
-/* Configuration file handling.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "config.h"
-#include "bots.h"
-#include "access.h"
#include "opertype.h"
#include "channels.h"
#include "hashcomp.h"
+#include "event.h"
+#include "bots.h"
+#include "modules.h"
+#include "servers.h"
+#include "protocol.h"
+#include "modules/nickserv.h"
using namespace Configuration;
-File ServicesConf("services.conf", false); // Services configuration file name
+File ServicesConf("anope.conf", false); // Services configuration file name
Conf *Config = NULL;
Block::Block(const Anope::string &n) : name(n), linenum(-1)
@@ -33,47 +45,37 @@ const Anope::string &Block::GetName() const
int Block::CountBlock(const Anope::string &bname)
{
- if (!this)
- return 0;
-
return blocks.count(bname);
}
+Block* Block::GetBlock(const Anope::string &bname)
+{
+ auto it = blocks.find(bname);
+
+ if (it != blocks.end())
+ return &it->second;
+
+ blocks.emplace(bname, bname);
+ return GetBlock(bname);
+}
+
Block* Block::GetBlock(const Anope::string &bname, int num)
{
- if (!this)
- return NULL;
-
std::pair<block_map::iterator, block_map::iterator> it = blocks.equal_range(bname);
for (int i = 0; it.first != it.second; ++it.first, ++i)
if (i == num)
return &it.first->second;
- return NULL;
-}
-
-bool Block::Set(const Anope::string &tag, const Anope::string &value)
-{
- if (!this)
- return false;
-
- items[tag] = value;
- return true;
+ return nullptr;
}
const Block::item_map* Block::GetItems() const
{
- if (this)
- return &items;
- else
- return NULL;
+ return &items;
}
-template<> const Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const
+template<> Anope::string Block::Get(const Anope::string &tag, const Anope::string& def) const
{
- if (!this)
- return def;
-
Anope::map<Anope::string>::const_iterator it = items.find(tag);
if (it != items.end())
return it->second;
@@ -83,15 +85,41 @@ template<> const Anope::string Block::Get(const Anope::string &tag, const Anope:
template<> time_t Block::Get(const Anope::string &tag, const Anope::string &def) const
{
- return Anope::DoTime(Get<const Anope::string>(tag, def));
+ return Anope::DoTime(Get<Anope::string>(tag, def));
}
template<> bool Block::Get(const Anope::string &tag, const Anope::string &def) const
{
- const Anope::string &str = Get<const Anope::string>(tag, def);
+ const Anope::string &str = Get<Anope::string>(tag, def);
return !str.empty() && !str.equals_ci("no") && !str.equals_ci("off") && !str.equals_ci("false") && !str.equals_ci("0");
}
+template<> unsigned int Block::Get(const Anope::string &tag, const Anope::string &def) const
+{
+ const Anope::string &str = Get<Anope::string>(tag, def);
+ std::size_t pos = str.length();
+ unsigned long l;
+
+ try
+ {
+ l = std::stoul(str.str(), &pos, 0);
+ }
+ catch (...)
+ {
+ return 0;
+ }
+
+ if (pos != str.length())
+ return 0;
+
+ return l;
+}
+
+template<> void Block::Set(const Anope::string &tag, const Anope::string &value)
+{
+ items[tag] = value;
+}
+
static void ValidateNotEmpty(const Anope::string &block, const Anope::string &name, const Anope::string &value)
{
if (value.empty())
@@ -121,14 +149,17 @@ Conf::Conf() : Block("")
{
Block *include = this->GetBlock("include", i);
- const Anope::string &type = include->Get<const Anope::string>("type"),
- &file = include->Get<const Anope::string>("name");
+ const Anope::string &type = include->Get<Anope::string>("type"),
+ &file = include->Get<Anope::string>("name");
+
+ ValidateNotEmpty("include", "name", file);
File f(file, type == "executable");
this->LoadConf(f);
}
- FOREACH_MOD(OnReload, (this));
+ for (Module *m : ModuleManager::Modules)
+ m->OnReload(this);
/* Check for modified values that aren't allowed to be modified */
if (Config)
@@ -147,20 +178,21 @@ Conf::Conf() : Block("")
{"networkinfo", "userlen"},
{"networkinfo", "hostlen"},
{"networkinfo", "chanlen"},
+ {"options", "casemap"},
};
for (unsigned i = 0; i < sizeof(noreload) / sizeof(noreload[0]); ++i)
- if (this->GetBlock(noreload[i].block)->Get<const Anope::string>(noreload[i].name) != Config->GetBlock(noreload[i].block)->Get<const Anope::string>(noreload[i].name))
+ if (this->GetBlock(noreload[i].block)->Get<Anope::string>(noreload[i].name) != Config->GetBlock(noreload[i].block)->Get<Anope::string>(noreload[i].name))
throw ConfigException("<" + noreload[i].block + ":" + noreload[i].name + "> can not be modified once set");
}
Block *serverinfo = this->GetBlock("serverinfo"), *options = this->GetBlock("options"),
*mail = this->GetBlock("mail"), *networkinfo = this->GetBlock("networkinfo");
- ValidateNotEmpty("serverinfo", "name", serverinfo->Get<const Anope::string>("name"));
- ValidateNotEmpty("serverinfo", "description", serverinfo->Get<const Anope::string>("description"));
- ValidateNotEmpty("serverinfo", "pid", serverinfo->Get<const Anope::string>("pid"));
- ValidateNotEmpty("serverinfo", "motd", serverinfo->Get<const Anope::string>("motd"));
+ ValidateNotEmpty("serverinfo", "name", serverinfo->Get<Anope::string>("name"));
+ ValidateNotEmpty("serverinfo", "description", serverinfo->Get<Anope::string>("description"));
+ ValidateNotEmpty("serverinfo", "pid", serverinfo->Get<Anope::string>("pid"));
+ ValidateNotEmpty("serverinfo", "motd", serverinfo->Get<Anope::string>("motd"));
ValidateNotZero("options", "readtimeout", options->Get<time_t>("readtimeout"));
ValidateNotZero("options", "warningtimeout", options->Get<time_t>("warningtimeout"));
@@ -170,13 +202,13 @@ Conf::Conf() : Block("")
ValidateNotZero("networkinfo", "hostlen", networkinfo->Get<unsigned>("hostlen"));
ValidateNotZero("networkinfo", "chanlen", networkinfo->Get<unsigned>("chanlen"));
- spacesepstream(options->Get<const Anope::string>("ulineservers")).GetTokens(this->Ulines);
+ spacesepstream(options->Get<Anope::string>("ulineservers")).GetTokens(this->Ulines);
if (mail->Get<bool>("usemail"))
{
Anope::string check[] = { "sendmailpath", "sendfrom", "registration_subject", "registration_message", "emailchange_subject", "emailchange_message", "memo_subject", "memo_message" };
for (unsigned i = 0; i < sizeof(check) / sizeof(Anope::string); ++i)
- ValidateNotEmpty("mail", check[i], mail->Get<const Anope::string>(check[i]));
+ ValidateNotEmpty("mail", check[i], mail->Get<Anope::string>(check[i]));
}
this->ReadTimeout = options->Get<time_t>("readtimeout");
@@ -185,21 +217,42 @@ Conf::Conf() : Block("")
this->StrictPrivmsg = !UseStrictPrivmsg ? "/msg " : "/";
{
std::vector<Anope::string> defaults;
- spacesepstream(this->GetModule("nickserv")->Get<const Anope::string>("defaults")).GetTokens(defaults);
+ spacesepstream(this->GetModule("nickserv")->Get<Anope::string>("defaults")).GetTokens(defaults);
this->DefPrivmsg = std::find(defaults.begin(), defaults.end(), "msg") != defaults.end();
}
- this->DefLanguage = options->Get<const Anope::string>("defaultlanguage");
+ this->DefLanguage = options->Get<Anope::string>("defaultlanguage");
this->TimeoutCheck = options->Get<time_t>("timeoutcheck");
this->NickChars = networkinfo->Get<Anope::string>("nick_chars");
+ Anope::string locale = options->Get<Anope::string>("locale");
+ Anope::string casemap = options->Get<Anope::string>("casemap");
+
+ if (locale.empty() == casemap.empty())
+ throw ConfigException("One of options:locale and options:casemap must be set");
+
+ if (locale.empty())
+ {
+ // load locale conf
+ File f(casemap + ".conf", false);
+ this->LoadConf(f);
+ }
+ else
+ {
+#if Boost_FOUND
+ this->locale = new std::locale(Anope::locale::generate(locale.str()));
+#else
+ throw ConfigException("Boost.Locale is not enabled, cannot use locale " + locale);
+#endif
+ }
+
for (int i = 0; i < this->CountBlock("uplink"); ++i)
{
Block *uplink = this->GetBlock("uplink", i);
- const Anope::string &host = uplink->Get<const Anope::string>("host");
+ const Anope::string &host = uplink->Get<Anope::string>("host");
bool ipv6 = uplink->Get<bool>("ipv6");
int port = uplink->Get<int>("port");
- const Anope::string &password = uplink->Get<const Anope::string>("password");
+ const Anope::string &password = uplink->Get<Anope::string>("password");
ValidateNotEmpty("uplink", "host", host);
ValidateNotZero("uplink", "port", port);
@@ -212,7 +265,7 @@ Conf::Conf() : Block("")
{
Block *module = this->GetBlock("module", i);
- const Anope::string &modname = module->Get<const Anope::string>("name");
+ const Anope::string &modname = module->Get<Anope::string>("name");
ValidateNotEmpty("module", "name", modname);
@@ -223,11 +276,11 @@ Conf::Conf() : Block("")
{
Block *opertype = this->GetBlock("opertype", i);
- const Anope::string &oname = opertype->Get<const Anope::string>("name"),
- &modes = opertype->Get<const Anope::string>("modes"),
- &inherits = opertype->Get<const Anope::string>("inherits"),
- &commands = opertype->Get<const Anope::string>("commands"),
- &privs = opertype->Get<const Anope::string>("privs");
+ const Anope::string &oname = opertype->Get<Anope::string>("name"),
+ &modes = opertype->Get<Anope::string>("modes"),
+ &inherits = opertype->Get<Anope::string>("inherits"),
+ &commands = opertype->Get<Anope::string>("commands"),
+ &privs = opertype->Get<Anope::string>("privs");
ValidateNotEmpty("opertype", "name", oname);
@@ -268,17 +321,17 @@ Conf::Conf() : Block("")
{
Block *oper = this->GetBlock("oper", i);
- const Anope::string &nname = oper->Get<const Anope::string>("name"),
- &type = oper->Get<const Anope::string>("type"),
- &password = oper->Get<const Anope::string>("password"),
- &certfp = oper->Get<const Anope::string>("certfp"),
- &host = oper->Get<const Anope::string>("host"),
- &vhost = oper->Get<const Anope::string>("vhost");
+ const Anope::string &nname = oper->Get<Anope::string>("name"),
+ &type = oper->Get<Anope::string>("type"),
+ &password = oper->Get<Anope::string>("password"),
+ &certfp = oper->Get<Anope::string>("certfp"),
+ &host = oper->Get<Anope::string>("host"),
+ &vhost = oper->Get<Anope::string>("vhost");
bool require_oper = oper->Get<bool>("require_oper");
ValidateNotEmpty("oper", "name", nname);
ValidateNotEmpty("oper", "type", type);
-
+
OperType *ot = NULL;
for (unsigned j = 0; j < this->MyOperTypes.size(); ++j)
if (this->MyOperTypes[j]->GetName() == type)
@@ -286,28 +339,29 @@ Conf::Conf() : Block("")
if (ot == NULL)
throw ConfigException("Oper block for " + nname + " has invalid oper type " + type);
- Oper *o = new Oper(nname, ot);
- o->require_oper = require_oper;
- o->password = password;
- o->certfp = certfp;
- spacesepstream(host).GetTokens(o->hosts);
- o->vhost = vhost;
-
- this->Opers.push_back(o);
+ Oper *o = Serialize::New<Oper *>();
+ o->conf = this;
+ o->SetName(nname);
+ o->SetType(ot);
+ o->SetRequireOper(require_oper);
+ o->SetPassword(password);
+ o->SetCertFP(certfp);
+ o->SetHost(host);
+ o->SetVhost(vhost);
}
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- it->second->conf = false;
+ for (BotInfo *bi : Serialize::GetObjects<BotInfo *>())
+ bi->conf = nullptr;
for (int i = 0; i < this->CountBlock("service"); ++i)
{
Block *service = this->GetBlock("service", i);
- const Anope::string &nick = service->Get<const Anope::string>("nick"),
- &user = service->Get<const Anope::string>("user"),
- &host = service->Get<const Anope::string>("host"),
- &gecos = service->Get<const Anope::string>("gecos"),
- &modes = service->Get<const Anope::string>("modes"),
- &channels = service->Get<const Anope::string>("channels");
+ const Anope::string &nick = service->Get<Anope::string>("nick"),
+ &user = service->Get<Anope::string>("user"),
+ &host = service->Get<Anope::string>("host"),
+ &gecos = service->Get<Anope::string>("gecos"),
+ &modes = service->Get<Anope::string>("modes"),
+ &channels = service->Get<Anope::string>("channels");
ValidateNotEmpty("service", "nick", nick);
ValidateNotEmpty("service", "user", user);
@@ -315,73 +369,19 @@ Conf::Conf() : Block("")
ValidateNotEmpty("service", "gecos", gecos);
ValidateNoSpaces("service", "channels", channels);
- BotInfo *bi = BotInfo::Find(nick, true);
- if (!bi)
- bi = new BotInfo(nick, user, host, gecos, modes);
- bi->conf = true;
-
- std::vector<Anope::string> oldchannels = bi->botchannels;
- bi->botchannels.clear();
- commasepstream sep(channels);
- for (Anope::string token; sep.GetToken(token);)
+ if (User *u = User::Find(nick, true))
{
- bi->botchannels.push_back(token);
- size_t ch = token.find('#');
- Anope::string chname, want_modes;
- if (ch == Anope::string::npos)
- chname = token;
- else
- {
- want_modes = token.substr(0, ch);
- chname = token.substr(ch);
- }
- bi->Join(chname);
- Channel *c = Channel::Find(chname);
- if (!c)
- continue; // Can't happen
-
- c->botchannel = true;
-
- /* Remove all existing modes */
- ChanUserContainer *cu = c->FindUser(bi);
- if (cu != NULL)
- for (size_t j = 0; j < cu->status.Modes().length(); ++j)
- c->RemoveMode(bi, ModeManager::FindChannelModeByChar(cu->status.Modes()[j]), bi->GetUID());
- /* Set the new modes */
- for (unsigned j = 0; j < want_modes.length(); ++j)
+ if (u->type != UserType::BOT)
{
- ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]);
- if (cm == NULL)
- cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j]));
- if (cm && cm->type == MODE_STATUS)
- c->SetMode(bi, cm, bi->GetUID());
+ u->Kill(Me, "Nickname required by services");
}
}
- for (unsigned k = 0; k < oldchannels.size(); ++k)
- {
- size_t ch = oldchannels[k].find('#');
- Anope::string chname = oldchannels[k].substr(ch != Anope::string::npos ? ch : 0);
- bool found = false;
- for (unsigned j = 0; j < bi->botchannels.size(); ++j)
- {
- ch = bi->botchannels[j].find('#');
- Anope::string ochname = bi->botchannels[j].substr(ch != Anope::string::npos ? ch : 0);
-
- if (chname.equals_ci(ochname))
- found = true;
- }
+ ServiceBot *sb = ServiceBot::Find(nick, true);
+ if (!sb)
+ sb = new ServiceBot(nick, user, host, gecos, modes);
- if (found)
- continue;
-
- Channel *c = Channel::Find(chname);
- if (c)
- {
- c->botchannel = false;
- bi->Part(c);
- }
- }
+ sb->bi->conf = service;
}
for (int i = 0; i < this->CountBlock("log"); ++i)
@@ -394,38 +394,45 @@ Conf::Conf() : Block("")
LogInfo l(logage, rawio, debug);
- l.bot = BotInfo::Find(log->Get<const Anope::string>("bot", "Global"), true);
- spacesepstream(log->Get<const Anope::string>("target")).GetTokens(l.targets);
- spacesepstream(log->Get<const Anope::string>("source")).GetTokens(l.sources);
- spacesepstream(log->Get<const Anope::string>("admin")).GetTokens(l.admin);
- spacesepstream(log->Get<const Anope::string>("override")).GetTokens(l.override);
- spacesepstream(log->Get<const Anope::string>("commands")).GetTokens(l.commands);
- spacesepstream(log->Get<const Anope::string>("servers")).GetTokens(l.servers);
- spacesepstream(log->Get<const Anope::string>("channels")).GetTokens(l.channels);
- spacesepstream(log->Get<const Anope::string>("users")).GetTokens(l.users);
- spacesepstream(log->Get<const Anope::string>("other")).GetTokens(l.normal);
+ l.bot = ServiceBot::Find(log->Get<Anope::string>("bot", "Global"), true);
+ spacesepstream(log->Get<Anope::string>("target")).GetTokens(l.targets);
+ spacesepstream(log->Get<Anope::string>("source")).GetTokens(l.sources);
+ spacesepstream(log->Get<Anope::string>("admin")).GetTokens(l.admin);
+ spacesepstream(log->Get<Anope::string>("override")).GetTokens(l.override);
+ spacesepstream(log->Get<Anope::string>("commands")).GetTokens(l.commands);
+ spacesepstream(log->Get<Anope::string>("servers")).GetTokens(l.servers);
+ spacesepstream(log->Get<Anope::string>("channels")).GetTokens(l.channels);
+ spacesepstream(log->Get<Anope::string>("users")).GetTokens(l.users);
+ spacesepstream(log->Get<Anope::string>("other")).GetTokens(l.normal);
this->LogInfos.push_back(l);
}
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- it->second->commands.clear();
+ for (std::pair<Anope::string, User *> p : UserListByNick)
+ {
+ User *u = p.second;
+ if (u->type != UserType::BOT)
+ continue;
+
+ ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
+ bi->commands.clear();
+ }
for (int i = 0; i < this->CountBlock("command"); ++i)
{
Block *command = this->GetBlock("command", i);
- const Anope::string &service = command->Get<const Anope::string>("service"),
- &nname = command->Get<const Anope::string>("name"),
- &cmd = command->Get<const Anope::string>("command"),
- &permission = command->Get<const Anope::string>("permission"),
- &group = command->Get<const Anope::string>("group");
+ const Anope::string &service = command->Get<Anope::string>("service"),
+ &nname = command->Get<Anope::string>("name"),
+ &cmd = command->Get<Anope::string>("command"),
+ &permission = command->Get<Anope::string>("permission"),
+ &group = command->Get<Anope::string>("group");
bool hide = command->Get<bool>("hide");
ValidateNotEmpty("command", "service", service);
ValidateNotEmpty("command", "name", nname);
ValidateNotEmpty("command", "command", cmd);
- BotInfo *bi = this->GetClient(service);
+ ServiceBot *bi = this->GetClient(service);
if (!bi)
continue;
@@ -434,26 +441,14 @@ Conf::Conf() : Block("")
ci.hide = hide;
}
- PrivilegeManager::ClearPrivileges();
- for (int i = 0; i < this->CountBlock("privilege"); ++i)
- {
- Block *privilege = this->GetBlock("privilege", i);
-
- const Anope::string &nname = privilege->Get<const Anope::string>("name"),
- &desc = privilege->Get<const Anope::string>("desc");
- int rank = privilege->Get<int>("rank");
-
- PrivilegeManager::AddPrivilege(Privilege(nname, desc, rank));
- }
-
for (int i = 0; i < this->CountBlock("fantasy"); ++i)
{
Block *fantasy = this->GetBlock("fantasy", i);
- const Anope::string &nname = fantasy->Get<const Anope::string>("name"),
- &service = fantasy->Get<const Anope::string>("command"),
- &permission = fantasy->Get<const Anope::string>("permission"),
- &group = fantasy->Get<const Anope::string>("group");
+ const Anope::string &nname = fantasy->Get<Anope::string>("name"),
+ &service = fantasy->Get<Anope::string>("command"),
+ &permission = fantasy->Get<Anope::string>("permission"),
+ &group = fantasy->Get<Anope::string>("group");
bool hide = fantasy->Get<bool>("hide"),
prepend_channel = fantasy->Get<bool>("prepend_channel", "yes");
@@ -462,6 +457,7 @@ Conf::Conf() : Block("")
CommandInfo &c = this->Fantasy[nname];
c.name = service;
+ c.cname = nname;
c.permission = permission;
c.group = group;
c.hide = hide;
@@ -472,8 +468,8 @@ Conf::Conf() : Block("")
{
Block *command_group = this->GetBlock("command_group", i);
- const Anope::string &nname = command_group->Get<const Anope::string>("name"),
- &description = command_group->Get<const Anope::string>("description");
+ const Anope::string &nname = command_group->Get<Anope::string>("name"),
+ &description = command_group->Get<Anope::string>("description");
CommandGroup gr;
gr.name = nname;
@@ -482,64 +478,151 @@ Conf::Conf() : Block("")
this->CommandGroups.push_back(gr);
}
- /* Below here can't throw */
-
- if (Config)
- /* Clear existing conf opers */
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
- {
- NickCore *nc = it->second;
- if (nc->o && std::find(Config->Opers.begin(), Config->Opers.end(), nc->o) != Config->Opers.end())
- nc->o = NULL;
- }
- /* Apply new opers */
- for (unsigned i = 0; i < this->Opers.size(); ++i)
+ for (int i = 0; i < this->CountBlock("usermode"); ++i)
{
- Oper *o = this->Opers[i];
+ Block *usermode = this->GetBlock("usermode", i);
- NickAlias *na = NickAlias::Find(o->name);
- if (!na)
- continue;
+ Anope::string nname = usermode->Get<Anope::string>("name"),
+ character = usermode->Get<Anope::string>("character");
+ bool oper_only = usermode->Get<bool>("oper_only"),
+ setable = usermode->Get<bool>("setable"),
+ param = usermode->Get<bool>("param");
- if (!na->nc || na->nc->o)
- {
- // If the account is already an oper it might mean two oper blocks for the same nick, or
- // something else has configured them as an oper (like a module)
- continue;
- }
+ ValidateNotEmpty("usermode", "name", nname);
+
+ if (character.length() != 1)
+ throw ConfigException("Usermode character length must be 1");
+
+ Usermode um;
+ um.name = nname;
+ um.character = character[0];
+ um.param = param;
+ um.oper_only = oper_only;
+ um.setable = setable;
- na->nc->o = o;
- Log() << "Tied oper " << na->nc->display << " to type " << o->ot->GetName();
+ this->Usermodes.push_back(um);
}
- if (options->Get<const Anope::string>("casemap", "ascii") == "ascii")
- Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>());
- else if (options->Get<const Anope::string>("casemap") == "rfc1459")
- Anope::casemap = std::locale(std::locale(), new Anope::rfc1459_ctype<char>());
- else
+ for (int i = 0; i < this->CountBlock("channelmode"); ++i)
{
- try
+ Block *channelmode = this->GetBlock("channelmode", i);
+
+ Anope::string nname = channelmode->Get<Anope::string>("name"),
+ character = channelmode->Get<Anope::string>("character"),
+ status = channelmode->Get<Anope::string>("status"),
+ param_regex = channelmode->Get<Anope::string>("param_regex");
+ bool oper_only = channelmode->Get<bool>("oper_only"),
+ setable = channelmode->Get<bool>("setable"),
+ list = channelmode->Get<bool>("list"),
+ param = channelmode->Get<bool>("param"),
+ param_unset = channelmode->Get<bool>("param_unset", "yes");
+ int level = channelmode->Get<int>("level");
+
+ ValidateNotEmpty("usermode", "name", nname);
+
+ if (character.length() != 1)
+ throw ConfigException("Channelmode character length must be 1");
+
+ if (status.length() > 1)
+ throw ConfigException("Channelmode status must be at most one character");
+
+ if (list || !param_regex.empty() || !status.empty())
+ param = true;
+
+ Channelmode cm;
+ cm.name = nname;
+ cm.character = character[0];
+ cm.status = !status.empty() ? status[0] : 0;
+ cm.param_regex = param_regex;
+ cm.oper_only = oper_only;
+ cm.setable = setable;
+ cm.list = list;
+ cm.param = param;
+ cm.param_unset = param_unset;
+ cm.level = level;
+
+ this->Channelmodes.push_back(cm);
+ }
+
+ for (int i = 0; i < this->CountBlock("casemap"); ++i)
+ {
+ Block *casemap = this->GetBlock("casemap", i);
+
+ unsigned char upper = casemap->Get<unsigned int>("upper"),
+ lower = casemap->Get<unsigned int>("lower");
+
+ if (!upper)
{
- Anope::casemap = std::locale(options->Get<const Anope::string>("casemap").c_str());
+ Anope::string s = casemap->Get<Anope::string>("upper");
+ if (s.length() == 1)
+ upper = s[0];
}
- catch (const std::runtime_error &)
+
+ if (!lower)
+ {
+ Anope::string s = casemap->Get<Anope::string>("lower");
+ if (s.length() == 1)
+ lower = s[0];
+ }
+
+ if (upper && lower)
{
- Log() << "Unknown casemap " << options->Get<const Anope::string>("casemap") << " - casemap not changed";
+ CaseMapUpper[lower] = CaseMapUpper[upper] = upper;
+ CaseMapLower[lower] = CaseMapLower[upper] = lower;
}
}
- Anope::CaseMapRebuild();
+
+ /* Below here can't throw */
+
+ /* Clear existing conf opers */
+ if (Config)
+ for (Oper *o : Serialize::GetObjects<Oper *>())
+ if (o->conf == Config)
+ o->Delete();
+ /* Apply new opers */
+ for (Oper *o : Serialize::GetObjects<Oper *>())
+ {
+ NickServ::Nick *na = NickServ::FindNick(o->GetName());
+ if (!na)
+ continue;
+
+ na->GetAccount()->o = o;
+ Log() << "Tied oper " << na->GetAccount()->GetDisplay() << " to type " << o->GetType()->GetName();
+ }
/* Check the user keys */
if (!options->Get<unsigned>("seed"))
Log() << "Configuration option options:seed should be set. It's for YOUR safety! Remember that!";
+
+ /* check regexengine */
+ const Anope::string &regex_engine = options->Get<Anope::string>("regexengine");
+ if (regex_engine == "ecmascript")
+ regex_flags = std::regex::ECMAScript;
+ else if (regex_engine == "basic")
+ regex_flags = std::regex::basic;
+ else if (regex_engine == "extended")
+ regex_flags = std::regex::extended;
+ else if (regex_engine == "awk")
+ regex_flags = std::regex::awk;
+ else if (regex_engine == "grep")
+ regex_flags = std::regex::grep;
+ else if (regex_engine == "egrep")
+ regex_flags = std::regex::egrep;
+ else
+ regex_flags = static_cast<std::basic_regex<char>::flag_type>(0);
+ /* always enable icase and optimize */
+ if (regex_flags)
+ regex_flags |= std::regex::icase | std::regex::optimize;
+
+ this->LineWrap = options->Get<unsigned>("linewrap", "200");
}
Conf::~Conf()
{
for (unsigned i = 0; i < MyOperTypes.size(); ++i)
delete MyOperTypes[i];
- for (unsigned i = 0; i < Opers.size(); ++i)
- delete Opers[i];
+
+ delete locale;
}
void Conf::Post(Conf *old)
@@ -552,33 +635,65 @@ void Conf::Post(Conf *old)
if (std::find(old->ModulesAutoLoad.begin(), old->ModulesAutoLoad.end(), this->ModulesAutoLoad[i]) == old->ModulesAutoLoad.end())
ModuleManager::LoadModule(this->ModulesAutoLoad[i], NULL);
+ ModeManager::Apply(old);
+
/* Apply opertype changes, as non-conf opers still point to the old oper types */
- for (unsigned i = Oper::opers.size(); i > 0; --i)
+ for (Oper *o : Serialize::GetObjects<Oper *>())
{
- Oper *o = Oper::opers[i - 1];
-
/* Oper's type is in the old config, so update it */
- if (std::find(old->MyOperTypes.begin(), old->MyOperTypes.end(), o->ot) != old->MyOperTypes.end())
+ if (std::find(old->MyOperTypes.begin(), old->MyOperTypes.end(), o->GetType()) != old->MyOperTypes.end())
{
- OperType *ot = o->ot;
- o->ot = NULL;
+ OperType *ot = o->GetType();
+ o->SetType(nullptr);
for (unsigned j = 0; j < MyOperTypes.size(); ++j)
if (ot->GetName() == MyOperTypes[j]->GetName())
- o->ot = MyOperTypes[j];
+ o->SetType(MyOperTypes[j]);
- if (o->ot == NULL)
+ if (o->GetType() == NULL)
{
/* Oper block has lost type */
- std::vector<Oper *>::iterator it = std::find(old->Opers.begin(), old->Opers.end(), o);
- if (it != old->Opers.end())
- old->Opers.erase(it);
+ o->Delete();
+ }
+ }
+ }
+
+ for (BotInfo *bi : Serialize::GetObjects<BotInfo *>())
+ {
+ if (!bi->conf)
+ {
+ bi->Delete();
+ continue;
+ }
+
+ for (int i = 0; i < bi->conf->CountBlock("channel"); ++i)
+ {
+ Block *channel = bi->conf->GetBlock("channel", i);
+
+ const Anope::string &chname = channel->Get<Anope::string>("name"),
+ &modes = channel->Get<Anope::string>("modes");
+
+ bi->bot->Join(chname);
- it = std::find(this->Opers.begin(), this->Opers.end(), o);
- if (it != this->Opers.end())
- this->Opers.erase(it);
+ Channel *c = Channel::Find(chname);
+ if (!c)
+ continue; // Can't happen
+
+ c->botchannel = true;
- delete o;
+ /* Remove all existing modes */
+ ChanUserContainer *cu = c->FindUser(bi->bot);
+ if (cu != NULL)
+ for (size_t j = 0; j < cu->status.Modes().length(); ++j)
+ c->RemoveMode(bi->bot, ModeManager::FindChannelModeByChar(cu->status.Modes()[j]), bi->bot->GetUID());
+ /* Set the new modes */
+ for (unsigned j = 0; j < modes.length(); ++j)
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[j]);
+ if (cm == NULL)
+ cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(modes[j]));
+ if (cm && cm->type == MODE_STATUS)
+ c->SetMode(bi->bot, cm, bi->bot->GetUID());
}
}
}
@@ -588,7 +703,7 @@ Block *Conf::GetModule(Module *m)
{
if (!m)
return NULL;
-
+
return GetModule(m->name);
}
@@ -599,30 +714,37 @@ Block *Conf::GetModule(const Anope::string &mname)
return it->second;
Block* &block = modules[mname];
-
+
/* Search for the block */
for (std::pair<block_map::iterator, block_map::iterator> iters = blocks.equal_range("module"); iters.first != iters.second; ++iters.first)
{
Block *b = &iters.first->second;
- if (b->Get<const Anope::string>("name") == mname)
+ if (b->Get<Anope::string>("name") == mname)
{
block = b;
break;
}
}
- return GetModule(mname);
+ if (block == nullptr)
+ {
+ /* not found, create new block */
+ auto it2 = blocks.emplace(mname, mname);
+ block = &it2->second;
+ }
+
+ return block;
}
-BotInfo *Conf::GetClient(const Anope::string &cname)
+ServiceBot *Conf::GetClient(const Anope::string &cname)
{
Anope::map<Anope::string>::iterator it = bots.find(cname);
if (it != bots.end())
- return BotInfo::Find(!it->second.empty() ? it->second : cname, true);
+ return ServiceBot::Find(!it->second.empty() ? it->second : cname, true);
Block *block = GetModule(cname.lower());
- const Anope::string &client = block->Get<const Anope::string>("client");
+ const Anope::string &client = block->Get<Anope::string>("client");
bots[cname] = client;
return GetClient(cname);
}
@@ -720,10 +842,10 @@ void Conf::LoadConf(File &file)
Log(LOG_DEBUG) << "Start to read conf " << file.GetName();
// Start reading characters...
while (!file.End())
- {
+ {
Anope::string line = file.Read();
++linenumber;
-
+
/* If this line is completely empty and we are in a quote, just append a newline */
if (line.empty() && in_quote)
wordbuffer += "\n";
@@ -884,10 +1006,10 @@ void Conf::LoadConf(File &file)
{
Block *define = this->GetBlock("define", i);
- const Anope::string &dname = define->Get<const Anope::string>("name");
+ const Anope::string &dname = define->Get<Anope::string>("name");
if (dname == wordbuffer && define != b)
- wordbuffer = define->Get<const Anope::string>("value");
+ wordbuffer = define->Get<Anope::string>("value");
}
if (b)
diff --git a/src/event.cpp b/src/event.cpp
new file mode 100644
index 000000000..8f59f9960
--- /dev/null
+++ b/src/event.cpp
@@ -0,0 +1,35 @@
+/*
+ * Anope IRC Services
+ *
+ * Copyright (C) 2014-2016 Adam <adam@anope.org>
+ * Copyright (C) 2016 Anope Team <team@anope.org>
+ *
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
+ */
+
+#include "services.h"
+#include "event.h"
+
+EventManager *EventManager::eventManager = nullptr;
+
+void EventManager::Init()
+{
+ eventManager = new EventManager();
+}
+
+EventManager *EventManager::Get()
+{
+ return eventManager;
+}
+
diff --git a/src/extensible.cpp b/src/extensible.cpp
index 4079290ff..dc468fae7 100644
--- a/src/extensible.cpp
+++ b/src/extensible.cpp
@@ -1,37 +1,39 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2013-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "extensible.h"
-static std::set<ExtensibleBase *> extensible_items;
-
-ExtensibleBase::ExtensibleBase(Module *m, const Anope::string &n) : Service(m, "Extensible", n)
+ExtensibleBase::ExtensibleBase(Module *m, const Anope::string &n) : ExtensibleBase(m, "Extensible", n)
{
- extensible_items.insert(this);
}
-ExtensibleBase::~ExtensibleBase()
+ExtensibleBase::ExtensibleBase(Module *m, const Anope::string &t, const Anope::string &n) : Service(m, t, n)
{
- extensible_items.erase(this);
}
Extensible::~Extensible()
{
- UnsetExtensibles();
-}
-
-void Extensible::UnsetExtensibles()
-{
while (!extension_items.empty())
(*extension_items.begin())->Unset(this);
}
-bool Extensible::HasExt(const Anope::string &name) const
+bool Extensible::HasExtOK(const Anope::string &name)
{
ExtensibleRef<void *> ref(name);
if (ref)
@@ -41,32 +43,3 @@ bool Extensible::HasExt(const Anope::string &name) const
return false;
}
-void Extensible::ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data)
-{
- for (std::set<ExtensibleBase *>::iterator it = e->extension_items.begin(); it != e->extension_items.end(); ++it)
- {
- ExtensibleBase *eb = *it;
- eb->ExtensibleSerialize(e, s, data);
- }
-}
-
-void Extensible::ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data)
-{
- for (std::set<ExtensibleBase *>::iterator it = extensible_items.begin(); it != extensible_items.end(); ++it)
- {
- ExtensibleBase *eb = *it;
- eb->ExtensibleUnserialize(e, s, data);
- }
-}
-
-template<>
-bool* Extensible::Extend(const Anope::string &name, const bool &what)
-{
- ExtensibleRef<bool> ref(name);
- if (ref)
- return ref->Set(this);
-
- Log(LOG_DEBUG) << "Extend for non-existent type " << name << " on " << static_cast<void *>(this);
- return NULL;
-}
-
diff --git a/src/hashcomp.cpp b/src/hashcomp.cpp
index 6374639d8..265cb362b 100644
--- a/src/hashcomp.cpp
+++ b/src/hashcomp.cpp
@@ -1,40 +1,46 @@
/*
+ * Anope IRC Services
*
- * (C) 2002-2011 InspIRCd Development Team
- * (C) 2008-2016 Anope Team <team@anope.org>
+ * Copyright (C) 2002-2011 InspIRCd Development Team
+ * Copyright (C) 2008-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "hashcomp.h"
#include "anope.h"
+#include "config.h"
-/* Case map in use by Anope */
-std::locale Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>());
-/* Cache of the above case map, forced upper */
-static unsigned char case_map_upper[256], case_map_lower[256];
-
-/* called whenever Anope::casemap is modified to rebuild the casemap cache */
-void Anope::CaseMapRebuild()
-{
- const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(Anope::casemap);
-
- for (unsigned i = 0; i < sizeof(case_map_upper); ++i)
- {
- case_map_upper[i] = ct.toupper(i);
- case_map_lower[i] = ct.tolower(i);
- }
-}
+#ifdef Boost_FOUND
+#include <boost/locale.hpp>
+#endif
unsigned char Anope::tolower(unsigned char c)
{
- return case_map_lower[c];
+ if (!Config || !Config->CaseMapLower[c])
+ return std::tolower(c);
+
+ return Config->CaseMapLower[c];
}
unsigned char Anope::toupper(unsigned char c)
{
- return case_map_upper[c];
+ if (!Config || !Config->CaseMapUpper[c])
+ return std::toupper(c);
+
+ return Config->CaseMapUpper[c];
}
/*
@@ -43,10 +49,10 @@ unsigned char Anope::toupper(unsigned char c)
* which is a case-insensitive equivalent to std::string.
*
*/
-
+
bool ci::ci_char_traits::eq(char c1st, char c2nd)
{
- return case_map_upper[static_cast<unsigned char>(c1st)] == case_map_upper[static_cast<unsigned char>(c2nd)];
+ return Anope::toupper(c1st) == Anope::toupper(c2nd);
}
bool ci::ci_char_traits::ne(char c1st, char c2nd)
@@ -56,15 +62,15 @@ bool ci::ci_char_traits::ne(char c1st, char c2nd)
bool ci::ci_char_traits::lt(char c1st, char c2nd)
{
- return case_map_upper[static_cast<unsigned char>(c1st)] < case_map_upper[static_cast<unsigned char>(c2nd)];
+ return Anope::toupper(c1st) < Anope::toupper(c2nd);
}
int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n)
{
for (unsigned i = 0; i < n; ++i)
{
- register unsigned char c1 = case_map_upper[static_cast<unsigned char>(*str1)],
- c2 = case_map_upper[static_cast<unsigned char>(*str2)];
+ unsigned char c1 = Anope::toupper(*str1),
+ c2 = Anope::toupper(*str2);
if (c1 > c2)
return 1;
@@ -81,7 +87,7 @@ int ci::ci_char_traits::compare(const char *str1, const char *str2, size_t n)
const char *ci::ci_char_traits::find(const char *s1, int n, char c)
{
- while (n-- > 0 && case_map_upper[static_cast<unsigned char>(*s1)] != case_map_upper[static_cast<unsigned char>(c)])
+ while (n-- > 0 && Anope::toupper(*s1) != Anope::toupper(c))
++s1;
return n >= 0 ? s1 : NULL;
}
@@ -162,3 +168,77 @@ bool sepstream::StreamEnd()
return this->pos > this->tokens.length();
}
+size_t Anope::hash::operator()(const Anope::string &s) const
+{
+ return std::hash<std::string>()(s.str());
+}
+
+bool Anope::compare::operator()(const Anope::string &s1, const Anope::string &s2) const
+{
+ return s1.equals_cs(s2);
+}
+
+size_t Anope::hash_ci::operator()(const Anope::string &s) const
+{
+ return std::hash<std::string>()(s.lower().str());
+}
+
+bool Anope::compare_ci::operator()(const Anope::string &s1, const Anope::string &s2) const
+{
+ return s1.equals_ci(s2);
+}
+
+size_t Anope::hash_locale::operator()(const Anope::string &s) const
+{
+#ifdef Boost_FOUND
+ if (Config != nullptr && Config->locale != nullptr)
+ {
+ return Anope::locale::hash(s.str());
+ }
+#endif
+
+ return Anope::hash_ci()(s);
+}
+
+bool Anope::compare_locale::operator()(const Anope::string &s1, const Anope::string &s2) const
+{
+#ifdef Boost_FOUND
+ if (Config != nullptr && Config->locale != nullptr)
+ {
+ return Anope::locale::compare(s1.str(), s2.str()) == 0;
+ }
+#endif
+
+ return Anope::compare_ci()(s1, s2);
+}
+
+#ifdef Boost_FOUND
+
+std::locale Anope::locale::generate(const std::string &name)
+{
+ boost::locale::generator gen;
+ return gen.generate(name);
+}
+
+int Anope::locale::compare(const std::string &s1, const std::string &s2)
+{
+ std::string c1 = boost::locale::conv::between(s1.data(), s1.data() + s1.length(),
+ Config->locale->name(),
+ "");
+
+ std::string c2 = boost::locale::conv::between(s2.data(), s2.data() + s2.length(),
+ Config->locale->name(),
+ "");
+
+ const boost::locale::collator<char> &ct = std::use_facet<boost::locale::collator<char>>(*Config->locale);
+ return ct.compare(boost::locale::collator_base::secondary, c1, c2);
+}
+
+long Anope::locale::hash(const std::string &s)
+{
+ const boost::locale::collator<char> &ct = std::use_facet<boost::locale::collator<char>>(*Config->locale);
+ return ct.hash(boost::locale::collator_base::secondary, s.data(), s.data() + s.length());
+}
+
+#endif
+
diff --git a/src/init.cpp b/src/init.cpp
index 7e5722603..ec23a7b4b 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,12 +1,20 @@
-/* Initialization and related routines.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -18,6 +26,8 @@
#include "socketengine.h"
#include "servers.h"
#include "language.h"
+#include "event.h"
+#include "modules.h"
#ifndef _WIN32
#include <sys/wait.h>
@@ -105,7 +115,7 @@ void Anope::Fork()
{
#ifndef _WIN32
kill(getppid(), SIGUSR2);
-
+
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
@@ -207,14 +217,14 @@ static void InitSignals()
static void remove_pidfile()
{
- remove(Config->GetBlock("serverinfo")->Get<const Anope::string>("pid").c_str());
+ remove(Config->GetBlock("serverinfo")->Get<Anope::string>("pid").c_str());
}
/* Create our PID file and write the PID to it. */
static void write_pidfile()
{
- FILE *pidfile = fopen(Config->GetBlock("serverinfo")->Get<const Anope::string>("pid").c_str(), "w");
+ FILE *pidfile = fopen(Config->GetBlock("serverinfo")->Get<Anope::string>("pid").c_str(), "w");
if (pidfile)
{
#ifdef _WIN32
@@ -226,7 +236,7 @@ static void write_pidfile()
atexit(remove_pidfile);
}
else
- throw CoreException("Can not write to PID file " + Config->GetBlock("serverinfo")->Get<const Anope::string>("pid"));
+ throw CoreException("Can not write to PID file " + Config->GetBlock("serverinfo")->Get<Anope::string>("pid"));
}
static void setuidgid()
@@ -236,21 +246,21 @@ static void setuidgid()
uid_t uid = -1;
gid_t gid = -1;
- if (!options->Get<const Anope::string>("user").empty())
+ if (!options->Get<Anope::string>("user").empty())
{
errno = 0;
- struct passwd *u = getpwnam(options->Get<const Anope::string>("user").c_str());
+ struct passwd *u = getpwnam(options->Get<Anope::string>("user").c_str());
if (u == NULL)
- Log() << "Unable to setuid to " << options->Get<const Anope::string>("user") << ": " << Anope::LastError();
+ Log() << "Unable to setuid to " << options->Get<Anope::string>("user") << ": " << Anope::LastError();
else
uid = u->pw_uid;
}
- if (!options->Get<const Anope::string>("group").empty())
+ if (!options->Get<Anope::string>("group").empty())
{
errno = 0;
- struct group *g = getgrnam(options->Get<const Anope::string>("group").c_str());
+ struct group *g = getgrnam(options->Get<Anope::string>("group").c_str());
if (g == NULL)
- Log() << "Unable to setgid to " << options->Get<const Anope::string>("group") << ": " << Anope::LastError();
+ Log() << "Unable to setgid to " << options->Get<Anope::string>("group") << ": " << Anope::LastError();
else
gid = g->gr_gid;
}
@@ -270,16 +280,16 @@ static void setuidgid()
if (static_cast<int>(gid) != -1)
{
if (setgid(gid) == -1)
- Log() << "Unable to setgid to " << options->Get<const Anope::string>("group") << ": " << Anope::LastError();
+ Log() << "Unable to setgid to " << options->Get<Anope::string>("group") << ": " << Anope::LastError();
else
- Log() << "Successfully set group to " << options->Get<const Anope::string>("group");
+ Log() << "Successfully set group to " << options->Get<Anope::string>("group");
}
if (static_cast<int>(uid) != -1)
{
if (setuid(uid) == -1)
- Log() << "Unable to setuid to " << options->Get<const Anope::string>("user") << ": " << Anope::LastError();
+ Log() << "Unable to setuid to " << options->Get<Anope::string>("user") << ": " << Anope::LastError();
else
- Log() << "Successfully set user to " << options->Get<const Anope::string>("user");
+ Log() << "Successfully set user to " << options->Get<Anope::string>("user");
}
#endif
}
@@ -291,8 +301,6 @@ void Anope::Init(int ac, char **av)
umask(DEFUMASK);
#endif
- Serialize::RegisterTypes();
-
/* Parse command line arguments */
ParseCommandLineArguments(ac, av);
@@ -423,7 +431,7 @@ void Anope::Init(int ac, char **av)
{
/* If we are configured to setuid later, don't issue a warning */
Configuration::Block *options = Config->GetBlock("options");
- if (options->Get<const Anope::string>("user").empty())
+ if (options->Get<Anope::string>("user").empty())
{
std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl;
std::cerr << " require root privileges to run, and it is discouraged that you run Anope" << std::endl;
@@ -480,6 +488,13 @@ void Anope::Init(int ac, char **av)
/* Initialize the socket engine. Note that some engines can not survive a fork(), so this must be here. */
SocketEngine::Init();
+ ServiceManager::Init();
+ EventManager::Init();
+
+ new BotInfoType();
+ new XLineType(nullptr);
+ new OperBlockType();
+
/* Read configuration file; exit if there are problems. */
try
{
@@ -488,7 +503,7 @@ void Anope::Init(int ac, char **av)
catch (const ConfigException &ex)
{
Log(LOG_TERMINAL) << ex.GetReason();
- Log(LOG_TERMINAL) << "*** Support resources: Read through the services.conf self-contained";
+ Log(LOG_TERMINAL) << "*** Support resources: Read through the anope.conf self-contained";
Log(LOG_TERMINAL) << "*** documentation. Read the documentation files found in the 'docs'";
Log(LOG_TERMINAL) << "*** folder. Visit our portal located at http://www.anope.org/. Join";
Log(LOG_TERMINAL) << "*** our support channel on /server irc.anope.org channel #anope.";
@@ -497,10 +512,15 @@ void Anope::Init(int ac, char **av)
/* Create me */
Configuration::Block *block = Config->GetBlock("serverinfo");
- Me = new Server(NULL, block->Get<const Anope::string>("name"), 0, block->Get<const Anope::string>("description"), block->Get<const Anope::string>("id"));
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
+ Me = new Server(NULL, block->Get<Anope::string>("name"), 0, block->Get<Anope::string>("description"), block->Get<Anope::string>("id"));
+ for (std::pair<Anope::string, User *> p : UserListByNick)
{
- it->second->server = Me;
+ User *u = p.second;
+ if (u->type != UserType::BOT)
+ continue;
+
+ ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
+ bi->server = Me;
++Me->users;
}
@@ -516,10 +536,12 @@ void Anope::Init(int ac, char **av)
block = Config->GetBlock("options");
srand(block->Get<unsigned>("seed") ^ time(NULL));
+ ModeManager::Apply(nullptr);
+
/* load modules */
Log() << "Loading modules...";
for (int i = 0; i < Config->CountBlock("module"); ++i)
- ModuleManager::LoadModule(Config->GetBlock("module", i)->Get<const Anope::string>("name"), NULL);
+ ModuleManager::LoadModule(Config->GetBlock("module", i)->Get<Anope::string>("name"), NULL);
#ifndef _WIN32
/* We won't background later, so we should setuid now */
@@ -542,20 +564,24 @@ void Anope::Init(int ac, char **av)
Anope::string sid = IRCD->SID_Retrieve();
if (Me->GetSID() == Me->GetName())
Me->SetSID(sid);
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- it->second->GenerateUID();
+ for (std::pair<Anope::string, User *> p : UserListByNick)
+ {
+ User *u = p.second;
+ if (u->type != UserType::BOT)
+ continue;
+
+ ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
+ bi->GenerateUID();
+ }
}
/* Load up databases */
Log() << "Loading databases...";
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnLoadDatabase, MOD_RESULT, ());
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::LoadDatabase::OnLoadDatabase);;
static_cast<void>(MOD_RESULT);
Log() << "Databases loaded";
for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
it->second->Sync();
-
- Serialize::CheckTypes();
}
diff --git a/src/language.cpp b/src/language.cpp
index 0a19729b1..8c3e6221a 100644
--- a/src/language.cpp
+++ b/src/language.cpp
@@ -1,12 +1,20 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -14,6 +22,7 @@
#include "commands.h"
#include "config.h"
#include "language.h"
+#include "modules/nickserv.h"
#if GETTEXT_FOUND
# include <libintl.h>
@@ -36,7 +45,7 @@ void Language::InitLanguages()
setlocale(LC_ALL, "");
- spacesepstream sep(Config->GetBlock("options")->Get<const Anope::string>("languages"));
+ spacesepstream sep(Config->GetBlock("options")->Get<Anope::string>("languages"));
Anope::string language;
while (sep.GetToken(language))
{
@@ -60,6 +69,11 @@ const char *Language::Translate(const char *string)
return Translate("", string);
}
+const char *Language::Translate(const Anope::string &string)
+{
+ return Translate("", string.c_str());
+}
+
const char *Language::Translate(User *u, const char *string)
{
if (u && u->Account())
@@ -68,9 +82,19 @@ const char *Language::Translate(User *u, const char *string)
return Translate("", string);
}
-const char *Language::Translate(const NickCore *nc, const char *string)
+const char *Language::Translate(User *u, const Anope::string &string)
+{
+ return Translate(u, string.c_str());
+}
+
+const char *Language::Translate(NickServ::Account *nc, const char *string)
+{
+ return Translate(nc ? nc->GetLanguage().c_str() : "", string);
+}
+
+const char *Language::Translate(NickServ::Account *nc, const Anope::string &string)
{
- return Translate(nc ? nc->language.c_str() : "", string);
+ return Translate(nc, string.c_str());
}
#if GETTEXT_FOUND
diff --git a/src/logger.cpp b/src/logger.cpp
index c681e42fa..0d379e568 100644
--- a/src/logger.cpp
+++ b/src/logger.cpp
@@ -1,12 +1,20 @@
-/* Logging routines.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2010-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -20,6 +28,9 @@
#include "servers.h"
#include "uplink.h"
#include "protocol.h"
+#include "event.h"
+#include "modules/nickserv.h"
+#include "modules/chanserv.h"
#ifndef _WIN32
#include <sys/time.h>
@@ -74,23 +85,23 @@ const Anope::string &LogFile::GetName() const
return this->filename;
}
-Log::Log(LogType t, const Anope::string &cat, BotInfo *b) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(t), category(cat)
+Log::Log(LogType t, const Anope::string &cat, ServiceBot *b) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(t), category(cat)
{
}
-Log::Log(LogType t, CommandSource &src, Command *_c, ChannelInfo *_ci) : u(src.GetUser()), nc(src.nc), c(_c), source(&src), chan(NULL), ci(_ci), s(NULL), m(NULL), type(t)
+Log::Log(LogType t, CommandSource &src, Command *_c, ChanServ::Channel *_ci) : u(src.GetUser()), nc(src.nc), c(_c), source(&src), chan(NULL), ci(_ci), s(NULL), m(NULL), type(t)
{
if (!c)
throw CoreException("Invalid pointers passed to Log::Log");
-
+
if (type != LOG_COMMAND && type != LOG_OVERRIDE && type != LOG_ADMIN)
throw CoreException("This constructor does not support this log type");
- size_t sl = c->name.find('/');
+ size_t sl = c->GetName().find('/');
this->bi = NULL;
if (sl != Anope::string::npos)
- this->bi = BotInfo::Find(c->name.substr(0, sl), true);
- this->category = c->name;
+ this->bi = ServiceBot::Find(c->GetName().substr(0, sl), true);
+ this->category = c->GetName();
}
Log::Log(User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u), nc(NULL), c(NULL), source(NULL), chan(ch), ci(chan ? *chan->ci : NULL), s(NULL), m(NULL), type(LOG_CHANNEL), category(cat)
@@ -99,23 +110,23 @@ Log::Log(User *_u, Channel *ch, const Anope::string &cat) : bi(NULL), u(_u), nc(
throw CoreException("Invalid pointers passed to Log::Log");
}
-Log::Log(User *_u, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat)
+Log::Log(User *_u, const Anope::string &cat, ServiceBot *_bi) : bi(_bi), u(_u), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_USER), category(cat)
{
if (!u)
throw CoreException("Invalid pointers passed to Log::Log");
}
-Log::Log(Server *serv, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat)
+Log::Log(Server *serv, const Anope::string &cat, ServiceBot *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(serv), m(NULL), type(LOG_SERVER), category(cat)
{
if (!s)
throw CoreException("Invalid pointer passed to Log::Log");
}
-Log::Log(BotInfo *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat)
+Log::Log(ServiceBot *b, const Anope::string &cat) : bi(b), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(NULL), type(LOG_NORMAL), category(cat)
{
}
-Log::Log(Module *mod, const Anope::string &cat, BotInfo *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat)
+Log::Log(Module *mod, const Anope::string &cat, ServiceBot *_bi) : bi(_bi), u(NULL), nc(NULL), c(NULL), source(NULL), chan(NULL), ci(NULL), s(NULL), m(mod), type(LOG_MODULE), category(cat)
{
}
@@ -128,8 +139,16 @@ Log::~Log()
else if (this->type == LOG_TERMINAL)
std::cout << this->BuildPrefix() << this->buf.str() << std::endl;
- FOREACH_MOD(OnLog, (this));
-
+ /* Some of the higher debug messages are in the event/service system which manages event dispatch,
+ * so firing off the log event here can cause them to be in weird states
+ */
+ if (this->type <= LOG_NORMAL)
+ {
+ EventManager *em = EventManager::Get();
+ if (em != nullptr)
+ em->Dispatch(&Event::Log::OnLog, this);
+ }
+
if (Config)
for (unsigned i = 0; i < Config->LogInfos.size(); ++i)
if (Config->LogInfos[i].HasType(this->type, this->category))
@@ -140,19 +159,19 @@ Anope::string Log::FormatSource() const
{
if (u)
if (nc)
- return this->u->GetMask() + " (" + this->nc->display + ")";
+ return this->u->GetMask() + " (" + this->nc->GetDisplay() + ")";
else
return this->u->GetMask();
else if (nc)
- return nc->display;
+ return nc->GetDisplay();
return "";
}
Anope::string Log::FormatCommand() const
{
- Anope::string buffer = FormatSource() + " used " + (source != NULL && !source->command.empty() ? source->command : this->c->name) + " ";
+ Anope::string buffer = FormatSource() + " used " + (source != NULL && !source->command.empty() ? source->command : this->c->GetName()) + " ";
if (this->ci)
- buffer += "on " + this->ci->name + " ";
+ buffer += "on " + this->ci->GetName() + " ";
return buffer;
}
@@ -329,9 +348,9 @@ void LogInfo::ProcessMessage(const Log *l)
log = true;
else if (l->u && src == l->u->nick)
log = true;
- else if (l->nc && src == l->nc->display)
+ else if (l->nc && src == l->nc->GetDisplay())
log = true;
- else if (l->ci && src == l->ci->name)
+ else if (l->ci && src == l->ci->GetName())
log = true;
else if (l->m && src == l->m->name)
log = true;
@@ -344,7 +363,7 @@ void LogInfo::ProcessMessage(const Log *l)
const Anope::string &buffer = l->BuildPrefix() + l->buf.str();
- FOREACH_MOD(OnLogMessage, (this, l, buffer));
+ EventManager::Get()->Dispatch(&Event::LogMessage::OnLogMessage, this, l, buffer);
for (unsigned i = 0; i < this->targets.size(); ++i)
{
@@ -358,7 +377,7 @@ void LogInfo::ProcessMessage(const Log *l)
if (!c)
continue;
- BotInfo *bi = l->bi;
+ User *bi = l->bi;
if (!bi)
bi = this->bot;
if (!bi)
@@ -375,7 +394,7 @@ void LogInfo::ProcessMessage(const Log *l)
}
}
}
-
+
tm *tm = localtime(&Anope::CurTime);
if (tm->tm_mday != this->last_day)
{
diff --git a/src/mail.cpp b/src/mail.cpp
index f909fa5a3..02a39bd13 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -1,19 +1,30 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "mail.h"
#include "config.h"
+#include "bots.h"
+#include "protocol.h"
+#include "modules/nickserv.h"
-Mail::Message::Message(const Anope::string &sf, const Anope::string &mailto, const Anope::string &a, const Anope::string &s, const Anope::string &m) : Thread(), sendmail_path(Config->GetBlock("mail")->Get<const Anope::string>("sendmailpath")), send_from(sf), mail_to(mailto), addr(a), subject(s), message(m), dont_quote_addresses(Config->GetBlock("mail")->Get<bool>("dontquoteaddresses")), success(false)
+Mail::Message::Message(const Anope::string &sf, const Anope::string &mailto, const Anope::string &a, const Anope::string &s, const Anope::string &m) : Thread(), sendmail_path(Config->GetBlock("mail")->Get<Anope::string>("sendmailpath")), send_from(sf), mail_to(mailto), addr(a), subject(s), message(m), dont_quote_addresses(Config->GetBlock("mail")->Get<bool>("dontquoteaddresses")), success(false)
{
}
@@ -50,37 +61,37 @@ void Mail::Message::Run()
SetExitState();
}
-bool Mail::Send(User *u, NickCore *nc, BotInfo *service, const Anope::string &subject, const Anope::string &message)
+bool Mail::Send(User *u, NickServ::Account *nc, ServiceBot *service, const Anope::string &subject, const Anope::string &message)
{
if (!nc || !service || subject.empty() || message.empty())
return false;
Configuration::Block *b = Config->GetBlock("mail");
-
+
if (!u)
{
- if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty())
+ if (!b->Get<bool>("usemail") || b->Get<Anope::string>("sendfrom").empty())
return false;
- else if (nc->email.empty())
+ else if (nc->GetEmail().empty())
return false;
nc->lastmail = Anope::CurTime;
- Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message);
+ Thread *t = new Mail::Message(b->Get<Anope::string>("sendfrom"), nc->GetDisplay(), nc->GetEmail(), subject, message);
t->Start();
return true;
}
else
{
- if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty())
+ if (!b->Get<bool>("usemail") || b->Get<Anope::string>("sendfrom").empty())
u->SendMessage(service, _("Services have been configured to not send mail."));
else if (Anope::CurTime - u->lastmail < b->Get<time_t>("delay"))
u->SendMessage(service, _("Please wait \002%d\002 seconds and retry."), b->Get<time_t>("delay") - (Anope::CurTime - u->lastmail));
- else if (nc->email.empty())
- u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->display.c_str());
+ else if (nc->GetEmail().empty())
+ u->SendMessage(service, _("E-mail for \002%s\002 is invalid."), nc->GetDisplay().c_str());
else
{
u->lastmail = nc->lastmail = Anope::CurTime;
- Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message);
+ Thread *t = new Mail::Message(b->Get<Anope::string>("sendfrom"), nc->GetDisplay(), nc->GetEmail(), subject, message);
t->Start();
return true;
}
@@ -89,14 +100,14 @@ bool Mail::Send(User *u, NickCore *nc, BotInfo *service, const Anope::string &su
}
}
-bool Mail::Send(NickCore *nc, const Anope::string &subject, const Anope::string &message)
+bool Mail::Send(NickServ::Account *nc, const Anope::string &subject, const Anope::string &message)
{
Configuration::Block *b = Config->GetBlock("mail");
- if (!b->Get<bool>("usemail") || b->Get<const Anope::string>("sendfrom").empty() || !nc || nc->email.empty() || subject.empty() || message.empty())
+ if (!b->Get<bool>("usemail") || b->Get<Anope::string>("sendfrom").empty() || !nc || nc->GetEmail().empty() || subject.empty() || message.empty())
return false;
nc->lastmail = Anope::CurTime;
- Thread *t = new Mail::Message(b->Get<const Anope::string>("sendfrom"), nc->display, nc->email, subject, message);
+ Thread *t = new Mail::Message(b->Get<Anope::string>("sendfrom"), nc->GetDisplay(), nc->GetEmail(), subject, message);
t->Start();
return true;
diff --git a/src/main.cpp b/src/main.cpp
index bbcccee27..33cd9b23f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,12 +1,20 @@
-/* Services -- main source file.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -15,6 +23,8 @@
#include "bots.h"
#include "socketengine.h"
#include "uplink.h"
+#include "event.h"
+#include "modules.h"
#ifndef _WIN32
#include <limits.h>
@@ -46,7 +56,7 @@ class UpdateTimer : public Timer
public:
UpdateTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { }
- void Tick(time_t) anope_override
+ void Tick(time_t) override
{
Anope::SaveDatabases();
}
@@ -57,9 +67,9 @@ class ExpireTimer : public Timer
public:
ExpireTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { }
- void Tick(time_t) anope_override
+ void Tick(time_t) override
{
- FOREACH_MOD(OnExpireTick, ());
+ EventManager::Get()->Dispatch(&Event::ExpireTick::OnExpireTick);
}
};
@@ -69,7 +79,7 @@ void Anope::SaveDatabases()
return;
Log(LOG_DEBUG) << "Saving databases";
- FOREACH_MOD(OnSaveDatabase, ());
+ EventManager::Get()->Dispatch(&Event::SaveDatabase::OnSaveDatabase);
}
/** The following comes from InspIRCd to get the full path of the Anope executable
@@ -113,9 +123,6 @@ static Anope::string GetFullProgDir(const Anope::string &argv0)
int main(int ac, char **av, char **envp)
{
- /* String comparisons won't work until we build the case map cache, so do it first */
- Anope::CaseMapRebuild();
-
BinaryDir = GetFullProgDir(av[0]);
if (BinaryDir[BinaryDir.length() - 1] == '.')
BinaryDir = BinaryDir.substr(0, BinaryDir.length() - 2);
@@ -180,11 +187,11 @@ int main(int ac, char **av, char **envp)
if (Anope::Restarting)
{
- FOREACH_MOD(OnRestart, ());
+ EventManager::Get()->Dispatch(&Event::Restart::OnRestart);
}
else
{
- FOREACH_MOD(OnShutdown, ());
+ EventManager::Get()->Dispatch(&Event::Shutdown::OnShutdown);
}
if (Anope::QuitReason.empty())
diff --git a/src/memos.cpp b/src/memos.cpp
deleted file mode 100644
index bf8f0eb73..000000000
--- a/src/memos.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/* MemoServ functions.
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "services.h"
-#include "modules.h"
-#include "service.h"
-#include "memo.h"
-#include "users.h"
-#include "account.h"
-#include "regchannel.h"
-
-Memo::Memo() : Serializable("Memo")
-{
- mi = NULL;
- unread = receipt = false;
-}
-
-Memo::~Memo()
-{
- if (mi)
- {
- std::vector<Memo *>::iterator it = std::find(mi->memos->begin(), mi->memos->end(), this);
-
- if (it != mi->memos->end())
- mi->memos->erase(it);
- }
-}
-
-void Memo::Serialize(Serialize::Data &data) const
-{
- data["owner"] << this->owner;
- data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time;
- data["sender"] << this->sender;
- data["text"] << this->text;
- data["unread"] << this->unread;
- data["receipt"] << this->receipt;
-}
-
-Serializable* Memo::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string owner;
-
- data["owner"] >> owner;
-
- bool ischan;
- MemoInfo *mi = MemoInfo::GetMemoInfo(owner, ischan);
- if (!mi)
- return NULL;
-
- Memo *m;
- if (obj)
- m = anope_dynamic_static_cast<Memo *>(obj);
- else
- {
- m = new Memo();
- m->mi = mi;
- }
-
- m->owner = owner;
- data["time"] >> m->time;
- data["sender"] >> m->sender;
- data["text"] >> m->text;
- data["unread"] >> m->unread;
- data["receipt"] >> m->receipt;
-
- if (obj == NULL)
- mi->memos->push_back(m);
- return m;
-}
-
-MemoInfo::MemoInfo() : memomax(0), memos("Memo")
-{
-}
-
-Memo *MemoInfo::GetMemo(unsigned index) const
-{
- if (index >= this->memos->size())
- return NULL;
- Memo *m = (*memos)[index];
- m->QueueUpdate();
- return m;
-}
-
-unsigned MemoInfo::GetIndex(Memo *m) const
-{
- for (unsigned i = 0; i < this->memos->size(); ++i)
- if (this->GetMemo(i) == m)
- return i;
- return -1;
-}
-
-void MemoInfo::Del(unsigned index)
-{
- if (index >= this->memos->size())
- return;
-
- Memo *m = this->GetMemo(index);
-
- std::vector<Memo *>::iterator it = std::find(memos->begin(), memos->end(), m);
- if (it != memos->end())
- memos->erase(it);
-
- delete m;
-}
-
-bool MemoInfo::HasIgnore(User *u)
-{
- for (unsigned i = 0; i < this->ignores.size(); ++i)
- if (u->nick.equals_ci(this->ignores[i]) || (u->Account() && u->Account()->display.equals_ci(this->ignores[i])) || Anope::Match(u->GetMask(), Anope::string(this->ignores[i])))
- return true;
- return false;
-}
-
-MemoInfo *MemoInfo::GetMemoInfo(const Anope::string &target, bool &ischan)
-{
- if (!target.empty() && target[0] == '#')
- {
- ischan = true;
- ChannelInfo *ci = ChannelInfo::Find(target);
- if (ci != NULL)
- return &ci->memos;
- }
- else
- {
- ischan = false;
- NickAlias *na = NickAlias::Find(target);
- if (na != NULL)
- return &na->nc->memos;
- }
-
- return NULL;
-}
-
diff --git a/src/messages.cpp b/src/messages.cpp
index ee02cc473..c778de383 100644
--- a/src/messages.cpp
+++ b/src/messages.cpp
@@ -1,12 +1,20 @@
-/* Common message handlers
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -19,6 +27,9 @@
#include "messages.h"
#include "servers.h"
#include "channels.h"
+#include "event.h"
+#include "bots.h"
+#include "modules/operserv/stats.h"
using namespace Message;
@@ -26,7 +37,8 @@ void Away::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
const Anope::string &msg = !params.empty() ? params[0] : "";
- FOREACH_MOD(OnUserAway, (source.GetUser(), msg));
+ EventManager::Get()->Dispatch(&Event::UserAway::OnUserAway, source.GetUser(), msg);
+
if (!msg.empty())
Log(source.GetUser(), "away") << "is now away: " << msg;
else
@@ -61,8 +73,8 @@ void Invite::Run(MessageSource &source, const std::vector<Anope::string> &params
if (!targ || targ->server != Me || !c || c->FindUser(targ))
return;
-
- FOREACH_MOD(OnInvite, (source.GetUser(), c, targ));
+
+ EventManager::Get()->Dispatch(&Event::Invite::OnInvite, source.GetUser(), c, targ);
}
void Join::Run(MessageSource &source, const std::vector<Anope::string> &params)
@@ -84,9 +96,9 @@ void Join::Run(MessageSource &source, const std::vector<Anope::string> &params)
Channel *c = cc->chan;
++it;
- FOREACH_MOD(OnPrePartChannel, (user, c));
+ EventManager::Get()->Dispatch(&Event::PrePartChannel::OnPrePartChannel, user, c);
cc->chan->DeleteUser(user);
- FOREACH_MOD(OnPartChannel, (user, c, c->name, ""));
+ EventManager::Get()->Dispatch(&Event::PartChannel::OnPartChannel, user, c, c->name, "");
}
continue;
}
@@ -119,14 +131,14 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co
/* Their TS is newer, don't accept any modes from them */
else if (ts > c->creation_time)
keep_their_modes = false;
-
+
/* Update the modes for the channel */
if (keep_their_modes && !modes.empty())
/* If we are syncing, mlock is checked later in Channel::Sync. It is important to not check it here
* so that Channel::SetCorrectModes can correctly detect the presence of channel mode +r.
*/
c->SetModesInternal(source, modes, ts, !c->syncing);
-
+
for (std::list<SJoinUser>::const_iterator it = users.begin(), it_end = users.end(); it != it_end; ++it)
{
const ChannelStatus &status = it->first;
@@ -147,8 +159,8 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co
* they aren't allowed to have (secureops etc).
*/
c->SetCorrectModes(u, true);
-
- FOREACH_MOD(OnJoinChannel, (u, c));
+
+ EventManager::Get()->Dispatch(&Event::JoinChannel::OnJoinChannel, u, c);
}
/* Channel is done syncing */
@@ -187,13 +199,13 @@ void Kick::Run(MessageSource &source, const std::vector<Anope::string> &params)
void Kill::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
User *u = User::Find(params[0]);
- BotInfo *bi;
+ ServiceBot *bi;
if (!u)
return;
/* Recover if someone kills us. */
- if (u->server == Me && (bi = dynamic_cast<BotInfo *>(u)))
+ if (u->server == Me && (bi = dynamic_cast<ServiceBot *>(u)))
{
static time_t last_time = 0;
@@ -240,7 +252,7 @@ void MOTD::Run(MessageSource &source, const std::vector<Anope::string> &params)
if (s != Me)
return;
- FILE *f = fopen(Config->GetBlock("serverinfo")->Get<const Anope::string>("motd").c_str(), "r");
+ FILE *f = fopen(Config->GetBlock("serverinfo")->Get<Anope::string>("motd").c_str(), "r");
if (f)
{
IRCD->SendNumeric(375, source.GetSource(), ":- %s Message of the Day", s->GetName().c_str());
@@ -266,10 +278,10 @@ void Notice::Run(MessageSource &source, const std::vector<Anope::string> &params
/* ignore channel notices */
if (!IRCD->IsChannelValid(params[0]))
{
- BotInfo *bi = BotInfo::Find(params[0]);
+ ServiceBot *bi = ServiceBot::Find(params[0]);
if (!bi)
return;
- FOREACH_MOD(OnBotNotice, (u, bi, message));
+ EventManager::Get()->Dispatch(&Event::BotNotice::OnBotNotice, u, bi, message);
}
}
@@ -289,9 +301,10 @@ void Part::Run(MessageSource &source, const std::vector<Anope::string> &params)
continue;
Log(u, c, "part") << "Reason: " << (!reason.empty() ? reason : "No reason");
- FOREACH_MOD(OnPrePartChannel, (u, c));
+
+ EventManager::Get()->Dispatch(&Event::PrePartChannel::OnPrePartChannel, u, c);
c->DeleteUser(u);
- FOREACH_MOD(OnPartChannel, (u, c, c->name, !reason.empty() ? reason : ""));
+ EventManager::Get()->Dispatch(&Event::PartChannel::OnPartChannel, u, c, c->name, reason);
}
}
@@ -312,7 +325,7 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &param
Channel *c = Channel::Find(receiver);
if (c)
{
- FOREACH_MOD(OnPrivmsg, (u, c, message));
+ EventManager::Get()->Dispatch(&Event::Privmsg::OnPrivmsg, u, c, message);
}
}
else
@@ -332,7 +345,7 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &param
}
else if (!IRCD->RequiresID && Config->UseStrictPrivmsg)
{
- BotInfo *bi = BotInfo::Find(receiver);
+ ServiceBot *bi = ServiceBot::Find(receiver);
if (!bi)
return;
Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << u->nick;
@@ -340,7 +353,7 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &param
return;
}
- BotInfo *bi = BotInfo::Find(botname, nick_only);
+ ServiceBot *bi = ServiceBot::Find(botname, nick_only);
if (bi)
{
@@ -361,11 +374,10 @@ void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &param
return;
}
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnBotPrivmsg, MOD_RESULT, (u, bi, message));
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::BotPrivmsg::OnBotPrivmsg, u, bi, message);
if (MOD_RESULT == EVENT_STOP)
return;
-
+
bi->OnMessage(u, message);
}
}
@@ -404,7 +416,7 @@ void SQuit::Run(MessageSource &source, const std::vector<Anope::string> &params)
s->Delete(s->GetName() + " " + s->GetUplink()->GetName());
}
-void Stats::Run(MessageSource &source, const std::vector<Anope::string> &params)
+void Message::Stats::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
User *u = source.GetUser();
@@ -426,14 +438,8 @@ void Stats::Run(MessageSource &source, const std::vector<Anope::string> &params)
IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
else
{
- for (unsigned i = 0; i < Oper::opers.size(); ++i)
- {
- Oper *o = Oper::opers[i];
-
- const NickAlias *na = NickAlias::Find(o->name);
- if (na)
- IRCD->SendNumeric(243, source.GetSource(), "O * * %s %s 0", o->name.c_str(), o->ot->GetName().replace_all_cs(" ", "_").c_str());
- }
+ for (Oper *o : Serialize::GetObjects<Oper *>())
+ IRCD->SendNumeric(243, source.GetSource(), "O * * %s %s 0", o->GetName().c_str(), o->GetType()->GetName().replace_all_cs(" ", "_").c_str());
IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
}
@@ -441,9 +447,11 @@ void Stats::Run(MessageSource &source, const std::vector<Anope::string> &params)
break;
case 'u':
{
+ ::Stats *s = Serialize::GetObject<::Stats *>();
long uptime = static_cast<long>(Anope::CurTime - Anope::StartTime);
+
IRCD->SendNumeric(242, source.GetSource(), ":Services up %d day%s, %02d:%02d:%02d", uptime / 86400, uptime / 86400 == 1 ? "" : "s", (uptime / 3600) % 24, (uptime / 60) % 60, uptime % 60);
- IRCD->SendNumeric(250, source.GetSource(), ":Current users: %d (%d ops); maximum %d", UserListByNick.size(), OperCount, MaxUserCount);
+ IRCD->SendNumeric(250, source.GetSource(), ":Current users: %d (%d ops); maximum %d", UserListByNick.size(), OperCount, s ? s->GetMaxUserCount() : 0);
IRCD->SendNumeric(219, source.GetSource(), "%c :End of /STATS report.", params[0][0]);
break;
} /* case 'u' */
@@ -487,11 +495,11 @@ void Whois::Run(MessageSource &source, const std::vector<Anope::string> &params)
if (u && u->server == Me)
{
- const BotInfo *bi = BotInfo::Find(u->GetUID());
+ const ServiceBot *bi = ServiceBot::Find(u->GetUID());
IRCD->SendNumeric(311, source.GetSource(), "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str());
if (bi)
IRCD->SendNumeric(307, source.GetSource(), "%s :is a registered nick", bi->nick.c_str());
- IRCD->SendNumeric(312, source.GetSource(), "%s %s :%s", u->nick.c_str(), Me->GetName().c_str(), Config->GetBlock("serverinfo")->Get<const Anope::string>("description").c_str());
+ IRCD->SendNumeric(312, source.GetSource(), "%s %s :%s", u->nick.c_str(), Me->GetName().c_str(), Config->GetBlock("serverinfo")->Get<Anope::string>("description").c_str());
if (bi)
IRCD->SendNumeric(317, source.GetSource(), "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(bi->signon));
IRCD->SendNumeric(318, source.GetSource(), "%s :End of /WHOIS list.", u->nick.c_str());
diff --git a/src/misc.cpp b/src/misc.cpp
index 0938a033c..3b044d9fa 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -1,12 +1,20 @@
-/* Miscellaneous routines.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -16,8 +24,8 @@
#include "config.h"
#include "bots.h"
#include "language.h"
-#include "regexpr.h"
#include "sockets.h"
+#include "event.h"
#include <errno.h>
#include <sys/types.h>
@@ -27,11 +35,13 @@
#include <netdb.h>
#endif
-NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(true), desc(descending)
+NumberList::NumberList(const Anope::string &list, bool descending, std::function<void(unsigned int)> nf, std::function<void(void)> ef) : endf(ef)
{
Anope::string error;
commasepstream sep(list);
Anope::string token;
+ bool is_valid = true;
+ std::set<unsigned> numbers;
sep.GetToken(token);
if (token.empty())
@@ -55,11 +65,8 @@ NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(tr
if (!error.empty())
{
- if (!this->InvalidRange(list))
- {
- is_valid = false;
- return;
- }
+ is_valid = false;
+ return;
}
}
else
@@ -80,47 +87,27 @@ NumberList::NumberList(const Anope::string &list, bool descending) : is_valid(tr
if (!error.empty() || !error2.empty())
{
- if (!this->InvalidRange(list))
- {
- is_valid = false;
- return;
- }
+ is_valid = false;
+ return;
}
}
} while (sep.GetToken(token));
-}
-
-NumberList::~NumberList()
-{
-}
-void NumberList::Process()
-{
if (!is_valid)
return;
- if (this->desc)
- {
- for (std::set<unsigned>::reverse_iterator it = numbers.rbegin(), it_end = numbers.rend(); it != it_end; ++it)
- this->HandleNumber(*it);
- }
+ if (descending)
+ std::for_each(numbers.rbegin(), numbers.rend(), nf);
else
- {
- for (std::set<unsigned>::iterator it = numbers.begin(), it_end = numbers.end(); it != it_end; ++it)
- this->HandleNumber(*it);
- }
+ std::for_each(numbers.begin(), numbers.end(), nf);
}
-void NumberList::HandleNumber(unsigned)
-{
-}
-
-bool NumberList::InvalidRange(const Anope::string &)
+NumberList::~NumberList()
{
- return true;
+ endf();
}
-ListFormatter::ListFormatter(NickCore *acc) : nc(acc)
+ListFormatter::ListFormatter(NickServ::Account *acc) : nc(acc)
{
}
@@ -160,14 +147,15 @@ void ListFormatter::Process(std::vector<Anope::string> &buffer)
unsigned length = 0;
for (std::map<Anope::string, size_t>::iterator it = lenghts.begin(), it_end = lenghts.end(); it != it_end; ++it)
{
- /* Break lines at 80 chars */
- if (length > 80)
+ if (length > Config->LineWrap)
{
breaks.insert(it->first);
length = 0;
}
else
+ {
length += it->second;
+ }
}
/* Only put a list header if more than 1 column */
@@ -214,7 +202,7 @@ void ListFormatter::Process(std::vector<Anope::string> &buffer)
}
}
-InfoFormatter::InfoFormatter(NickCore *acc) : nc(acc), longest(0)
+InfoFormatter::InfoFormatter(NickServ::Account *acc) : nc(acc), longest(0)
{
}
@@ -311,7 +299,7 @@ time_t Anope::DoTime(const Anope::string &s)
return amount;
}
-Anope::string Anope::Duration(time_t t, const NickCore *nc)
+Anope::string Anope::Duration(time_t t, NickServ::Account *nc)
{
/* We first calculate everything */
time_t years = t / 31536000;
@@ -352,7 +340,7 @@ Anope::string Anope::Duration(time_t t, const NickCore *nc)
}
}
-Anope::string Anope::strftime(time_t t, const NickCore *nc, bool short_output)
+Anope::string Anope::strftime(time_t t, NickServ::Account *nc, bool short_output)
{
tm tm = *localtime(&t);
char buf[BUFSIZE];
@@ -367,10 +355,10 @@ Anope::string Anope::strftime(time_t t, const NickCore *nc, bool short_output)
return Anope::string(buf) + " " + Language::Translate(nc, _("(now)"));
}
-Anope::string Anope::Expires(time_t expires, const NickCore *nc)
+Anope::string Anope::Expires(time_t expires, NickServ::Account *nc)
{
if (!expires)
- return Language::Translate(nc, NO_EXPIRE);
+ return Language::Translate(nc, _("does not expire"));
else if (expires <= Anope::CurTime)
return Language::Translate(nc, _("expires momentarily"));
else
@@ -407,38 +395,29 @@ bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case
{
size_t s = 0, m = 0, str_len = str.length(), mask_len = mask.length();
- if (use_regex && mask_len >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
+ if (use_regex && Config->regex_flags && mask_len >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/')
{
Anope::string stripped_mask = mask.substr(1, mask_len - 2);
// This is often called with the same mask multiple times in a row, so cache it
- static Regex *r = NULL;
+ static Anope::string pattern;
+ static std::regex r;
- if (r == NULL || r->GetExpression() != stripped_mask)
+ if (pattern != stripped_mask)
{
- ServiceReference<RegexProvider> provider("Regex", Config->GetBlock("options")->Get<const Anope::string>("regexengine"));
- if (provider)
+ try
{
- try
- {
- delete r;
- r = NULL;
- // This may throw
- r = provider->Compile(stripped_mask);
- }
- catch (const RegexException &ex)
- {
- Log(LOG_DEBUG) << ex.GetReason();
- }
+ r.assign(stripped_mask.str(), Config->regex_flags);
+ pattern = stripped_mask;
}
- else
+ catch (const std::regex_error &error)
{
- delete r;
- r = NULL;
+ Log(LOG_DEBUG) << error.what();
}
}
- if (r != NULL && r->Matches(str))
- return true;
+ if (pattern == stripped_mask)
+ if (std::regex_search(str.str(), r))
+ return true;
// Fall through to non regex match
}
@@ -509,29 +488,10 @@ bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case
void Anope::Encrypt(const Anope::string &src, Anope::string &dest)
{
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnEncrypt, MOD_RESULT, (src, dest));
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::Encrypt::OnEncrypt, src, dest);
static_cast<void>(MOD_RESULT);
}
-bool Anope::Decrypt(const Anope::string &src, Anope::string &dest)
-{
- size_t pos = src.find(':');
- if (pos == Anope::string::npos)
- {
- Log() << "Error: Anope::Decrypt() called with invalid password string (" << src << ")";
- return false;
- }
- Anope::string hashm(src.begin(), src.begin() + pos);
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnDecrypt, MOD_RESULT, (hashm, src, dest));
- if (MOD_RESULT == EVENT_ALLOW)
- return true;
-
- return false;
-}
-
Anope::string Anope::printf(const char *fmt, ...)
{
va_list args;
@@ -651,7 +611,7 @@ Anope::string Anope::VersionBuildString()
if (!flags.empty())
s += ", flags " + flags;
-
+
return s;
}
diff --git a/src/modes.cpp b/src/modes.cpp
index 229945b7d..b41bece1d 100644
--- a/src/modes.cpp
+++ b/src/modes.cpp
@@ -1,9 +1,21 @@
-/* Mode support
+/*
+ * Anope IRC Services
*
- * (C) 2008-2011 Adam <Adam@anope.org>
- * (C) 2008-2016 Anope Team <team@anope.org>
+ * Copyright (C) 2008-2011 Adam <Adam@anope.org>
+ * Copyright (C) 2008-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -13,6 +25,8 @@
#include "protocol.h"
#include "channels.h"
#include "uplink.h"
+#include "event.h"
+#include "modules/chanserv.h"
struct StackerInfo;
@@ -36,9 +50,6 @@ static std::map<Anope::string, UserMode *> UserModesByName;
/* Sorted by status */
static std::vector<ChannelModeStatus *> ChannelModesByStatus;
-/* Number of generic modes we support */
-unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0;
-
struct StackerInfo
{
/* Modes to be added */
@@ -46,7 +57,7 @@ struct StackerInfo
/* Modes to be deleted */
std::list<std::pair<Mode *, Anope::string> > DelModes;
/* Bot this is sent from */
- BotInfo *bi;
+ User *bi;
StackerInfo() : bi(NULL) { }
@@ -124,6 +135,12 @@ Mode::~Mode()
bool Mode::CanSet(User *u) const
{
+ if (!setable)
+ return false;
+
+ if (oper_only)
+ return u && u->HasMode("OPER");
+
return true;
}
@@ -142,8 +159,7 @@ ChannelMode::ChannelMode(const Anope::string &cm, char mch) : Mode(cm, MC_CHANNE
bool ChannelMode::CanSet(User *u) const
{
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnCanSet, MOD_RESULT, (u, this));
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::CanSet::OnCanSet, u, this);
return MOD_RESULT != EVENT_STOP;
}
@@ -186,6 +202,11 @@ ChannelModeParam::ChannelModeParam(const Anope::string &cm, char mch, bool ma) :
this->type = MODE_PARAM;
}
+bool ChannelModeParam::IsValid(Anope::string &value) const
+{
+ return std::regex_search(value.str(), param_validation);
+}
+
ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar, char msymbol, short mlevel) : ChannelMode(mname, modeChar), symbol(msymbol), level(mlevel)
{
this->type = MODE_STATUS;
@@ -231,34 +252,6 @@ ChannelMode *ChannelModeVirtual<T>::Wrap(Anope::string &param)
template class ChannelModeVirtual<ChannelMode>;
template class ChannelModeVirtual<ChannelModeList>;
-bool UserModeOperOnly::CanSet(User *u) const
-{
- return u && u->HasMode("OPER");
-}
-
-bool UserModeNoone::CanSet(User *u) const
-{
- return false;
-}
-
-bool ChannelModeKey::IsValid(Anope::string &value) const
-{
- if (!value.empty() && value.find(':') == Anope::string::npos && value.find(',') == Anope::string::npos)
- return true;
-
- return false;
-}
-
-bool ChannelModeOperOnly::CanSet(User *u) const
-{
- return u && u->HasMode("OPER");
-}
-
-bool ChannelModeNoone::CanSet(User *u) const
-{
- return false;
-}
-
void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string &param)
{
bool is_param = mode->type == MODE_PARAM;
@@ -313,7 +306,7 @@ void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string &param)
static class ModePipe : public Pipe
{
public:
- void OnNotify()
+ void OnNotify() override
{
ModeManager::ProcessModes();
}
@@ -395,15 +388,10 @@ bool ModeManager::AddUserMode(UserMode *um)
{
if (ModeManager::FindUserModeByChar(um->mchar) != NULL)
return false;
+
if (ModeManager::FindUserModeByName(um->name) != NULL)
return false;
- if (um->name.empty())
- {
- um->name = stringify(++GenericUserModes);
- Log() << "ModeManager: Added generic support for user mode " << um->mchar;
- }
-
unsigned want = um->mchar;
if (want >= UserModesIdx.size())
UserModesIdx.resize(want + 1);
@@ -413,7 +401,7 @@ bool ModeManager::AddUserMode(UserMode *um)
UserModes.push_back(um);
- FOREACH_MOD(OnUserModeAdd, (um));
+ EventManager::Get()->Dispatch(&Event::UserModeAdd::OnUserModeAdd, um);
return true;
}
@@ -425,12 +413,6 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
if (ModeManager::FindChannelModeByName(cm->name) != NULL)
return false;
- if (cm->name.empty())
- {
- cm->name = stringify(++GenericChannelModes);
- Log() << "ModeManager: Added generic support for channel mode " << cm->mchar;
- }
-
if (cm->mchar)
{
unsigned want = cm->mchar;
@@ -454,7 +436,7 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
ChannelModes.push_back(cm);
- FOREACH_MOD(OnChannelModeAdd, (cm));
+ EventManager::Get()->Dispatch(&Event::ChannelModeAdd::OnChannelModeAdd, cm);
for (unsigned int i = 0; i < ChannelModes.size(); ++i)
ChannelModes[i]->Check();
@@ -570,7 +552,7 @@ char ModeManager::GetStatusChar(char value)
ChannelMode *cm = ChannelModesIdx[want];
if (cm == NULL || cm->type != MODE_STATUS || cm->mchar == value)
return 0;
-
+
return cm->mchar;
}
@@ -610,7 +592,7 @@ void ModeManager::RebuildStatusModes()
std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp);
}
-void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const Anope::string &Param)
+void ModeManager::StackerAdd(User *bi, Channel *c, ChannelMode *cm, bool Set, const Anope::string &Param)
{
StackerInfo *s = GetInfo(ChannelStackerObjects, c);
s->AddMode(cm, Set, Param);
@@ -624,7 +606,7 @@ void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set,
modePipe->Notify();
}
-void ModeManager::StackerAdd(BotInfo *bi, User *u, UserMode *um, bool Set, const Anope::string &Param)
+void ModeManager::StackerAdd(User *bi, User *u, UserMode *um, bool Set, const Anope::string &Param)
{
StackerInfo *s = GetInfo(UserStackerObjects, u);
s->AddMode(um, Set, Param);
@@ -742,7 +724,59 @@ void ModeManager::StackerDel(Mode *m)
}
}
-Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0), family(0)
+void ModeManager::Apply(Configuration::Conf *old)
+{
+#warning "remove old modes"
+
+ for (Configuration::Channelmode &cm : Config->Channelmodes)
+ {
+ ChannelMode *mode;
+
+ if (cm.list)
+ Log(LOG_DEBUG) << "Creating channelmode list " << cm.name << " (" << cm.character << ")";
+ else if (cm.status)
+ Log(LOG_DEBUG) << "Creating channelmode status " << cm.name << " (" << cm.character << ")";
+ else if (cm.param)
+ Log(LOG_DEBUG) << "Creating channelmode param " << cm.name << " (" << cm.character << ")";
+ else
+ Log(LOG_DEBUG) << "Creating channelmode " << cm.name << " (" << cm.character << ")";
+
+ if (cm.list)
+ mode = new ChannelModeList(cm.name, cm.character);
+ else if (cm.status)
+ mode = new ChannelModeStatus(cm.name, cm.character, cm.status, cm.level);
+ else if (cm.param)
+ mode = new ChannelModeParam(cm.name, cm.character, !cm.param_unset);
+ else
+ mode = new ChannelMode(cm.name, cm.character);
+
+ mode->SetSetable(cm.setable);
+ mode->SetOperOnly(cm.oper_only);
+
+ if (!AddChannelMode(mode))
+ delete mode;
+ }
+
+ for (Configuration::Usermode &um : Config->Usermodes)
+ {
+ UserMode *mode;
+
+ Log(LOG_DEBUG) << "Creating usermode " << um.name << " (" << um.character << ")";
+
+ if (um.param)
+ mode = new UserModeParam(um.name, um.character);
+ else
+ mode = new UserMode(um.name, um.character);
+
+ mode->SetSetable(um.setable);
+ mode->SetOperOnly(um.oper_only);
+
+ if (!AddUserMode(mode))
+ delete mode;
+ }
+}
+
+Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0)
{
Anope::string n, u, h;
@@ -769,21 +803,21 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh
else
this->nick = fh;
}
-
+
at = this->host.find('#');
if (at != Anope::string::npos)
{
this->real = this->host.substr(at + 1);
this->host = this->host.substr(0, at);
}
-
+
/* If the mask is all *'s it will match anything, so just clear it */
if (this->nick.find_first_not_of("*") == Anope::string::npos)
this->nick.clear();
-
+
if (this->user.find_first_not_of("*") == Anope::string::npos)
this->user.clear();
-
+
if (this->host.find_first_not_of("*") == Anope::string::npos)
this->host.clear();
else
@@ -803,8 +837,6 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh
{
this->cidr_len = convertTo<unsigned short>(cidr_range);
- /* If we got here, cidr_len is a valid number. */
-
this->host = cidr_ip;
this->family = addr.family();
@@ -831,6 +863,7 @@ const Anope::string Entry::GetNUHMask() const
h = host.empty() ? "*" : host,
r = real.empty() ? "" : "#" + real,
c;
+
switch (family)
{
case AF_INET:
@@ -842,8 +875,7 @@ const Anope::string Entry::GetNUHMask() const
c = "/" + stringify(cidr_len);
break;
}
-
- return n + "!" + u + "@" + h + c + r;
+ return n + "!" + u + "@" + h + r + c;
}
bool Entry::Matches(User *u, bool full) const
@@ -888,10 +920,10 @@ bool Entry::Matches(User *u, bool full) const
else if (!this->host.empty() && !Anope::Match(u->GetDisplayedHost(), this->host) && !Anope::Match(u->GetCloakedHost(), this->host) &&
(!full || (!Anope::Match(u->host, this->host) && !Anope::Match(u->ip.addr(), this->host))))
ret = false;
-
+
if (!this->real.empty() && !Anope::Match(u->realname, this->real))
ret = false;
-
+
return ret;
}
diff --git a/src/module.cpp b/src/module.cpp
index 3e377efec..73ab9ad99 100644
--- a/src/module.cpp
+++ b/src/module.cpp
@@ -1,15 +1,25 @@
-/* Modular support
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "modules.h"
#include "language.h"
-#include "account.h"
#ifdef GETTEXT_FOUND
# include <libintl.h>
@@ -33,7 +43,7 @@ Module::Module(const Anope::string &modname, const Anope::string &, ModType modt
if (ModuleManager::FindModule(this->name))
throw CoreException("Module already exists!");
-
+
if (Anope::NoThird && type & THIRD)
throw ModuleException("Third party modules may not be loaded");
@@ -63,11 +73,6 @@ Module::Module(const Anope::string &modname, const Anope::string &, ModType modt
Module::~Module()
{
- UnsetExtensibles();
-
- /* Detach all event hooks for this module */
- ModuleManager::DetachAll(this);
- IdentifyRequest::ModuleUnload(this);
/* Clear any active timers this module has */
TimerManager::DeleteTimersFor(this);
@@ -102,10 +107,6 @@ void Module::SetAuthor(const Anope::string &nauthor)
this->author = nauthor;
}
-void Module::Prioritize()
-{
-}
-
ModuleVersion::ModuleVersion(const ModuleVersionC &ver)
{
version_major = ver.version_major;
diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp
index 2cda9e256..204421f34 100644
--- a/src/modulemanager.cpp
+++ b/src/modulemanager.cpp
@@ -1,16 +1,27 @@
-/* Modular support
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "modules.h"
#include "users.h"
-#include "regchannel.h"
#include "config.h"
+#include "event.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -21,7 +32,16 @@
#endif
std::list<Module *> ModuleManager::Modules;
-std::vector<Module *> ModuleManager::EventHandlers[I_SIZE];
+
+void ModuleDef::Depends(const Anope::string &modname)
+{
+ dependencies.push_back(modname);
+}
+
+const std::vector<Anope::string> &ModuleDef::GetDependencies()
+{
+ return dependencies;
+}
#ifdef _WIN32
void ModuleManager::CleanupRuntimeDirectory()
@@ -36,7 +56,7 @@ void ModuleManager::CleanupRuntimeDirectory()
Log(LOG_DEBUG) << "Cannot open directory (" << dirbuf << ")";
return;
}
-
+
for (dirent *dp; (dp = readdir(dirp));)
{
if (!dp->d_ino)
@@ -62,17 +82,17 @@ void ModuleManager::CleanupRuntimeDirectory()
static ModuleReturn moduleCopyFile(const Anope::string &name, Anope::string &output)
{
Anope::string input = Anope::ModuleDir + "/modules/" + name + ".so";
-
+
struct stat s;
if (stat(input.c_str(), &s) == -1)
return MOD_ERR_NOEXIST;
else if (!S_ISREG(s.st_mode))
return MOD_ERR_NOEXIST;
-
+
std::ifstream source(input.c_str(), std::ios_base::in | std::ios_base::binary);
if (!source.is_open())
return MOD_ERR_NOEXIST;
-
+
char *tmp_output = strdup(output.c_str());
int target_fd = mkstemp(tmp_output);
if (target_fd == -1 || close(target_fd) == -1)
@@ -85,7 +105,7 @@ static ModuleReturn moduleCopyFile(const Anope::string &name, Anope::string &out
free(tmp_output);
Log(LOG_DEBUG_2) << "Runtime module location: " << output;
-
+
std::ofstream target(output.c_str(), std::ios_base::in | std::ios_base::binary);
if (!target.is_open())
{
@@ -103,7 +123,7 @@ static ModuleReturn moduleCopyFile(const Anope::string &name, Anope::string &out
target.write(buffer, read_len);
want -= read_len;
}
-
+
source.close();
target.close();
@@ -111,22 +131,6 @@ static ModuleReturn moduleCopyFile(const Anope::string &name, Anope::string &out
}
#endif
-/* This code was found online at http://www.linuxjournal.com/article/3687#comment-26593
- *
- * This function will take a pointer from either dlsym or GetProcAddress and cast it in
- * a way that won't cause C++ warnings/errors to come up.
- */
-template <class TYPE> static TYPE function_cast(void *symbol)
-{
- union
- {
- void *symbol;
- TYPE function;
- } cast;
- cast.symbol = symbol;
- return cast.function;
-}
-
ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
{
if (modname.empty())
@@ -139,7 +143,7 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
#ifdef _WIN32
/* Generate the filename for the temporary copy of the module */
- Anope::string pbuf = Anope::DataDir + "/runtime/" + modname + ".so.XXXXXX";
+ Anope::string pbuf = Anope::DataDir + "/runtime/" + modname.replace_all_cs("/", "_") + ".so.XXXXXX";
/* Don't skip return value checking! -GD */
ModuleReturn ret = moduleCopyFile(modname, pbuf);
@@ -152,7 +156,7 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
return ret;
}
#else
- Anope::string pbuf = Anope::ModuleDir + "/modules/" + modname + ".so";
+ Anope::string pbuf = Anope::ModuleDir + "/modules/" + modname.replace_all_cs("/", "_") + ".so";
#endif
dlerror();
@@ -165,9 +169,21 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
return MOD_ERR_NOLOAD;
}
+ dlerror();
+ AnopeModule *module = static_cast<AnopeModule *>(dlsym(handle, "AnopeMod"));
+ err = dlerror();
+ if (!module || module->api_version != ANOPE_MODAPI_VER)
+ {
+ Log() << "No module symbols function found, not an Anope module";
+ if (err && *err)
+ Log(LOG_DEBUG) << err;
+ dlclose(handle);
+ return MOD_ERR_NOLOAD;
+ }
+
try
{
- ModuleVersion v = GetVersion(handle);
+ ModuleVersion v = module->version();
if (v.GetMajor() < Anope::VersionMajor() || (v.GetMajor() == Anope::VersionMajor() && v.GetMinor() < Anope::VersionMinor()))
{
@@ -205,17 +221,7 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
return MOD_ERR_NOLOAD;
}
- dlerror();
- Module *(*func)(const Anope::string &, const Anope::string &) = function_cast<Module *(*)(const Anope::string &, const Anope::string &)>(dlsym(handle, "AnopeInit"));
- err = dlerror();
- if (!func)
- {
- Log() << "No init function found, not an Anope module";
- if (err && *err)
- Log(LOG_DEBUG) << err;
- dlclose(handle);
- return MOD_ERR_NOLOAD;
- }
+ ModuleDef *def = module->init();
/* Create module. */
Anope::string nick;
@@ -227,7 +233,7 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
ModuleReturn moderr = MOD_ERR_OK;
try
{
- m = func(modname, nick);
+ m = def->Create(modname, nick);
}
catch (const ModuleException &ex)
{
@@ -244,6 +250,8 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
m->filename = pbuf;
m->handle = handle;
+ m->def = def;
+ m->module = module;
/* Initialize config */
try
@@ -260,9 +268,6 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
Log() << "Module " << modname << " couldn't load due to configuration problems: " << ex.GetReason();
moderr = MOD_ERR_EXCEPTION;
}
- catch (const NotImplementedException &ex)
- {
- }
if (moderr != MOD_ERR_OK)
{
@@ -272,41 +277,17 @@ ModuleReturn ModuleManager::LoadModule(const Anope::string &modname, User *u)
Log(LOG_DEBUG) << "Module " << modname << " loaded.";
- /* Attach module to all events */
- for (unsigned i = 0; i < I_SIZE; ++i)
- EventHandlers[i].push_back(m);
-
- m->Prioritize();
-
- FOREACH_MOD(OnModuleLoad, (u, m));
+ EventManager::Get()->Dispatch(&Event::ModuleLoad::OnModuleLoad, u, m);
return MOD_ERR_OK;
}
-ModuleVersion ModuleManager::GetVersion(void *handle)
-{
- dlerror();
- ModuleVersionC (*func)() = function_cast<ModuleVersionC (*)()>(dlsym(handle, "AnopeVersion"));;
- if (!func)
- {
- Log() << "No version function found, not an Anope module";
-
- const char *err = dlerror();
- if (err && *err)
- Log(LOG_DEBUG) << err;
-
- throw ModuleException("No version");
- }
-
- return func();
-}
-
ModuleReturn ModuleManager::UnloadModule(Module *m, User *u)
{
if (!m)
return MOD_ERR_PARAMS;
- FOREACH_MOD(OnModuleUnload, (u, m));
+ EventManager::Get()->Dispatch(&Event::ModuleUnload::OnModuleUnload, u, m);
return DeleteModule(m);
}
@@ -366,22 +347,20 @@ ModuleReturn ModuleManager::DeleteModule(Module *m)
if (!m || !m->handle)
return MOD_ERR_PARAMS;
+ Serialize::Unregister(m);
+
void *handle = m->handle;
Anope::string filename = m->filename;
Log(LOG_DEBUG) << "Unloading module " << m->name;
- dlerror();
- void (*destroy_func)(Module *m) = function_cast<void (*)(Module *)>(dlsym(m->handle, "AnopeFini"));
- const char *err = dlerror();
- if (!destroy_func || (err && *err))
- {
- Log() << "No destroy function found for " << m->name << ", chancing delete...";
- delete m; /* we just have to chance they haven't overwrote the delete operator then... */
- }
- else
- destroy_func(m); /* Let the module delete it self, just in case */
+ ModuleDef *def = m->def;
+ AnopeModule *module = m->module;
+ def->Destroy(m);
+ module->fini(def);
+
+ dlerror();
if (dlclose(handle))
Log() << dlerror();
@@ -389,121 +368,8 @@ ModuleReturn ModuleManager::DeleteModule(Module *m)
if (!filename.empty())
unlink(filename.c_str());
#endif
-
- return MOD_ERR_OK;
-}
-
-void ModuleManager::DetachAll(Module *mod)
-{
- for (unsigned i = 0; i < I_SIZE; ++i)
- {
- std::vector<Module *> &mods = EventHandlers[i];
- std::vector<Module *>::iterator it2 = std::find(mods.begin(), mods.end(), mod);
- if (it2 != mods.end())
- mods.erase(it2);
- }
-}
-
-bool ModuleManager::SetPriority(Module *mod, Priority s)
-{
- for (unsigned i = 0; i < I_SIZE; ++i)
- SetPriority(mod, static_cast<Implementation>(i), s);
-
- return true;
-}
-
-bool ModuleManager::SetPriority(Module *mod, Implementation i, Priority s, Module **modules, size_t sz)
-{
- /** To change the priority of a module, we first find its position in the vector,
- * then we find the position of the other modules in the vector that this module
- * wants to be before/after. We pick off either the first or last of these depending
- * on which they want, and we make sure our module is *at least* before or after
- * the first or last of this subset, depending again on the type of priority.
- */
-
- /* Locate our module. This is O(n) but it only occurs on module load so we're
- * not too bothered about it
- */
- size_t source = 0;
- bool found = false;
- for (size_t x = 0, end = EventHandlers[i].size(); x != end; ++x)
- if (EventHandlers[i][x] == mod)
- {
- source = x;
- found = true;
- break;
- }
-
- /* Eh? this module doesn't exist, probably trying to set priority on an event
- * they're not attached to.
- */
- if (!found)
- return false;
-
- size_t swap_pos = 0;
- bool swap = true;
- switch (s)
- {
- /* Dummy value */
- case PRIORITY_DONTCARE:
- swap = false;
- break;
- /* Module wants to be first, sod everything else */
- case PRIORITY_FIRST:
- swap_pos = 0;
- break;
- /* Module is submissive and wants to be last... awww. */
- case PRIORITY_LAST:
- if (EventHandlers[i].empty())
- swap_pos = 0;
- else
- swap_pos = EventHandlers[i].size() - 1;
- break;
- /* Place this module after a set of other modules */
- case PRIORITY_AFTER:
- /* Find the latest possible position */
- swap_pos = 0;
- swap = false;
- for (size_t x = 0, end = EventHandlers[i].size(); x != end; ++x)
- for (size_t n = 0; n < sz; ++n)
- if (modules[n] && EventHandlers[i][x] == modules[n] && x >= swap_pos && source <= swap_pos)
- {
- swap_pos = x;
- swap = true;
- }
- break;
- /* Place this module before a set of other modules */
- case PRIORITY_BEFORE:
- swap_pos = EventHandlers[i].size() - 1;
- swap = false;
- for (size_t x = 0, end = EventHandlers[i].size(); x != end; ++x)
- for (size_t n = 0; n < sz; ++n)
- if (modules[n] && EventHandlers[i][x] == modules[n] && x <= swap_pos && source >= swap_pos)
- {
- swap = true;
- swap_pos = x;
- }
- }
-
- /* Do we need to swap? */
- if (swap && swap_pos != source)
- {
- /* Suggestion from Phoenix, "shuffle" the modules to better retain call order */
- int incrmnt = 1;
-
- if (source > swap_pos)
- incrmnt = -1;
-
- for (unsigned j = source; j != swap_pos; j += incrmnt)
- {
- if (j + incrmnt > EventHandlers[i].size() - 1 || (!j && incrmnt == -1))
- continue;
- std::swap(EventHandlers[i][j], EventHandlers[i][j + incrmnt]);
- }
- }
-
- return true;
+ return MOD_ERR_OK;
}
void ModuleManager::UnloadAll()
@@ -516,7 +382,7 @@ void ModuleManager::UnloadAll()
if ((m->type & j) == m->type)
modules.push_back(m->name);
}
-
+
for (unsigned i = 0; i < modules.size(); ++i)
{
Module *m = FindModule(modules[i]);
diff --git a/src/nickalias.cpp b/src/nickalias.cpp
deleted file mode 100644
index 795298cba..000000000
--- a/src/nickalias.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "services.h"
-#include "account.h"
-#include "modules.h"
-#include "opertype.h"
-#include "protocol.h"
-#include "users.h"
-#include "servers.h"
-#include "config.h"
-
-Serialize::Checker<nickalias_map> NickAliasList("NickAlias");
-
-NickAlias::NickAlias(const Anope::string &nickname, NickCore* nickcore) : Serializable("NickAlias")
-{
- if (nickname.empty())
- throw CoreException("Empty nick passed to NickAlias constructor");
- else if (!nickcore)
- throw CoreException("Empty nickcore passed to NickAlias constructor");
-
- this->time_registered = this->last_seen = Anope::CurTime;
- this->nick = nickname;
- this->nc = nickcore;
- nickcore->aliases->push_back(this);
-
- size_t old = NickAliasList->size();
- (*NickAliasList)[this->nick] = this;
- if (old == NickAliasList->size())
- Log(LOG_DEBUG) << "Duplicate nick " << nickname << " in nickalias table";
-
- if (this->nc->o == NULL)
- {
- Oper *o = Oper::Find(this->nick);
- if (o == NULL)
- o = Oper::Find(this->nc->display);
- nickcore->o = o;
- if (this->nc->o != NULL)
- Log() << "Tied oper " << this->nc->display << " to type " << this->nc->o->ot->GetName();
- }
-}
-
-NickAlias::~NickAlias()
-{
- UnsetExtensibles();
-
- FOREACH_MOD(OnDelNick, (this));
-
- /* Accept nicks that have no core, because of database load functions */
- if (this->nc)
- {
- /* Next: see if our core is still useful. */
- std::vector<NickAlias *>::iterator it = std::find(this->nc->aliases->begin(), this->nc->aliases->end(), this);
- if (it != this->nc->aliases->end())
- this->nc->aliases->erase(it);
- if (this->nc->aliases->empty())
- {
- delete this->nc;
- this->nc = NULL;
- }
- else
- {
- /* Display updating stuff */
- if (this->nick.equals_ci(this->nc->display))
- this->nc->SetDisplay(this->nc->aliases->front());
- }
- }
-
- /* Remove us from the aliases list */
- NickAliasList->erase(this->nick);
-}
-
-void NickAlias::SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created)
-{
- this->vhost_ident = ident;
- this->vhost_host = host;
- this->vhost_creator = creator;
- this->vhost_created = created;
-}
-
-void NickAlias::RemoveVhost()
-{
- this->vhost_ident.clear();
- this->vhost_host.clear();
- this->vhost_creator.clear();
- this->vhost_created = 0;
-}
-
-bool NickAlias::HasVhost() const
-{
- return !this->vhost_host.empty();
-}
-
-const Anope::string &NickAlias::GetVhostIdent() const
-{
- return this->vhost_ident;
-}
-
-const Anope::string &NickAlias::GetVhostHost() const
-{
- return this->vhost_host;
-}
-
-const Anope::string &NickAlias::GetVhostCreator() const
-{
- return this->vhost_creator;
-}
-
-time_t NickAlias::GetVhostCreated() const
-{
- return this->vhost_created;
-}
-
-NickAlias *NickAlias::Find(const Anope::string &nick)
-{
- nickalias_map::const_iterator it = NickAliasList->find(nick);
- if (it != NickAliasList->end())
- {
- it->second->QueueUpdate();
- return it->second;
- }
-
- return NULL;
-}
-
-void NickAlias::Serialize(Serialize::Data &data) const
-{
- data["nick"] << this->nick;
- data["last_quit"] << this->last_quit;
- data["last_realname"] << this->last_realname;
- data["last_usermask"] << this->last_usermask;
- data["last_realhost"] << this->last_realhost;
- data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
- data.SetType("last_seen", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
- data["nc"] << this->nc->display;
-
- if (this->HasVhost())
- {
- data["vhost_ident"] << this->GetVhostIdent();
- data["vhost_host"] << this->GetVhostHost();
- data["vhost_creator"] << this->GetVhostCreator();
- data["vhost_time"] << this->GetVhostCreated();
- }
-
- Extensible::ExtensibleSerialize(this, this, data);
-}
-
-Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string snc, snick;
-
- data["nc"] >> snc;
- data["nick"] >> snick;
-
- NickCore *core = NickCore::Find(snc);
- if (core == NULL)
- return NULL;
-
- NickAlias *na;
- if (obj)
- na = anope_dynamic_static_cast<NickAlias *>(obj);
- else
- na = new NickAlias(snick, core);
-
- if (na->nc != core)
- {
- std::vector<NickAlias *>::iterator it = std::find(na->nc->aliases->begin(), na->nc->aliases->end(), na);
- if (it != na->nc->aliases->end())
- na->nc->aliases->erase(it);
-
- if (na->nc->aliases->empty())
- delete na->nc;
- else if (na->nick.equals_ci(na->nc->display))
- na->nc->SetDisplay(na->nc->aliases->front());
-
- na->nc = core;
- core->aliases->push_back(na);
- }
-
- data["last_quit"] >> na->last_quit;
- data["last_realname"] >> na->last_realname;
- data["last_usermask"] >> na->last_usermask;
- data["last_realhost"] >> na->last_realhost;
- data["time_registered"] >> na->time_registered;
- data["last_seen"] >> na->last_seen;
-
- Anope::string vhost_ident, vhost_host, vhost_creator;
- time_t vhost_time;
-
- data["vhost_ident"] >> vhost_ident;
- data["vhost_host"] >> vhost_host;
- data["vhost_creator"] >> vhost_creator;
- data["vhost_time"] >> vhost_time;
-
- na->SetVhost(vhost_ident, vhost_host, vhost_creator, vhost_time);
-
- Extensible::ExtensibleUnserialize(na, na, data);
-
- /* compat */
- bool b;
- b = false;
- data["extensible:NO_EXPIRE"] >> b;
- if (b)
- na->Extend<bool>("NS_NO_EXPIRE");
- /* end compat */
-
- return na;
-}
-
diff --git a/src/nickcore.cpp b/src/nickcore.cpp
deleted file mode 100644
index 633f5a7cb..000000000
--- a/src/nickcore.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "services.h"
-#include "modules.h"
-#include "account.h"
-#include "config.h"
-
-Serialize::Checker<nickcore_map> NickCoreList("NickCore");
-
-NickCore::NickCore(const Anope::string &coredisplay) : Serializable("NickCore"), chanaccess("ChannelInfo"), aliases("NickAlias")
-{
- if (coredisplay.empty())
- throw CoreException("Empty display passed to NickCore constructor");
-
- this->o = NULL;
- this->channelcount = 0;
- this->lastmail = 0;
-
- this->display = coredisplay;
-
- size_t old = NickCoreList->size();
- (*NickCoreList)[this->display] = this;
- if (old == NickCoreList->size())
- Log(LOG_DEBUG) << "Duplicate account " << coredisplay << " in nickcore table?";
-
- FOREACH_MOD(OnNickCoreCreate, (this));
-}
-
-NickCore::~NickCore()
-{
- UnsetExtensibles();
-
- FOREACH_MOD(OnDelCore, (this));
-
- if (!this->chanaccess->empty())
- Log(LOG_DEBUG) << "Non-empty chanaccess list in destructor!";
-
- for (std::list<User *>::iterator it = this->users.begin(); it != this->users.end();)
- {
- User *user = *it++;
- user->Logout();
- }
- this->users.clear();
-
- NickCoreList->erase(this->display);
-
- this->ClearAccess();
-
- if (!this->memos.memos->empty())
- {
- for (unsigned i = 0, end = this->memos.memos->size(); i < end; ++i)
- delete this->memos.GetMemo(i);
- this->memos.memos->clear();
- }
-}
-
-void NickCore::Serialize(Serialize::Data &data) const
-{
- data["display"] << this->display;
- data["pass"] << this->pass;
- data["email"] << this->email;
- data["language"] << this->language;
- for (unsigned i = 0; i < this->access.size(); ++i)
- data["access"] << this->access[i] << " ";
- data["memomax"] << this->memos.memomax;
- for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
- data["memoignores"] << this->memos.ignores[i] << " ";
- Extensible::ExtensibleSerialize(this, this, data);
-}
-
-Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- NickCore *nc;
-
- Anope::string sdisplay;
-
- data["display"] >> sdisplay;
-
- if (obj)
- nc = anope_dynamic_static_cast<NickCore *>(obj);
- else
- nc = new NickCore(sdisplay);
-
- data["pass"] >> nc->pass;
- data["email"] >> nc->email;
- data["language"] >> nc->language;
- {
- Anope::string buf;
- data["access"] >> buf;
- spacesepstream sep(buf);
- nc->access.clear();
- while (sep.GetToken(buf))
- nc->access.push_back(buf);
- }
- data["memomax"] >> nc->memos.memomax;
- {
- Anope::string buf;
- data["memoignores"] >> buf;
- spacesepstream sep(buf);
- nc->memos.ignores.clear();
- while (sep.GetToken(buf))
- nc->memos.ignores.push_back(buf);
- }
-
- Extensible::ExtensibleUnserialize(nc, nc, data);
-
- /* compat */
- bool b;
- b = false;
- data["extensible:SECURE"] >> b;
- if (b)
- nc->Extend<bool>("NS_SECURE");
- b = false;
- data["extensible:PRIVATE"] >> b;
- if (b)
- nc->Extend<bool>("NS_PRIVATE");
- b = false;
- data["extensible:AUTOOP"] >> b;
- if (b)
- nc->Extend<bool>("AUTOOP");
- b = false;
- data["extensible:HIDE_EMAIL"] >> b;
- if (b)
- nc->Extend<bool>("HIDE_EMAIL");
- b = false;
- data["extensible:HIDE_QUIT"] >> b;
- if (b)
- nc->Extend<bool>("HIDE_QUIT");
- b = false;
- data["extensible:MEMO_RECEIVE"] >> b;
- if (b)
- nc->Extend<bool>("MEMO_RECEIVE");
- b = false;
- data["extensible:MEMO_SIGNON"] >> b;
- if (b)
- nc->Extend<bool>("MEMO_SIGNON");
- b = false;
- data["extensible:KILLPROTECT"] >> b;
- if (b)
- nc->Extend<bool>("KILLPROTECT");
- /* end compat */
-
- return nc;
-}
-
-void NickCore::SetDisplay(const NickAlias *na)
-{
- if (na->nc != this || na->nick == this->display)
- return;
-
- FOREACH_MOD(OnChangeCoreDisplay, (this, na->nick));
-
- /* this affects the serialized aliases */
- for (unsigned i = 0; i < aliases->size(); ++i)
- aliases->at(i)->QueueUpdate();
-
- /* Remove the core from the list */
- NickCoreList->erase(this->display);
-
- this->display = na->nick;
-
- (*NickCoreList)[this->display] = this;
-}
-
-bool NickCore::IsServicesOper() const
-{
- return this->o != NULL;
-}
-
-void NickCore::AddAccess(const Anope::string &entry)
-{
- this->access.push_back(entry);
- FOREACH_MOD(OnNickAddAccess, (this, entry));
-}
-
-Anope::string NickCore::GetAccess(unsigned entry) const
-{
- if (this->access.empty() || entry >= this->access.size())
- return "";
- return this->access[entry];
-}
-
-unsigned NickCore::GetAccessCount() const
-{
- return this->access.size();
-}
-
-bool NickCore::FindAccess(const Anope::string &entry)
-{
- for (unsigned i = 0, end = this->access.size(); i < end; ++i)
- if (this->access[i] == entry)
- return true;
-
- return false;
-}
-
-void NickCore::EraseAccess(const Anope::string &entry)
-{
- for (unsigned i = 0, end = this->access.size(); i < end; ++i)
- if (this->access[i] == entry)
- {
- FOREACH_MOD(OnNickEraseAccess, (this, entry));
- this->access.erase(this->access.begin() + i);
- break;
- }
-}
-
-void NickCore::ClearAccess()
-{
- FOREACH_MOD(OnNickClearAccess, (this));
- this->access.clear();
-}
-
-bool NickCore::IsOnAccess(const User *u) const
-{
- Anope::string buf = u->GetIdent() + "@" + u->host, buf2, buf3;
- if (!u->vhost.empty())
- buf2 = u->GetIdent() + "@" + u->vhost;
- if (!u->GetCloakedHost().empty())
- buf3 = u->GetIdent() + "@" + u->GetCloakedHost();
-
- for (unsigned i = 0, end = this->access.size(); i < end; ++i)
- {
- Anope::string a = this->GetAccess(i);
- if (Anope::Match(buf, a) || (!buf2.empty() && Anope::Match(buf2, a)) || (!buf3.empty() && Anope::Match(buf3, a)))
- return true;
- }
- return false;
-}
-
-void NickCore::AddChannelReference(ChannelInfo *ci)
-{
- ++(*this->chanaccess)[ci];
-}
-
-void NickCore::RemoveChannelReference(ChannelInfo *ci)
-{
- int& i = (*this->chanaccess)[ci];
- if (--i <= 0)
- this->chanaccess->erase(ci);
-}
-
-void NickCore::GetChannelReferences(std::deque<ChannelInfo *> &queue)
-{
- queue.clear();
- for (std::map<ChannelInfo *, int>::iterator it = this->chanaccess->begin(), it_end = this->chanaccess->end(); it != it_end; ++it)
- queue.push_back(it->first);
-}
-
-NickCore* NickCore::Find(const Anope::string &nick)
-{
- nickcore_map::const_iterator it = NickCoreList->find(nick);
- if (it != NickCoreList->end())
- {
- it->second->QueueUpdate();
- return it->second;
- }
-
- return NULL;
-}
-
diff --git a/src/opertype.cpp b/src/opertype.cpp
index 9438c2ff5..91676bd84 100644
--- a/src/opertype.cpp
+++ b/src/opertype.cpp
@@ -1,9 +1,21 @@
/*
+ * Anope IRC Services
*
- * (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
- * (C) 2008-2016 Anope Team <team@anope.org>
+ * Copyright (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
+ * Copyright (C) 2009-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -11,31 +23,83 @@
#include "opertype.h"
#include "config.h"
-std::vector<Oper *> Oper::opers;
+Anope::string Oper::GetName()
+{
+ return Get(&OperBlockType::name);
+}
-Oper::Oper(const Anope::string &n, OperType *o) : name(n), ot(o), require_oper(false)
+void Oper::SetName(const Anope::string &n)
{
- opers.push_back(this);
+ Set(&OperBlockType::name, n);
}
-Oper::~Oper()
+Anope::string Oper::GetPassword()
{
- std::vector<Oper *>::iterator it = std::find(opers.begin(), opers.end(), this);
- if (it != opers.end())
- opers.erase(it);
+ return Get(&OperBlockType::password);
}
-Oper *Oper::Find(const Anope::string &name)
+void Oper::SetPassword(const Anope::string &s)
{
- for (unsigned i = 0; i < opers.size(); ++i)
- {
- Oper *o = opers[i];
+ Set(&OperBlockType::password, s);
+}
- if (o->name.equals_ci(name))
+Anope::string Oper::GetCertFP()
+{
+ return Get(&OperBlockType::certfp);
+}
+
+void Oper::SetCertFP(const Anope::string &s)
+{
+ Set(&OperBlockType::certfp, s);
+}
+
+Anope::string Oper::GetHost()
+{
+ return Get(&OperBlockType::host);
+}
+
+void Oper::SetHost(const Anope::string &h)
+{
+ Set(&OperBlockType::host, h);
+}
+
+Anope::string Oper::GetVhost()
+{
+ return Get(&OperBlockType::vhost);
+}
+
+void Oper::SetVhost(const Anope::string &s)
+{
+ Set(&OperBlockType::vhost, s);
+}
+
+OperType *Oper::GetType()
+{
+ return OperType::Find(Get(&OperBlockType::type));
+}
+
+void Oper::SetType(OperType *t)
+{
+ Set(&OperBlockType::type, t->GetName());
+}
+
+bool Oper::GetRequireOper()
+{
+ return Get(&OperBlockType::require_oper);
+}
+
+void Oper::SetRequireOper(const bool &b)
+{
+ Set(&OperBlockType::require_oper, b);
+}
+
+Oper *Oper::Find(const Anope::string &name)
+{
+ for (Oper *o : Serialize::GetObjects<Oper *>())
+ if (o->GetName() == name)
return o;
- }
- return NULL;
+ return nullptr;
}
OperType *OperType::Find(const Anope::string &name)
diff --git a/src/pipeengine.cpp b/src/pipeengine.cpp
index 0953387c1..1a133641f 100644
--- a/src/pipeengine.cpp
+++ b/src/pipeengine.cpp
@@ -1,12 +1,20 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2010-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -48,10 +56,11 @@ Pipe::~Pipe()
bool Pipe::ProcessRead()
{
+ char dummy[512];
+ while (read(this->GetFD(), dummy, sizeof(dummy)) == sizeof(dummy));
+
this->OnNotify();
- char dummy[512];
- while (read(this->GetFD(), dummy, 512) == 512);
return true;
}
@@ -76,6 +85,6 @@ bool Pipe::SetWriteBlocking(bool state)
void Pipe::Notify()
{
- this->Write("\0", 1);
+ this->Write("", 1);
}
diff --git a/src/process.cpp b/src/process.cpp
index b095ab40b..356a3b695 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -1,12 +1,20 @@
-/* Main processing code for Services.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -14,7 +22,7 @@
#include "protocol.h"
#include "servers.h"
#include "users.h"
-#include "regchannel.h"
+#include "event.h"
void Anope::Process(const Anope::string &buffer)
{
@@ -50,13 +58,10 @@ void Anope::Process(const Anope::string &buffer)
static const Anope::string proto_name = ModuleManager::FindFirstOf(PROTOCOL) ? ModuleManager::FindFirstOf(PROTOCOL)->name : "";
MessageSource src(source);
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnMessage, MOD_RESULT, (src, command, params));
- if (MOD_RESULT == EVENT_STOP)
- return;
- ServiceReference<IRCDMessage> m("IRCDMessage", proto_name + "/" + command.lower());
+ EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::Message::OnMessage, src, command, params);
+
+ ServiceReference<IRCDMessage> m(proto_name + "/" + command.lower());
if (!m)
{
Log(LOG_DEBUG) << "unknown message from server (" << buffer << ")";
@@ -100,11 +105,26 @@ void IRCDProto::Parse(const Anope::string &buffer, Anope::string &source, Anope:
}
}
-Anope::string IRCDProto::Format(const Anope::string &source, const Anope::string &message)
+Anope::string IRCDProto::Format(IRCMessage &message)
{
+ std::stringstream buffer;
+
+ const Anope::string &source = message.GetSource().GetUID();
if (!source.empty())
- return ":" + source + " " + message;
- else
- return message;
+ buffer << ":" << source << " ";
+
+ buffer << message.GetCommand();
+
+ for (unsigned int i = 0; i < message.GetParameters().size(); ++i)
+ {
+ buffer << " ";
+
+ if (i + 1 == message.GetParameters().size())
+ buffer << ":";
+
+ buffer << message.GetParameters()[i];
+ }
+
+ return buffer.str();
}
diff --git a/src/protocol.cpp b/src/protocol.cpp
index c8320e25a..c5b555cad 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -1,12 +1,20 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -80,7 +88,7 @@ Anope::string IRCDProto::SID_Retrieve()
if (!IRCD || !IRCD->RequiresID)
return "";
- static Anope::string current_sid = Config->GetBlock("serverinfo")->Get<const Anope::string>("id");
+ static Anope::string current_sid = Config->GetBlock("serverinfo")->Get<Anope::string>("id");
if (current_sid.empty())
current_sid = "00A";
@@ -96,61 +104,65 @@ Anope::string IRCDProto::SID_Retrieve()
void IRCDProto::SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason)
{
- UplinkSocket::Message(source) << "KILL " << target << " :" << reason;
+ Uplink::Send(source, "KILL", target, reason);
}
void IRCDProto::SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf)
{
- UplinkSocket::Message(source) << "KILL " << user->GetUID() << " :" << buf;
+ Uplink::Send(source, "KILL", user->GetUID(), buf);
}
void IRCDProto::SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf)
{
- UplinkSocket::Message(source) << "MODE " << dest->name << " " << buf;
+ IRCMessage message(source, "MODE", dest->name);
+ message.TokenizeAndPush(buf);
+ Uplink::SendMessage(message);
}
void IRCDProto::SendModeInternal(const MessageSource &source, User *dest, const Anope::string &buf)
{
- UplinkSocket::Message(source) << "MODE " << dest->GetUID() << " " << buf;
+ IRCMessage message(source, "MODE", dest->GetUID());
+ message.TokenizeAndPush(buf);
+ Uplink::SendMessage(message);
}
void IRCDProto::SendKickInternal(const MessageSource &source, const Channel *c, User *u, const Anope::string &r)
{
if (!r.empty())
- UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID() << " :" << r;
+ Uplink::Send(source, "KICK", c->name, u->GetUID(), r);
else
- UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID();
+ Uplink::Send(source, "KICK", c->name, u->GetUID());
}
void IRCDProto::SendNoticeInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &msg)
{
- UplinkSocket::Message(source) << "NOTICE " << dest << " :" << msg;
+ Uplink::Send(source, "NOTICE", dest, msg);
}
void IRCDProto::SendPrivmsgInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf)
{
- UplinkSocket::Message(source) << "PRIVMSG " << dest << " :" << buf;
+ Uplink::Send(source, "PRIVMSG", dest, buf);
}
void IRCDProto::SendQuitInternal(User *u, const Anope::string &buf)
{
if (!buf.empty())
- UplinkSocket::Message(u) << "QUIT :" << buf;
+ Uplink::Send(u, "QUIT", buf);
else
- UplinkSocket::Message(u) << "QUIT";
+ Uplink::Send(u, "QUIT");
}
void IRCDProto::SendPartInternal(User *u, const Channel *chan, const Anope::string &buf)
{
if (!buf.empty())
- UplinkSocket::Message(u) << "PART " << chan->name << " :" << buf;
+ Uplink::Send(u, "PART", chan->name, buf);
else
- UplinkSocket::Message(u) << "PART " << chan->name;
+ Uplink::Send(u, "PART", chan->name);
}
void IRCDProto::SendGlobopsInternal(const MessageSource &source, const Anope::string &buf)
{
- UplinkSocket::Message(source) << "GLOBOPS :" << buf;
+ Uplink::Send(source, "GLOBOPS", buf);
}
void IRCDProto::SendCTCPInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf)
@@ -166,12 +178,15 @@ void IRCDProto::SendNumericInternal(int numeric, const Anope::string &dest, cons
n = "0" + n;
if (numeric < 100)
n = "0" + n;
- UplinkSocket::Message(Me) << n << " " << dest << " " << buf;
+
+ IRCMessage message(Me, n, dest);
+ message.TokenizeAndPush(buf);
+ Uplink::SendMessage(message);
}
void IRCDProto::SendTopic(const MessageSource &source, Channel *c)
{
- UplinkSocket::Message(source) << "TOPIC " << c->name << " :" << c->topic;
+ Uplink::Send(source, "TOPIC", c->name, c->topic);
}
void IRCDProto::SendSVSKill(const MessageSource &source, User *user, const char *fmt, ...)
@@ -264,28 +279,22 @@ void IRCDProto::SendQuit(User *u, const char *fmt, ...)
void IRCDProto::SendPing(const Anope::string &servname, const Anope::string &who)
{
if (servname.empty())
- UplinkSocket::Message(Me) << "PING " << who;
+ Uplink::Send(Me, "PING", who);
else
- UplinkSocket::Message(Me) << "PING " << servname << " " << who;
+ Uplink::Send(Me, "PING", servname, who);
}
-/**
- * Send a PONG reply to a received PING.
- * servname should be left NULL to send a one param reply.
- * @param servname Daemon or client that is responding to the PING.
- * @param who Origin of the PING and destination of the PONG message.
- **/
void IRCDProto::SendPong(const Anope::string &servname, const Anope::string &who)
{
if (servname.empty())
- UplinkSocket::Message(Me) << "PONG " << who;
+ Uplink::Send(Me, "PONG", who);
else
- UplinkSocket::Message(Me) << "PONG " << servname << " " << who;
+ Uplink::Send(Me, "PONG", servname, who);
}
void IRCDProto::SendInvite(const MessageSource &source, const Channel *c, User *u)
{
- UplinkSocket::Message(source) << "INVITE " << u->GetUID() << " " << c->name;
+ Uplink::Send(source, "INVITE", u->GetUID(), c->name);
}
void IRCDProto::SendPart(User *user, const Channel *chan, const char *fmt, ...)
@@ -315,17 +324,17 @@ void IRCDProto::SendGlobops(const MessageSource &source, const char *fmt, ...)
void IRCDProto::SendSquit(Server *s, const Anope::string &message)
{
- UplinkSocket::Message() << "SQUIT " << s->GetSID() << " :" << message;
+ Uplink::Send("SQUIT", s->GetSID(), message);
}
void IRCDProto::SendNickChange(User *u, const Anope::string &newnick)
{
- UplinkSocket::Message(u) << "NICK " << newnick << " " << Anope::CurTime;
+ Uplink::Send(u, "NICK", newnick, Anope::CurTime);
}
void IRCDProto::SendForceNickChange(User *u, const Anope::string &newnick, time_t when)
{
- UplinkSocket::Message() << "SVSNICK " << u->GetUID() << " " << newnick << " " << when;
+ Uplink::Send(u, "SVSNICK", u->GetUID(), newnick, when);
}
void IRCDProto::SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
@@ -360,16 +369,16 @@ bool IRCDProto::IsNickValid(const Anope::string &nick)
if (nick.empty())
return false;
-
+
Anope::string special = "[]\\`_^{|}";
-
+
for (unsigned i = 0; i < nick.length(); ++i)
if (!(nick[i] >= 'A' && nick[i] <= 'Z') && !(nick[i] >= 'a' && nick[i] <= 'z')
&& special.find(nick[i]) == Anope::string::npos
&& (Config && Config->NickChars.find(nick[i]) == Anope::string::npos)
&& (!i || (!(nick[i] >= '0' && nick[i] <= '9') && nick[i] != '-')))
return false;
-
+
return true;
}
@@ -407,8 +416,8 @@ bool IRCDProto::IsHostValid(const Anope::string &host)
if (host.empty() || host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"))
return false;
- const Anope::string &vhostdisablebe = Config->GetBlock("networkinfo")->Get<const Anope::string>("disallow_start_or_end"),
- vhostchars = Config->GetBlock("networkinfo")->Get<const Anope::string>("vhost_chars");
+ const Anope::string &vhostdisablebe = Config->GetBlock("networkinfo")->Get<Anope::string>("disallow_start_or_end"),
+ vhostchars = Config->GetBlock("networkinfo")->Get<Anope::string>("vhost_chars");
if (vhostdisablebe.find_first_of(host[0]) != Anope::string::npos)
return false;
@@ -474,6 +483,15 @@ const Anope::string &MessageSource::GetName() const
return this->source;
}
+const Anope::string &MessageSource::GetUID() const
+{
+ if (this->s)
+ return this->s->GetSID();
+ if (this->u)
+ return this->u->GetUID();
+ return this->source;
+}
+
const Anope::string &MessageSource::GetSource() const
{
return this->source;
@@ -484,9 +502,9 @@ User *MessageSource::GetUser() const
return this->u;
}
-BotInfo *MessageSource::GetBot() const
+ServiceBot *MessageSource::GetBot() const
{
- return BotInfo::Find(this->GetName(), true);
+ return ServiceBot::Find(this->GetName(), true);
}
Server *MessageSource::GetServer() const
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
deleted file mode 100644
index 356ceb093..000000000
--- a/src/regchannel.cpp
+++ /dev/null
@@ -1,695 +0,0 @@
-/* Registered channel functions
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "services.h"
-#include "modules.h"
-#include "regchannel.h"
-#include "account.h"
-#include "access.h"
-#include "channels.h"
-#include "config.h"
-#include "bots.h"
-#include "servers.h"
-
-Serialize::Checker<registered_channel_map> RegisteredChannelList("ChannelInfo");
-
-AutoKick::AutoKick() : Serializable("AutoKick")
-{
-}
-
-AutoKick::~AutoKick()
-{
- if (this->ci)
- {
- std::vector<AutoKick *>::iterator it = std::find(this->ci->akick->begin(), this->ci->akick->end(), this);
- if (it != this->ci->akick->end())
- this->ci->akick->erase(it);
-
- const NickAlias *na = NickAlias::Find(this->mask);
- if (na != NULL)
- na->nc->RemoveChannelReference(this->ci);
- }
-}
-
-void AutoKick::Serialize(Serialize::Data &data) const
-{
- data["ci"] << this->ci->name;
- if (this->nc)
- data["nc"] << this->nc->display;
- else
- data["mask"] << this->mask;
- data["reason"] << this->reason;
- data["creator"] << this->creator;
- data.SetType("addtime", Serialize::Data::DT_INT); data["addtime"] << this->addtime;
- data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
-}
-
-Serializable* AutoKick::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string sci, snc;
-
- data["ci"] >> sci;
- data["nc"] >> snc;
-
- ChannelInfo *ci = ChannelInfo::Find(sci);
- if (!ci)
- return NULL;
-
- AutoKick *ak;
- NickCore *nc = NickCore::Find(snc);
- if (obj)
- {
- ak = anope_dynamic_static_cast<AutoKick *>(obj);
- data["creator"] >> ak->creator;
- data["reason"] >> ak->reason;
- ak->nc = NickCore::Find(snc);
- data["mask"] >> ak->mask;
- data["addtime"] >> ak->addtime;
- data["last_used"] >> ak->last_used;
- }
- else
- {
- time_t addtime, lastused;
- data["addtime"] >> addtime;
- data["last_used"] >> lastused;
-
- Anope::string screator, sreason, smask;
-
- data["creator"] >> screator;
- data["reason"] >> sreason;
- data["mask"] >> smask;
-
- if (nc)
- ak = ci->AddAkick(screator, nc, sreason, addtime, lastused);
- else
- ak = ci->AddAkick(screator, smask, sreason, addtime, lastused);
- }
-
- return ak;
-}
-
-ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable("ChannelInfo"),
- access("ChanAccess"), akick("AutoKick")
-{
- if (chname.empty())
- throw CoreException("Empty channel passed to ChannelInfo constructor");
-
- this->founder = NULL;
- this->successor = NULL;
- this->c = Channel::Find(chname);
- if (this->c)
- this->c->ci = this;
- this->banexpire = 0;
- this->bi = NULL;
- this->last_topic_time = 0;
-
- this->name = chname;
-
- this->bantype = 2;
- this->memos.memomax = 0;
- this->last_used = this->time_registered = Anope::CurTime;
-
- size_t old = RegisteredChannelList->size();
- (*RegisteredChannelList)[this->name] = this;
- if (old == RegisteredChannelList->size())
- Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in registered channel table?";
-
- FOREACH_MOD(OnCreateChan, (this));
-}
-
-ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"),
- access("ChanAccess"), akick("AutoKick")
-{
- *this = ci;
-
- if (this->founder)
- ++this->founder->channelcount;
-
- this->access->clear();
- this->akick->clear();
-
- FOREACH_MOD(OnCreateChan, (this));
-}
-
-ChannelInfo::~ChannelInfo()
-{
- UnsetExtensibles();
-
- FOREACH_MOD(OnDelChan, (this));
-
- Log(LOG_DEBUG) << "Deleting channel " << this->name;
-
- if (this->c)
- {
- if (this->bi && this->c->FindUser(this->bi))
- this->bi->Part(this->c);
-
- /* Parting the service bot can cause the channel to go away */
-
- if (this->c)
- {
- if (this->c && this->c->CheckDelete())
- this->c->QueueForDeletion();
-
- this->c = NULL;
- }
- }
-
- RegisteredChannelList->erase(this->name);
-
- this->SetFounder(NULL);
- this->SetSuccessor(NULL);
-
- this->ClearAccess();
- this->ClearAkick();
-
- if (!this->memos.memos->empty())
- {
- for (unsigned i = 0, end = this->memos.memos->size(); i < end; ++i)
- delete this->memos.GetMemo(i);
- this->memos.memos->clear();
- }
-}
-
-void ChannelInfo::Serialize(Serialize::Data &data) const
-{
- data["name"] << this->name;
- if (this->founder)
- data["founder"] << this->founder->display;
- if (this->successor)
- data["successor"] << this->successor->display;
- data["description"] << this->desc;
- data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
- data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used;
- data["last_topic"] << this->last_topic;
- data["last_topic_setter"] << this->last_topic_setter;
- data.SetType("last_topic_time", Serialize::Data::DT_INT); data["last_topic_time"] << this->last_topic_time;
- data.SetType("bantype", Serialize::Data::DT_INT); data["bantype"] << this->bantype;
- {
- Anope::string levels_buffer;
- for (Anope::map<int16_t>::const_iterator it = this->levels.begin(), it_end = this->levels.end(); it != it_end; ++it)
- levels_buffer += it->first + " " + stringify(it->second) + " ";
- data["levels"] << levels_buffer;
- }
- if (this->bi)
- data["bi"] << this->bi->nick;
- data.SetType("banexpire", Serialize::Data::DT_INT); data["banexpire"] << this->banexpire;
- data["memomax"] << this->memos.memomax;
- for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
- data["memoignores"] << this->memos.ignores[i] << " ";
-
- Extensible::ExtensibleSerialize(this, this, data);
-}
-
-Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string sname, sfounder, ssuccessor, slevels, sbi;
-
- data["name"] >> sname;
- data["founder"] >> sfounder;
- data["successor"] >> ssuccessor;
- data["levels"] >> slevels;
- data["bi"] >> sbi;
-
- ChannelInfo *ci;
- if (obj)
- ci = anope_dynamic_static_cast<ChannelInfo *>(obj);
- else
- ci = new ChannelInfo(sname);
-
- ci->SetFounder(NickCore::Find(sfounder));
- ci->SetSuccessor(NickCore::Find(ssuccessor));
-
- data["description"] >> ci->desc;
- data["time_registered"] >> ci->time_registered;
- data["last_used"] >> ci->last_used;
- data["last_topic"] >> ci->last_topic;
- data["last_topic_setter"] >> ci->last_topic_setter;
- data["last_topic_time"] >> ci->last_topic_time;
- data["bantype"] >> ci->bantype;
- {
- std::vector<Anope::string> v;
- spacesepstream(slevels).GetTokens(v);
- for (unsigned i = 0; i + 1 < v.size(); i += 2)
- try
- {
- ci->levels[v[i]] = convertTo<int16_t>(v[i + 1]);
- }
- catch (const ConvertException &) { }
- }
- BotInfo *bi = BotInfo::Find(sbi, true);
- if (*ci->bi != bi)
- {
- if (bi)
- bi->Assign(NULL, ci);
- else if (ci->bi)
- ci->bi->UnAssign(NULL, ci);
- }
- data["banexpire"] >> ci->banexpire;
- data["memomax"] >> ci->memos.memomax;
- {
- Anope::string buf;
- data["memoignores"] >> buf;
- spacesepstream sep(buf);
- ci->memos.ignores.clear();
- while (sep.GetToken(buf))
- ci->memos.ignores.push_back(buf);
- }
-
- Extensible::ExtensibleUnserialize(ci, ci, data);
-
- /* compat */
- bool b;
- b = false;
- data["extensible:SECURE"] >> b;
- if (b)
- ci->Extend<bool>("CS_SECURE");
- b = false;
- data["extensible:PRIVATE"] >> b;
- if (b)
- ci->Extend<bool>("CS_PRIVATE");
- b = false;
- data["extensible:NO_EXPIRE"] >> b;
- if (b)
- ci->Extend<bool>("CS_NO_EXPIRE");
- b = false;
- data["extensible:FANTASY"] >> b;
- if (b)
- ci->Extend<bool>("BS_FANTASY");
- b = false;
- data["extensible:GREET"] >> b;
- if (b)
- ci->Extend<bool>("BS_GREET");
- b = false;
- data["extensible:PEACE"] >> b;
- if (b)
- ci->Extend<bool>("PEACE");
- b = false;
- data["extensible:SECUREFOUNDER"] >> b;
- if (b)
- ci->Extend<bool>("SECUREFOUNDER");
- b = false;
- data["extensible:RESTRICTED"] >> b;
- if (b)
- ci->Extend<bool>("RESTRICTED");
- b = false;
- data["extensible:KEEPTOPIC"] >> b;
- if (b)
- ci->Extend<bool>("KEEPTOPIC");
- b = false;
- data["extensible:SIGNKICK"] >> b;
- if (b)
- ci->Extend<bool>("SIGNKICK");
- b = false;
- data["extensible:SIGNKICK_LEVEL"] >> b;
- if (b)
- ci->Extend<bool>("SIGNKICK_LEVEL");
- /* end compat */
-
- return ci;
-}
-
-
-void ChannelInfo::SetFounder(NickCore *nc)
-{
- if (this->founder)
- {
- --this->founder->channelcount;
- this->founder->RemoveChannelReference(this);
- }
-
- this->founder = nc;
-
- if (this->founder)
- {
- ++this->founder->channelcount;
- this->founder->AddChannelReference(this);
- }
-}
-
-NickCore *ChannelInfo::GetFounder() const
-{
- return this->founder;
-}
-
-void ChannelInfo::SetSuccessor(NickCore *nc)
-{
- if (this->successor)
- this->successor->RemoveChannelReference(this);
- this->successor = nc;
- if (this->successor)
- this->successor->AddChannelReference(this);
-}
-
-NickCore *ChannelInfo::GetSuccessor() const
-{
- return this->successor;
-}
-
-BotInfo *ChannelInfo::WhoSends() const
-{
- if (this && this->bi)
- return this->bi;
-
- BotInfo *ChanServ = Config->GetClient("ChanServ");
- if (ChanServ)
- return ChanServ;
-
- if (!BotListByNick->empty())
- return BotListByNick->begin()->second;
-
- return NULL;
-}
-
-void ChannelInfo::AddAccess(ChanAccess *taccess)
-{
- this->access->push_back(taccess);
-}
-
-ChanAccess *ChannelInfo::GetAccess(unsigned index) const
-{
- if (this->access->empty() || index >= this->access->size())
- return NULL;
-
- ChanAccess *acc = (*this->access)[index];
- acc->QueueUpdate();
- return acc;
-}
-
-static void FindMatchesRecurse(ChannelInfo *ci, const User *u, const NickCore *account, unsigned int depth, std::vector<ChanAccess::Path> &paths, ChanAccess::Path &path)
-{
- if (depth > ChanAccess::MAX_DEPTH)
- return;
-
- for (unsigned int i = 0; i < ci->GetAccessCount(); ++i)
- {
- ChanAccess *a = ci->GetAccess(i);
- ChannelInfo *next = NULL;
-
- if (a->Matches(u, account, next))
- {
- ChanAccess::Path next_path = path;
- next_path.push_back(a);
-
- paths.push_back(next_path);
- }
- else if (next)
- {
- ChanAccess::Path next_path = path;
- next_path.push_back(a);
-
- FindMatchesRecurse(next, u, account, depth + 1, paths, next_path);
- }
- }
-}
-
-static void FindMatches(AccessGroup &group, ChannelInfo *ci, const User *u, const NickCore *account)
-{
- ChanAccess::Path path;
- FindMatchesRecurse(ci, u, account, 0, group.paths, path);
-}
-
-AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed)
-{
- AccessGroup group;
-
- if (u == NULL)
- return group;
-
- const NickCore *nc = u->Account();
- if (nc == NULL && !this->HasExt("NS_SECURE") && u->IsRecognized())
- {
- const NickAlias *na = NickAlias::Find(u->nick);
- if (na != NULL)
- nc = na->nc;
- }
-
- group.super_admin = u->super_admin;
- group.founder = IsFounder(u, this);
- group.ci = this;
- group.nc = nc;
-
- FindMatches(group, this, u, u->Account());
-
- if (group.founder || !group.paths.empty())
- {
- if (updateLastUsed)
- this->last_used = Anope::CurTime;
-
- for (unsigned i = 0; i < group.paths.size(); ++i)
- {
- ChanAccess::Path &p = group.paths[i];
-
- for (unsigned int j = 0; j < p.size(); ++j)
- p[j]->last_seen = Anope::CurTime;
- }
- }
-
- return group;
-}
-
-AccessGroup ChannelInfo::AccessFor(const NickCore *nc, bool updateLastUsed)
-{
- AccessGroup group;
-
- group.founder = (this->founder && this->founder == nc);
- group.ci = this;
- group.nc = nc;
-
- FindMatches(group, this, NULL, nc);
-
- if (group.founder || !group.paths.empty())
- if (updateLastUsed)
- this->last_used = Anope::CurTime;
-
- /* don't update access last seen here, this isn't the user requesting access */
-
- return group;
-}
-
-unsigned ChannelInfo::GetAccessCount() const
-{
- return this->access->size();
-}
-
-static unsigned int GetDeepAccessCount(const ChannelInfo *ci, std::set<const ChannelInfo *> &seen, unsigned int depth)
-{
- if (depth > ChanAccess::MAX_DEPTH || seen.count(ci))
- return 0;
- seen.insert(ci);
-
- unsigned int total = 0;
-
- for (unsigned int i = 0; i < ci->GetAccessCount(); ++i)
- {
- ChanAccess::Path path;
- ChanAccess *a = ci->GetAccess(i);
- ChannelInfo *next = NULL;
-
- a->Matches(NULL, NULL, next);
- ++total;
-
- if (next)
- total += GetDeepAccessCount(ci, seen, depth + 1);
- }
-
- return total;
-}
-
-unsigned ChannelInfo::GetDeepAccessCount() const
-{
- std::set<const ChannelInfo *> seen;
- return ::GetDeepAccessCount(this, seen, 0);
-}
-
-ChanAccess *ChannelInfo::EraseAccess(unsigned index)
-{
- if (this->access->empty() || index >= this->access->size())
- return NULL;
-
- ChanAccess *ca = this->access->at(index);
- this->access->erase(this->access->begin() + index);
- return ca;
-}
-
-void ChannelInfo::ClearAccess()
-{
- for (unsigned i = this->access->size(); i > 0; --i)
- delete this->GetAccess(i - 1);
-}
-
-AutoKick *ChannelInfo::AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t, time_t lu)
-{
- AutoKick *autokick = new AutoKick();
- autokick->ci = this;
- autokick->nc = akicknc;
- autokick->reason = reason;
- autokick->creator = user;
- autokick->addtime = t;
- autokick->last_used = lu;
-
- this->akick->push_back(autokick);
-
- akicknc->AddChannelReference(this);
-
- return autokick;
-}
-
-AutoKick *ChannelInfo::AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t, time_t lu)
-{
- AutoKick *autokick = new AutoKick();
- autokick->ci = this;
- autokick->mask = mask;
- autokick->nc = NULL;
- autokick->reason = reason;
- autokick->creator = user;
- autokick->addtime = t;
- autokick->last_used = lu;
-
- this->akick->push_back(autokick);
-
- return autokick;
-}
-
-AutoKick *ChannelInfo::GetAkick(unsigned index) const
-{
- if (this->akick->empty() || index >= this->akick->size())
- return NULL;
-
- AutoKick *ak = (*this->akick)[index];
- ak->QueueUpdate();
- return ak;
-}
-
-unsigned ChannelInfo::GetAkickCount() const
-{
- return this->akick->size();
-}
-
-void ChannelInfo::EraseAkick(unsigned index)
-{
- if (this->akick->empty() || index >= this->akick->size())
- return;
-
- delete this->GetAkick(index);
-}
-
-void ChannelInfo::ClearAkick()
-{
- while (!this->akick->empty())
- delete this->akick->back();
-}
-
-const Anope::map<int16_t> &ChannelInfo::GetLevelEntries()
-{
- return this->levels;
-}
-
-int16_t ChannelInfo::GetLevel(const Anope::string &priv) const
-{
- if (PrivilegeManager::FindPrivilege(priv) == NULL)
- {
- Log(LOG_DEBUG) << "Unknown privilege " + priv;
- return ACCESS_INVALID;
- }
-
- Anope::map<int16_t>::const_iterator it = this->levels.find(priv);
- if (it == this->levels.end())
- return 0;
- return it->second;
-}
-
-void ChannelInfo::SetLevel(const Anope::string &priv, int16_t level)
-{
- if (PrivilegeManager::FindPrivilege(priv) == NULL)
- {
- Log(LOG_DEBUG) << "Unknown privilege " + priv;
- return;
- }
-
- this->levels[priv] = level;
-}
-
-void ChannelInfo::RemoveLevel(const Anope::string &priv)
-{
- this->levels.erase(priv);
-}
-
-void ChannelInfo::ClearLevels()
-{
- this->levels.clear();
-}
-
-Anope::string ChannelInfo::GetIdealBan(User *u) const
-{
- int bt = this ? this->bantype : -1;
- switch (bt)
- {
- case 0:
- return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost();
- case 1:
- if (u->GetVIdent()[0] == '~')
- return "*!*" + u->GetVIdent() + "@" + u->GetDisplayedHost();
- else
- return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost();
- case 3:
- return "*!" + u->Mask();
- case 2:
- default:
- return "*!*@" + u->GetDisplayedHost();
- }
-}
-
-ChannelInfo* ChannelInfo::Find(const Anope::string &name)
-{
- registered_channel_map::const_iterator it = RegisteredChannelList->find(name);
- if (it != RegisteredChannelList->end())
- {
- it->second->QueueUpdate();
- return it->second;
- }
-
- return NULL;
-}
-
-bool IsFounder(const User *user, const ChannelInfo *ci)
-{
- if (!user || !ci)
- return false;
-
- if (user->super_admin)
- return true;
-
- if (user->Account() && user->Account() == ci->GetFounder())
- return true;
-
- return false;
-}
-
-
-void ChannelInfo::AddChannelReference(const Anope::string &what)
-{
- ++references[what];
-}
-
-void ChannelInfo::RemoveChannelReference(const Anope::string &what)
-{
- int &i = references[what];
- if (--i <= 0)
- references.erase(what);
-}
-
-void ChannelInfo::GetChannelReferences(std::deque<Anope::string> &chans)
-{
- chans.clear();
- for (Anope::map<int>::iterator it = references.begin(); it != references.end(); ++it)
- chans.push_back(it->first);
-}
diff --git a/src/serialize.cpp b/src/serialize.cpp
index 3c54b933d..099151191 100644
--- a/src/serialize.cpp
+++ b/src/serialize.cpp
@@ -1,178 +1,318 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2012-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "anope.h"
#include "serialize.h"
#include "modules.h"
-#include "account.h"
-#include "bots.h"
-#include "regchannel.h"
-#include "xline.h"
-#include "access.h"
+#include "event.h"
using namespace Serialize;
-std::vector<Anope::string> Type::TypeOrder;
-std::map<Anope::string, Type *> Serialize::Type::Types;
-std::list<Serializable *> *Serializable::SerializableItems;
+std::unordered_map<ID, Object *> Serialize::objects;
-void Serialize::RegisterTypes()
-{
- static Type nc("NickCore", NickCore::Unserialize), na("NickAlias", NickAlias::Unserialize), bi("BotInfo", BotInfo::Unserialize),
- ci("ChannelInfo", ChannelInfo::Unserialize), access("ChanAccess", ChanAccess::Unserialize),
- akick("AutoKick", AutoKick::Unserialize), memo("Memo", Memo::Unserialize), xline("XLine", XLine::Unserialize);
-}
+std::vector<FieldBase *> Serialize::serializableFields;
+
+std::multimap<Anope::string, Anope::string> Serialize::child_types;
-void Serialize::CheckTypes()
+static ID curid;
+
+
+Object *Serialize::GetID(ID id)
{
- for (std::map<Anope::string, Serialize::Type *>::const_iterator it = Serialize::Type::GetTypes().begin(), it_end = Serialize::Type::GetTypes().end(); it != it_end; ++it)
- {
- Serialize::Type *t = it->second;
- t->Check();
- }
+ auto it = objects.find(id);
+ if (it != objects.end())
+ return it->second;
+ return nullptr;
}
-Serializable::Serializable(const Anope::string &serialize_type) : last_commit(0), last_commit_time(0), id(0), redis_ignore(0)
+void Serialize::Clear()
{
- if (SerializableItems == NULL)
- SerializableItems = new std::list<Serializable *>();
- SerializableItems->push_back(this);
+ std::unordered_map<ID, Object *> o;
+ objects.swap(o);
- this->s_type = Type::Find(serialize_type);
+ for (const std::pair<ID, Object *> &p : o)
+ delete p.second;
+}
- this->s_iter = SerializableItems->end();
- --this->s_iter;
+void Serialize::Unregister(Module *m)
+{
+ for (TypeBase *s : ServiceManager::Get()->FindServices<Serialize::TypeBase *>())
+ if (s->GetOwner() == m)
+ s->Unregister();
- FOREACH_MOD(OnSerializableConstruct, (this));
+ for (FieldBase *field : serializableFields)
+ if (field->GetOwner() == m)
+ field->Unregister();
}
-Serializable::Serializable(const Serializable &other) : last_commit(0), last_commit_time(0), id(0), redis_ignore(0)
+std::vector<Edge> Object::GetRefs(TypeBase *type)
{
- SerializableItems->push_back(this);
- this->s_iter = SerializableItems->end();
- --this->s_iter;
+ std::vector<Edge> refs;
+ EventReturn result = EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializeGetRefs, this, type, refs);
+ if (result == EVENT_ALLOW)
+ return refs;
- this->s_type = other.s_type;
+ if (type == nullptr)
+ {
+ refs.clear();
+ for (const std::pair<TypeBase *, std::vector<Edge>> &p : edges)
+ {
+ const std::vector<Edge> &e = p.second;
+ refs.insert(refs.end(), e.begin(), e.end());
+ }
+ return refs;
+ }
- FOREACH_MOD(OnSerializableConstruct, (this));
+ auto it = edges.find(type);
+ if (it != edges.end())
+ return it->second;
+ return std::vector<Edge>();
}
-Serializable::~Serializable()
+Object::Object(TypeBase *type)
{
- FOREACH_MOD(OnSerializableDestruct, (this));
+ ID i;
+ EventReturn result = EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializableGetId, i);
+ if (result != EVENT_ALLOW)
+ {
+ while (GetID(++curid));
+ i = curid;
+ }
+
+ id = i;
+ objects[id] = this;
+
+ this->s_type = type;
+
+ type->objects.insert(this);
+
+ Log(LOG_DEBUG_2) << "Creating object id #" << id << " address " << static_cast<void *>(this) << " type " << type->GetName();
- SerializableItems->erase(this->s_iter);
+ EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializableCreate, this);
}
-Serializable &Serializable::operator=(const Serializable &)
+Object::Object(TypeBase *type, ID i)
{
- return *this;
+ this->id = i;
+ objects[i] = this;
+
+ this->s_type = type;
+
+ type->objects.insert(this);
+
+ Log(LOG_DEBUG_2) << "Creating object from id #" << id << " address " << static_cast<void *>(this) << " type " << type->GetName();
}
-void Serializable::QueueUpdate()
+Object::~Object()
{
- /* Schedule updater */
- FOREACH_MOD(OnSerializableUpdate, (this));
+ Log(LOG_DEBUG_2) << "Destructing object id #" << id << " address " << static_cast<void *>(this) << " type " << s_type->GetName();
- /* Check for modifications now - this can delete this object! */
- FOREACH_MOD(OnSerializeCheck, (this->GetSerializableType()));
+ /* Remove in memory edges */
+ cont:
+ for (const std::pair<TypeBase *, std::vector<Edge>> &p : edges)
+ for (const Edge &edge : p.second)
+ {
+ if (!edge.direction)
+ {
+ Log(LOG_DEBUG_2) << "Removing edge from object id #" << edge.other->id << " type " << edge.other->GetSerializableType()->GetName() << " on field " << edge.field->serialize_name;
+ edge.other->RemoveEdge(this, edge.field);
+ }
+ else
+ {
+ Log(LOG_DEBUG_2) << "Removing edge to object id #" << edge.other->id << " type " << edge.other->GetSerializableType()->GetName() << " on field " << edge.field->serialize_name;
+ this->RemoveEdge(edge.other, edge.field);
+ }
+ goto cont;
+ }
+
+ objects.erase(id);
+ s_type->objects.erase(this);
}
-bool Serializable::IsCached(Serialize::Data &data)
+void Object::Delete()
{
- return this->last_commit == data.Hash();
+ Log(LOG_DEBUG_2) << "Deleting object id #" << id << " type " << s_type->GetName();
+
+ /* Delete dependant objects */
+ for (const Edge &edge : GetRefs(nullptr))
+ {
+ Object *other = edge.other;
+ FieldBase *field = edge.field;
+
+ if (edge.direction)
+ continue;
+
+ if (field->depends)
+ {
+ Log(LOG_DEBUG_2) << "Deleting dependent object #" << other->id << " type " << other->GetSerializableType()->GetName() << " due to edge on " << field->serialize_name;
+ other->Delete();
+ }
+ else
+ {
+ Log(LOG_DEBUG_2) << "Unsetting field " << field->serialize_name << " on object #" << other->id << " type " << other->GetSerializableType()->GetName();
+ field->UnsetS(other);
+ }
+ }
+
+ EventManager::Get()->Dispatch(&Event::SerializeEvents::OnSerializableDelete, this);
+
+ delete this;
}
-void Serializable::UpdateCache(Serialize::Data &data)
+void Object::AddEdge(Object *other, FieldBase *field)
{
- this->last_commit = data.Hash();
+ // field = the field on 'this' object
+ this->edges[other->GetSerializableType()].emplace_back(other, field, true);
+ // field = the field on the other object
+ other->edges[this->GetSerializableType()].emplace_back(this, field, false);
}
-bool Serializable::IsTSCached()
+void Object::RemoveEdge(Object *other, FieldBase *field)
{
- return this->last_commit_time == Anope::CurTime;
+ std::vector<Edge> &myedges = this->edges[other->GetSerializableType()];
+ auto it = std::find(myedges.begin(), myedges.end(), Edge(other, field, true));
+ if (it != myedges.end())
+ myedges.erase(it);
+ else
+ Log(LOG_DEBUG_2) << "Unable to locate edge for removal on #" << this->id << " type " << s_type->GetName() << " -> #" << other->id << " type " << other->GetSerializableType()->GetName();
+
+ std::vector<Edge> &theiredges = other->edges[this->GetSerializableType()];
+ it = std::find(theiredges.begin(), theiredges.end(), Edge(this, field, false));
+ if (it != theiredges.end())
+ theiredges.erase(it);
+ else
+ Log(LOG_DEBUG_2) << "Unable to locate edge for removal on #" << this->id << " type " << s_type->GetName() << " <- #" << other->id << " type " << other->GetSerializableType()->GetName();
}
-void Serializable::UpdateTS()
+TypeBase::TypeBase(Module *o, const Anope::string &n) : Service(o, TypeBase::NAME, n), name(n), owner(o)
{
- this->last_commit_time = Anope::CurTime;
}
-const std::list<Serializable *> &Serializable::GetItems()
+TypeBase::~TypeBase()
{
- return *SerializableItems;
+ if (!Serialize::GetObjects<Object *>(this->GetName()).empty())
+ throw CoreException("Type destructing with objects still alive");
}
-Type::Type(const Anope::string &n, unserialize_func f, Module *o) : name(n), unserialize(f), owner(o), timestamp(0)
+void TypeBase::Unregister()
{
- TypeOrder.push_back(this->name);
- Types[this->name] = this;
+ Log(LOG_DEBUG_2) << "Unregistering type " << this->GetName();
- FOREACH_MOD(OnSerializeTypeCreate, (this));
+ for (Object *obj : GetObjects<Object *>(this->GetName()))
+ obj->Delete();
+
+ for (FieldBase *field : serializableFields)
+ {
+ if (field->serialize_type == this->GetName())
+ {
+ field->Unregister();
+ }
+ }
}
-Type::~Type()
+Serialize::FieldBase *TypeBase::GetField(const Anope::string &fname)
{
- /* null the type of existing serializable objects of this type */
- if (Serializable::SerializableItems != NULL)
- for (std::list<Serializable *>::iterator it = Serializable::SerializableItems->begin(); it != Serializable::SerializableItems->end(); ++it)
- {
- Serializable *s = *it;
+ /* is this too slow? */
+ for (FieldBase *fb : ServiceManager::Get()->FindServices<FieldBase *>())
+ if (fb->serialize_type == this->GetName() && fb->serialize_name == fname)
+ return fb;
- if (s->s_type == this)
- s->s_type = NULL;
- }
+ Log(LOG_DEBUG_2) << "GetField() for unknown field " << fname << " on " << this->GetName();
- std::vector<Anope::string>::iterator it = std::find(TypeOrder.begin(), TypeOrder.end(), this->name);
- if (it != TypeOrder.end())
- TypeOrder.erase(it);
- Types.erase(this->name);
+ return nullptr;
}
-Serializable *Type::Unserialize(Serializable *obj, Serialize::Data &data)
+std::vector<Serialize::FieldBase *> TypeBase::GetFields()
{
- return this->unserialize(obj, data);
+ std::vector<Serialize::FieldBase *> fields;
+
+ for (FieldBase *fb : ServiceManager::Get()->FindServices<FieldBase *>())
+ if (fb->serialize_type == this->GetName())
+ fields.push_back(fb);
+
+ return fields;
}
-void Type::Check()
+TypeBase *TypeBase::Find(const Anope::string &name)
{
- FOREACH_MOD(OnSerializeCheck, (this));
+ return ServiceManager::Get()->FindService<TypeBase *>(name);
}
-time_t Type::GetTimestamp() const
+FieldBase::FieldBase(Module *c, const Anope::string &n, const Anope::string &t, bool d)
+ : Service(c, FieldBase::NAME)
+ , serialize_type(t)
+ , serialize_name(n)
+ , depends(d)
{
- return this->timestamp;
+ serializableFields.push_back(this);
}
-void Type::UpdateTimestamp()
+FieldBase::~FieldBase()
{
- this->timestamp = Anope::CurTime;
+ auto it = std::find(serializableFields.begin(), serializableFields.end(), this);
+ if (it != serializableFields.end())
+ serializableFields.erase(it);
}
-Type *Serialize::Type::Find(const Anope::string &name)
+void FieldBase::Unregister()
{
- std::map<Anope::string, Type *>::iterator it = Types.find(name);
- if (it != Types.end())
- return it->second;
- return NULL;
+ Log(LOG_DEBUG_2) << "Unregistering field " << serialize_name << " on " << serialize_type;
+
+ /* find edges on this field */
+ for (Object *s : Serialize::GetObjects<Object *>(serialize_type))
+ {
+ for (const std::pair<TypeBase *, std::vector<Edge>> &p : s->edges)
+ for (const Edge &edge : p.second)
+ if (edge.direction && edge.field == this)
+ {
+ Log(LOG_DEBUG_2) << "Removing edge on #" << s->id << " type " << s->GetSerializableType()->GetName() << " -> #" << edge.other->id << " type " << edge.other->GetSerializableType()->GetName();
+ s->RemoveEdge(edge.other, edge.field);
+
+ goto cont;
+ }
+ cont:;
+ }
}
-const std::vector<Anope::string> &Type::GetTypeOrder()
+void Serialize::SetParent(const Anope::string &child, const Anope::string &parent)
{
- return TypeOrder;
+ child_types.insert(std::make_pair(parent, child));
}
-const std::map<Anope::string, Serialize::Type *>& Type::GetTypes()
+std::vector<Serialize::TypeBase *> Serialize::GetTypes(const Anope::string &name)
{
- return Types;
-}
+ std::vector<Serialize::TypeBase *> v;
+ Serialize::TypeBase *t = Serialize::TypeBase::Find(name);
+ if (t != nullptr)
+ v.push_back(t);
+ else
+ Log(LOG_DEBUG_2) << "GetTypes for unknown type " << name;
+
+ auto its = child_types.equal_range(name);
+ for (; its.first != its.second; ++its.first)
+ {
+ t = Serialize::TypeBase::Find(its.first->second);
+ if (t != nullptr)
+ v.push_back(t);
+ }
+
+ return v;
+}
diff --git a/src/servers.cpp b/src/servers.cpp
index b78cd19f7..5f48a5e7c 100644
--- a/src/servers.cpp
+++ b/src/servers.cpp
@@ -1,12 +1,20 @@
-/* Routines to maintain a list of connected servers
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2004-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -14,10 +22,11 @@
#include "xline.h"
#include "servers.h"
#include "bots.h"
-#include "regchannel.h"
#include "protocol.h"
#include "config.h"
#include "channels.h"
+#include "event.h"
+#include "modules/chanserv.h"
/* Anope */
Server *Me = NULL;
@@ -46,93 +55,10 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano
/* Check to be sure this isn't a juped server */
if (Me == this->uplink && !juped)
- {
- /* Now do mode related stuff as we know what modes exist .. */
- for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- {
- BotInfo *bi = it->second;
- Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : IRCD->DefaultPseudoclientModes;
-
- bi->SetModesInternal(bi, modes.c_str());
- for (unsigned i = 0; i < bi->botchannels.size(); ++i)
- {
- size_t h = bi->botchannels[i].find('#');
- if (h == Anope::string::npos)
- continue;
- Anope::string chname = bi->botchannels[i].substr(h);
- Channel *c = Channel::Find(chname);
- if (c && c->FindUser(bi))
- {
- Anope::string want_modes = bi->botchannels[i].substr(0, h);
- for (unsigned j = 0; j < want_modes.length(); ++j)
- {
- ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]);
- if (cm == NULL)
- cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j]));
- if (cm && cm->type == MODE_STATUS)
- {
- MessageSource ms = bi;
- c->SetModeInternal(ms, cm, bi->nick);
- }
- }
- }
- }
- }
-
- IRCD->SendBOB();
-
- for (unsigned i = 0; i < Me->GetLinks().size(); ++i)
- {
- Server *s = Me->GetLinks()[i];
-
- if (s->juped)
- IRCD->SendServer(s);
- }
-
- /* We make the bots go online */
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- {
- User *u = it->second;
-
- BotInfo *bi = BotInfo::Find(u->GetUID());
- if (bi)
- {
- XLine x(bi->nick, "Reserved for services");
- IRCD->SendSQLine(NULL, &x);
- }
-
- IRCD->SendClientIntroduction(u);
- if (bi)
- bi->introduced = true;
- }
-
- for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
- {
- Channel *c = it->second;
-
- if (c->users.empty())
- IRCD->SendChannel(c);
- else
- for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit)
- IRCD->SendJoin(cit->second->user, c, &cit->second->status);
-
- for (Channel::ModeList::const_iterator it2 = c->GetModes().begin(); it2 != c->GetModes().end(); ++it2)
- {
- ChannelMode *cm = ModeManager::FindChannelModeByName(it2->first);
- if (!cm || cm->type != MODE_LIST)
- continue;
- ModeManager::StackerAdd(c->ci->WhoSends(), c, cm, true, it2->second);
- }
-
- if (!c->topic.empty() && !c->topic_setter.empty())
- IRCD->SendTopic(c->ci->WhoSends(), c);
-
- c->syncing = true;
- }
- }
+ Burst();
}
- FOREACH_MOD(OnNewServer, (this));
+ EventManager::Get()->Dispatch(&Event::NewServer::OnNewServer, this);
}
Server::~Server()
@@ -157,7 +83,7 @@ Server::~Server()
for (unsigned i = this->links.size(); i > 0; --i)
this->links[i - 1]->Delete(this->quit_reason);
-
+
Servers::ByName.erase(this->name);
if (!this->sid.empty())
Servers::ByID.erase(this->sid);
@@ -167,10 +93,64 @@ void Server::Delete(const Anope::string &reason)
{
this->quit_reason = reason;
this->quitting = true;
- FOREACH_MOD(OnServerQuit, (this));
+ EventManager::Get()->Dispatch(&Event::ServerQuit::OnServerQuit, this);
delete this;
}
+void Server::Burst()
+{
+ IRCD->SendBOB();
+
+ for (unsigned i = 0; i < Me->GetLinks().size(); ++i)
+ {
+ Server *s = Me->GetLinks()[i];
+
+ if (s->juped)
+ IRCD->SendServer(s);
+ }
+
+ /* We make the bots go online */
+ for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
+ {
+ User *u = it->second;
+
+ ServiceBot *bi = ServiceBot::Find(u->GetUID());
+ if (bi)
+ {
+ //XLine x(bi->nick, "Reserved for services");
+ //IRCD->SendSQLine(NULL, &x);
+ }
+
+ IRCD->SendClientIntroduction(u);
+ if (bi)
+ bi->introduced = true;
+ }
+
+ for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
+ {
+ Channel *c = it->second;
+
+ if (c->users.empty())
+ IRCD->SendChannel(c);
+ else
+ for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit)
+ IRCD->SendJoin(cit->second->user, c, &cit->second->status);
+
+ for (Channel::ModeList::const_iterator it2 = c->GetModes().begin(); it2 != c->GetModes().end(); ++it2)
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByName(it2->first);
+ if (!cm || cm->type != MODE_LIST)
+ continue;
+ ModeManager::StackerAdd(c->ci->WhoSends(), c, cm, true, it2->second);
+ }
+
+ if (!c->topic.empty() && !c->topic_setter.empty())
+ IRCD->SendTopic(c->ci->WhoSends(), c);
+
+ c->syncing = true;
+ }
+}
+
const Anope::string &Server::GetName() const
{
return this->name;
@@ -255,7 +235,7 @@ void Server::Sync(bool sync_links)
Log(this, "sync") << "is done syncing";
- FOREACH_MOD(OnServerSync, (this));
+ EventManager::Get()->Dispatch(&Event::ServerSync::OnServerSync, this);
if (sync_links && !this->links.empty())
{
@@ -267,7 +247,7 @@ void Server::Sync(bool sync_links)
if (me)
{
- FOREACH_MOD(OnPreUplinkSync, (this));
+ EventManager::Get()->Dispatch(&Event::PreUplinkSync::OnPreUplinkSync, this);
}
for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end;)
@@ -284,7 +264,7 @@ void Server::Sync(bool sync_links)
IRCD->SendEOB();
Me->Sync(false);
- FOREACH_MOD(OnUplinkSync, (this));
+ EventManager::Get()->Dispatch(&Event::UplinkSync::OnUplinkSync, this);
if (!Anope::NoFork)
{
@@ -325,7 +305,7 @@ bool Server::IsQuitting() const
return quitting;
}
-void Server::Notice(BotInfo *source, const Anope::string &message)
+void Server::Notice(ServiceBot *source, const Anope::string &message)
{
if (Config->UsePrivmsg && Config->DefPrivmsg)
IRCD->SendGlobalPrivmsg(source, this, message);
@@ -336,18 +316,18 @@ void Server::Notice(BotInfo *source, const Anope::string &message)
Server *Server::Find(const Anope::string &name, bool name_only)
{
Anope::map<Server *>::iterator it;
-
+
if (!name_only)
{
it = Servers::ByID.find(name);
if (it != Servers::ByID.end())
return it->second;
}
-
+
it = Servers::ByName.find(name);
if (it != Servers::ByName.end())
return it->second;
-
+
return NULL;
}
diff --git a/src/service.cpp b/src/service.cpp
new file mode 100644
index 000000000..9e99d0cad
--- /dev/null
+++ b/src/service.cpp
@@ -0,0 +1,67 @@
+/*
+ * Anope IRC Services
+ *
+ * Copyright (C) 2016 Adam <Adam@anope.org>
+ * Copyright (C) 2014-2016 Anope Team <team@anope.org>
+ *
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
+ */
+
+#include "services.h"
+#include "service.h"
+#include "modules/nickserv.h"
+#include "modules/chanserv.h"
+#include "modules/memoserv.h"
+
+NickServ::NickServService *NickServ::service = nullptr;
+ChanServ::ChanServService *ChanServ::service = nullptr;
+MemoServ::MemoServService *MemoServ::service = nullptr;
+
+ServiceReferenceBase::ServiceReferenceBase(const Anope::string &_type, const Anope::string &_name) : type(_type), name(_name)
+{
+ ServiceManager::Get()->RegisterReference(this);
+}
+
+ServiceReferenceBase::ServiceReferenceBase(const Anope::string &_type) : ServiceReferenceBase(_type, "")
+{
+}
+
+ServiceReferenceBase::~ServiceReferenceBase()
+{
+ ServiceManager::Get()->UnregisterReference(this);
+}
+
+void ServiceReferenceBase::SetService(Service *service)
+{
+ if (service == nullptr)
+ this->services.clear();
+ else
+ this->services = { service };
+}
+
+void ServiceReferenceBase::SetServices(const std::vector<Service *> &s)
+{
+ this->services = s;
+}
+
+Service::Service(Module *o, const Anope::string &t, const Anope::string &n) : owner(o), type(t), name(n)
+{
+ ServiceManager::Get()->Register(this);
+}
+
+Service::~Service()
+{
+ ServiceManager::Get()->Unregister(this);
+}
+
diff --git a/src/service_manager.cpp b/src/service_manager.cpp
new file mode 100644
index 000000000..ef26fb13b
--- /dev/null
+++ b/src/service_manager.cpp
@@ -0,0 +1,138 @@
+/*
+ * Anope IRC Services
+ *
+ * Copyright (C) 2016 Adam <Adam@anope.org>
+ * Copyright (C) 2016 Anope Team <team@anope.org>
+ *
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
+ */
+
+#include "services.h"
+#include "service.h"
+#include "logger.h"
+
+ServiceManager *ServiceManager::manager = nullptr;
+
+void ServiceManager::Init()
+{
+ assert(manager == nullptr);
+ manager = new ServiceManager();
+}
+
+ServiceManager *ServiceManager::Get()
+{
+ return manager;
+}
+
+void ServiceManager::Destroy()
+{
+ delete manager;
+ manager = nullptr;
+}
+
+Service *ServiceManager::FindService(const Anope::string &name)
+{
+ for (Service *s : services)
+ if (s->GetName() == name)
+ return s;
+ return nullptr;
+}
+
+Service *ServiceManager::FindService(const Anope::string &type, const Anope::string &name)
+{
+ for (Service *s : services)
+ if (s->GetType() == type && s->GetName() == name)
+ return s;
+ return nullptr;
+}
+
+std::vector<Service *> ServiceManager::FindServices(const Anope::string &type)
+{
+ std::vector<Service *> v;
+
+ for (Service *s : services)
+ if (s->GetType() == type)
+ v.push_back(s);
+
+ return v;
+}
+
+void ServiceManager::Register(Service *service)
+{
+ // assert type
+ if (service->GetType().empty())
+ throw ModuleException("Service type must be non empty");
+
+ if (service->GetName().empty() == false)
+ {
+ Service *s = FindService(service->GetType(), service->GetName());
+
+ if (s != nullptr)
+ throw ModuleException("Service of type " + service->GetType() + " with name " + service->GetName() + " already exists");
+ }
+
+ Log(LOG_DEBUG_2) << "Service registered: " << service->GetType() << " " << service->GetName() << " address " << static_cast<void *>(this) << " by " << service->GetOwner();
+
+ services.push_back(service);
+
+ LookupAll();
+}
+
+void ServiceManager::Unregister(Service *service)
+{
+ Log(LOG_DEBUG_2) << "Service unregistered: " << service->GetType() << " " << service->GetName() << " address " << static_cast<void *>(service) << " by " << service->GetOwner();
+
+ auto it = std::find(services.begin(), services.end(), service);
+ if (it != services.end())
+ {
+ services.erase(it);
+
+ LookupAll();
+ }
+}
+
+void ServiceManager::Lookup(ServiceReferenceBase *reference)
+{
+ if (reference->GetName().empty())
+ {
+ std::vector<Service *> services = this->FindServices(reference->GetType());
+ Log(LOG_DEBUG_2) << "Service lookup " << static_cast<void *>(reference) << " type " << reference->GetType() << " name " << reference->GetName() << ": " << services.size() << " services";
+ reference->SetServices(services);
+ }
+ else
+ {
+ Service *service = this->FindService(reference->GetType(), reference->GetName());
+ Log(LOG_DEBUG_2) << "Service lookup " << static_cast<void *>(reference) << " type " << reference->GetType() << " name " << reference->GetName() << ": " << service;
+ reference->SetService(service);
+ }
+}
+
+void ServiceManager::LookupAll()
+{
+ for (ServiceReferenceBase *s : references)
+ Lookup(s);
+}
+
+void ServiceManager::RegisterReference(ServiceReferenceBase *reference)
+{
+ Lookup(reference);
+ this->references.push_back(reference);
+}
+
+void ServiceManager::UnregisterReference(ServiceReferenceBase *reference)
+{
+ auto it = std::find(this->references.begin(), this->references.end(), reference);
+ if (it != this->references.end())
+ this->references.erase(it);
+}
diff --git a/src/socket_clients.cpp b/src/socket_clients.cpp
index bb0618f31..278ba7c21 100644
--- a/src/socket_clients.cpp
+++ b/src/socket_clients.cpp
@@ -1,12 +1,20 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2011-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
diff --git a/src/socket_transport.cpp b/src/socket_transport.cpp
index 070807264..2ffeadd03 100644
--- a/src/socket_transport.cpp
+++ b/src/socket_transport.cpp
@@ -1,12 +1,20 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2011-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -32,7 +40,7 @@ bool BufferedSocket::ProcessRead()
return false;
if (len < 0)
return SocketEngine::IgnoreErrno();
-
+
tbuffer[len] = 0;
this->read_buffer.append(tbuffer);
this->recv_len = len;
@@ -130,7 +138,7 @@ bool BinarySocket::ProcessRead()
int len = this->io->Recv(this, tbuffer, sizeof(tbuffer));
if (len <= 0)
return false;
-
+
return this->Read(tbuffer, len);
}
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp
index f132ba2b9..3c0c22f40 100644
--- a/src/socketengines/socketengine_epoll.cpp
+++ b/src/socketengines/socketengine_epoll.cpp
@@ -1,6 +1,6 @@
/*
*
- * (C) 2003-2016 Anope Team
+ * (C) 2003-2014 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
@@ -28,7 +28,7 @@ void SocketEngine::Init()
if (EngineHandle == -1)
throw SocketException("Could not initialize epoll socket engine: " + Anope::LastError());
-
+
events.resize(DefaultSize);
}
@@ -46,7 +46,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
bool before_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE];
s->flags[flag] = set;
-
+
bool now_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE];
epoll_event ev;
@@ -65,7 +65,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
mod = EPOLL_CTL_MOD;
else
return;
-
+
if (epoll_ctl(EngineHandle, mod, ev.data.fd, &ev) == -1)
throw SocketException("Unable to epoll_ctl() fd " + stringify(ev.data.fd) + " to epoll: " + Anope::LastError());
}
diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp
index 9ccf128d5..5c5c99afe 100644
--- a/src/socketengines/socketengine_kqueue.cpp
+++ b/src/socketengines/socketengine_kqueue.cpp
@@ -1,6 +1,6 @@
/*
*
- * (C) 2003-2016 Anope Team
+ * (C) 2003-2014 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
@@ -39,7 +39,7 @@ void SocketEngine::Init()
if (kq_fd < 0)
throw SocketException("Unable to create kqueue engine: " + Anope::LastError());
-
+
change_events.resize(DefaultSize);
event_events.resize(DefaultSize);
}
@@ -56,7 +56,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
return;
s->flags[flag] = set;
-
+
int mod;
if (flag == SF_READABLE)
mod = EVFILT_READ;
diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp
index 8475dd414..422959df2 100644
--- a/src/socketengines/socketengine_poll.cpp
+++ b/src/socketengines/socketengine_poll.cpp
@@ -1,6 +1,6 @@
/*
*
- * (C) 2003-2016 Anope Team
+ * (C) 2003-2014 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
@@ -113,7 +113,7 @@ void SocketEngine::Process()
for (unsigned i = 0, processed = 0; i < events.size() && processed != static_cast<unsigned>(total); ++i)
{
pollfd *ev = &events[i];
-
+
if (ev->revents != 0)
++processed;
diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp
index 86b2085ea..f1f4fb8d8 100644
--- a/src/socketengines/socketengine_select.cpp
+++ b/src/socketengines/socketengine_select.cpp
@@ -1,6 +1,6 @@
/*
*
- * (C) 2003-2016 Anope Team
+ * (C) 2003-2014 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
@@ -46,7 +46,7 @@ void SocketEngine::Change(Socket *s, bool set, SocketFlag flag)
bool before_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE];
s->flags[flag] = set;
-
+
bool now_registered = s->flags[SF_READABLE] || s->flags[SF_WRITABLE];
if (!before_registered && now_registered)
diff --git a/src/sockets.cpp b/src/sockets.cpp
index f15f0ccbd..70c9fef0d 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -1,12 +1,20 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2010-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -282,7 +290,7 @@ bool cidr::operator<(const cidr &other) const
{
if (this->addr.sa.sa_family != other.addr.sa.sa_family)
return this->addr.sa.sa_family < other.addr.sa.sa_family;
-
+
switch (this->addr.sa.sa_family)
{
case AF_INET:
diff --git a/src/threadengine.cpp b/src/threadengine.cpp
index f392ac472..bfd7605c3 100644
--- a/src/threadengine.cpp
+++ b/src/threadengine.cpp
@@ -1,48 +1,26 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2010-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "threadengine.h"
#include "anope.h"
-
-#ifndef _WIN32
-#include <pthread.h>
-#endif
-
-static inline pthread_attr_t *get_engine_attr()
-{
- /* Threadengine attributes used by this thread engine */
- static pthread_attr_t attr;
- static bool inited = false;
-
- if (inited == false)
- {
- if (pthread_attr_init(&attr))
- throw CoreException("Error calling pthread_attr_init");
- if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE))
- throw CoreException("Unable to mark threads as joinable");
- inited = true;
- }
-
- return &attr;
-}
-
-static void *entry_point(void *parameter)
-{
- Thread *thread = static_cast<Thread *>(parameter);
- thread->Run();
- thread->SetExitState();
- pthread_exit(0);
- return NULL;
-}
+#include <system_error>
Thread::Thread() : exit(false)
{
@@ -55,7 +33,15 @@ Thread::~Thread()
void Thread::Join()
{
this->SetExitState();
- pthread_join(handle, NULL);
+ try
+ {
+ if (this->handle.joinable())
+ this->handle.join();
+ }
+ catch (const std::system_error &error)
+ {
+ throw CoreException("Unable to join thread: " + Anope::string(error.what()));
+ }
}
void Thread::SetExitState()
@@ -64,18 +50,28 @@ void Thread::SetExitState()
exit = true;
}
-void Thread::Exit()
-{
- this->SetExitState();
- pthread_exit(0);
-}
-
void Thread::Start()
{
- if (pthread_create(&this->handle, get_engine_attr(), entry_point, this))
+ try
+ {
+ this->handle = std::thread([this]()
+ {
+ try
+ {
+ this->Run();
+ }
+ catch (...)
+ {
+ this->SetExitState();
+ throw;
+ }
+ this->SetExitState();
+ });
+ }
+ catch (const std::system_error &error)
{
this->flags[SF_DEAD] = true;
- throw CoreException("Unable to create thread: " + Anope::LastError());
+ throw CoreException("Unable to create thread: " + Anope::string(error.what()));
}
}
@@ -90,47 +86,28 @@ void Thread::OnNotify()
this->flags[SF_DEAD] = true;
}
-Mutex::Mutex()
-{
- pthread_mutex_init(&mutex, NULL);
-}
-
-Mutex::~Mutex()
-{
- pthread_mutex_destroy(&mutex);
-}
-
void Mutex::Lock()
{
- pthread_mutex_lock(&mutex);
-}
-
-void Mutex::Unlock()
-{
- pthread_mutex_unlock(&mutex);
+ this->m.lock();
}
bool Mutex::TryLock()
{
- return pthread_mutex_trylock(&mutex) == 0;
+ return this->m.try_lock();
}
-Condition::Condition() : Mutex()
+void Mutex::Unlock()
{
- pthread_cond_init(&cond, NULL);
+ this->m.unlock();
}
-Condition::~Condition()
+void Condition::Wait()
{
- pthread_cond_destroy(&cond);
+ this->cv.wait(this->m);
}
void Condition::Wakeup()
{
- pthread_cond_signal(&cond);
+ this->cv.notify_one();
}
-void Condition::Wait()
-{
- pthread_cond_wait(&cond, &mutex);
-}
diff --git a/src/timers.cpp b/src/timers.cpp
index a4538c05d..dd32a9395 100644
--- a/src/timers.cpp
+++ b/src/timers.cpp
@@ -1,9 +1,20 @@
-/* Timer stuff.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2009-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt
index ef2f3b15b..4d64f6fd9 100644
--- a/src/tools/CMakeLists.txt
+++ b/src/tools/CMakeLists.txt
@@ -1,6 +1,6 @@
# Find all the *.cpp files within the current source directory, and sort the list
file(GLOB TOOLS_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
-sort_list(TOOLS_SRCS)
+list(SORT TOOLS_SRCS)
# Set all the files to use C++ as well as set their compile flags
set_source_files_properties(${TOOLS_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}")
@@ -9,31 +9,19 @@ set_source_files_properties(${TOOLS_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS
foreach(SRC ${TOOLS_SRCS})
# Convert the source file extension to have no extension
string(REGEX REPLACE "\\.cpp$" "" EXE ${SRC})
- # Calculate the header file dependencies for the given source file
- calculate_depends(${SRC})
- # Only continue if this file isn't skipped
- if(NOT SKIP)
- # Generate the executable and set its linker flags, also set it to depend on the main Anope executable to be built beforehand
- add_executable(${EXE} ${SRC})
- set_target_properties(${EXE} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}")
- add_dependencies(${EXE} ${PROGRAM_NAME})
- # Only for Windows, set anopesmtp to require the wsock32 library
- if(WIN32 AND ${EXE} STREQUAL anopesmtp)
- target_link_libraries(${EXE} wsock32)
- endif(WIN32 AND ${EXE} STREQUAL anopesmtp)
- if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" AND ${EXE} STREQUAL anopesmtp)
- target_link_libraries(${EXE} socket nsl)
- endif(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS" AND ${EXE} STREQUAL anopesmtp)
- # Set the executable to be installed to the bin directory under the main directory
- install(TARGETS ${EXE}
- DESTINATION ${BIN_DIR}
- )
- # Add the executable to the list of files for CPack to ignore
- get_target_property(EXE_BINARY ${EXE} LOCATION)
- get_filename_component(EXE_BINARY ${EXE_BINARY} NAME)
- add_to_cpack_ignored_files("${EXE_BINARY}$" TRUE)
- endif(NOT SKIP)
-endforeach(SRC)
+ # Generate the executable and set its linker flags, also set it to depend on the main Anope executable to be built beforehand
+ add_executable(${EXE} ${SRC})
+ set_target_properties(${EXE} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}")
+ add_dependencies(${EXE} ${PROGRAM_NAME})
+ # Set the executable to be installed to the bin directory under the main directory
+ install(TARGETS ${EXE}
+ DESTINATION ${BIN_DIR}
+ )
+ # Add the executable to the list of files for CPack to ignore
+ get_target_property(EXE_BINARY ${EXE} LOCATION)
+ get_filename_component(EXE_BINARY ${EXE_BINARY} NAME)
+ add_to_cpack_ignored_files("${EXE_BINARY}$" TRUE)
+endforeach()
# If not on Windows, generate anoperc and install it along with mydbgen
if(NOT WIN32)
@@ -44,9 +32,9 @@ if(NOT WIN32)
install (PROGRAMS geoipupdate.sh
DESTINATION ${BIN_DIR}
)
-endif(NOT WIN32)
+endif()
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the tools directory
if(NOT WIN32 AND RUNGROUP)
install(CODE "execute_process(COMMAND ${CHMOD} 2770 \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/bin\")")
-endif(NOT WIN32 AND RUNGROUP)
+endif()
diff --git a/src/tools/anoperc.in b/src/tools/anoperc.in
index 2802e57e2..dce1e035e 100644
--- a/src/tools/anoperc.in
+++ b/src/tools/anoperc.in
@@ -2,7 +2,7 @@
#
# Configuration script for Services
#
-# (C) 2003-2016 Anope Team
+# (C) 2003-2014 Anope Team
# Contact us at team@anope.org
#
# Please read COPYING and README for further details.
@@ -14,8 +14,8 @@
-ANOPEPID="@INSTDIR@/data/services.pid"
-ANOPROG="@INSTDIR@/bin/services"
+ANOPEPID="@INSTDIR@/data/anope.pid"
+ANOPROG="@INSTDIR@/bin/anope"
LOG="@INSTDIR@/logs/"
ARCVERSION="2"
diff --git a/src/tools/anopesmtp.cpp b/src/tools/anopesmtp.cpp
deleted file mode 100644
index 392c6e627..000000000
--- a/src/tools/anopesmtp.cpp
+++ /dev/null
@@ -1,492 +0,0 @@
-/* smtp stuff handler for win32.
- *
- * (C) 2003-2016 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.
- *
- * Written by Dominick Meglio <codemastr@unrealircd.com>
- * *nix port by Trystan Scott Lee <trystan@nomadirc.net>
- */
-
-#include "sysconf.h"
-
-/* Some Linux boxes (or maybe glibc includes) require this for the
- * prototype of strsignal(). */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#include <string>
-#include <vector>
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <cerrno>
-#include <iostream>
-#include <fstream>
-
-#ifndef _WIN32
-# include <unistd.h>
-# include <netdb.h>
-# include <netinet/in.h>
-# include <sys/socket.h>
-# include <arpa/inet.h>
-# include <sys/time.h>
-#else
-# include <winsock.h>
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-#include <sys/types.h>
-
-#ifdef _AIX
-extern int strcasecmp(const char *, const char *);
-extern int strncasecmp(const char *, const char *, size_t);
-# if 0 /* These break on some AIX boxes (4.3.1 reported). */
-extern int socket(int, int, int);
-extern int connect(int, struct sockaddr *, int);
-# endif
-#endif /* _AIX */
-
-/* Some SUN fixs */
-#ifdef __sun
-/* Solaris specific code, types that do not exist in Solaris'
- * * sys/types.h
- * **/
-# ifndef INADDR_NONE
-# define INADDR_NONE (-1)
-# endif
-#endif
-
-#ifdef _WIN32
-typedef SOCKET ano_socket_t;
-#define ano_sockclose(fd) closesocket(fd)
-#define ano_sockread(fd, buf, len) recv(fd, buf, len, 0)
-#define ano_sockwrite(fd, buf, len) send(fd, buf, len, 0)
-#else
-typedef int ano_socket_t;
-#define ano_sockclose(fd) close(fd)
-#define ano_sockread(fd, buf, len) read(fd, buf, len)
-#define ano_sockwrite(fd, buf, len) write(fd, buf, len)
-#define SOCKET_ERROR -1
-#endif
-
-/* Data structures */
-struct smtp_message
-{
- std::vector<std::string> smtp_headers;
- std::vector<std::string> smtp_body;
- std::string from;
- std::string to;
- ano_socket_t sock;
-};
-
-int smtp_debug = 0;
-
-struct smtp_message smail;
-
-static std::string get_logname(struct tm *tm = NULL)
-{
- char timestamp[32];
-
- if (!tm)
- {
- time_t t = time(NULL);
- tm = localtime(&t);
- }
-
- strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
- std::string name = std::string("anopesmtp.") + timestamp;
- return name;
-}
-
-/* Log stuff to the log file with a datestamp. Note that errno is
- * preserved by this routine and log_perror().
- */
-
-void alog(const char *fmt, ...)
-{
- if (!smtp_debug || !fmt)
- return;
-
- std::fstream file;
- file.open(get_logname().c_str(), std::ios_base::out | std::ios_base::app);
-
- if (!file.is_open())
- return;
-
- va_list args;
- va_start(args, fmt);
-
- time_t t = time(NULL);
- struct tm *tm = localtime(&t);
-
- char buf[256];
- strftime(buf, sizeof(buf) - 1, "[%b %d %H:%M:%S %Y] ", tm);
- file << buf;
- vsnprintf(buf, sizeof(buf), fmt, args);
- file << buf << std::endl;
- va_end(args);
- va_end(args);
-
- file.close();
-}
-
-/* Remove a trailing \r\n */
-std::string strip(const std::string &buf)
-{
- std::string newbuf = buf;
- char c = newbuf[newbuf.size() - 1];
- while (c == '\n' || c == '\r')
- {
- newbuf.erase(newbuf.end() - 1);
- c = newbuf[newbuf.size() - 1];
- }
- return newbuf;
-}
-
-/* Is the buffer a header? */
-bool smtp_is_header(const std::string &buf)
-{
- size_t tmp = buf.find(' ');
-
- if (tmp == std::string::npos)
- return false;
-
- if (tmp > 0 && buf[tmp - 1] == ':')
- return true;
- return false;
-}
-
-/* Parse a header into a name and value */
-void smtp_parse_header(const std::string &buf, std::string &header, std::string &value)
-{
- std::string newbuf = strip(buf);
-
- size_t space = newbuf.find(' ');
- if (space != std::string::npos)
- {
- header = newbuf.substr(0, space);
- value = newbuf.substr(space + 1);
- }
- else
- {
- header = newbuf;
- value = "";
- }
-}
-
-/* Have we reached the end of input? */
-bool smtp_is_end(const std::string &buf)
-{
- if (buf[0] == '.')
- if (buf[1] == '\r' || buf[1] == '\n')
- return true;
-
- return false;
-}
-
-/* Set who the email is to */
-void smtp_set_to(const std::string &to)
-{
- smail.to = to;
- size_t c = smail.to.rfind('<');
- if (c != std::string::npos && c + 1 < smail.to.size())
- {
- smail.to = smail.to.substr(c + 1);
- smail.to.erase(smail.to.end() - 1);
- }
-}
-
-/* Establish a connection to the SMTP server */
-int smtp_connect(const char *host, unsigned short port)
-{
- struct sockaddr_in addr;
-
- if ((smail.sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
- return 0;
-
- if ((addr.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
- {
- struct hostent *hent;
- if (!(hent = gethostbyname(host)))
- return 0;
- memcpy(&addr.sin_addr, hent->h_addr, hent->h_length);
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port ? port : 25);
- if (connect(smail.sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(struct sockaddr_in)) == SOCKET_ERROR)
- {
- ano_sockclose(smail.sock);
- return 0;
- }
-
- return 1;
-}
-
-/* Send a line of text */
-int smtp_send(const char *text)
-{
- int result = ano_sockwrite(smail.sock, text, strlen(text));
-
- alog("SMTP: sent %s",text);
-
- if (result == SOCKET_ERROR)
- ano_sockclose(smail.sock);
-
- return result;
-}
-
-/* Read a line of text */
-int smtp_read(char *buf, int len)
-{
- int result;
-
- memset(buf, 0, len);
- result = ano_sockread(smail.sock, buf, len);
-
- if (result == SOCKET_ERROR)
- ano_sockclose(smail.sock);
-
- return result;
-}
-
-/* Retrieve a response code */
-int smtp_get_code(const std::string &text)
-{
- size_t tmp = text.find(' ');
-
- if (tmp == std::string::npos)
- return 0;
-
- return atol(text.substr(0, tmp).c_str());
-}
-
-/* Send the email */
-int smtp_send_email()
-{
- char buf[1024];
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- int code = smtp_get_code(buf);
- if (code != 220)
- {
- alog("SMTP: error expected code 220 got %d",code);
- return 0;
- }
-
- if (!smtp_send("HELO anope\r\n"))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (code != 250)
- {
- alog("SMTP: error expected code 250 got %d",code);
- return 0;
- }
-
- strcpy(buf, "MAIL FROM: <");
- strcat(buf, smail.from.c_str());
- strcat(buf, ">\r\n");
-
- if (!smtp_send(buf))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (code != 250)
- return 0;
-
- strcpy(buf, "RCPT TO: <");
- strcat(buf, smail.to.c_str());
- strcat(buf, ">\r\n");
-
- if (!smtp_send(buf))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (smtp_get_code(buf) != 250)
- {
- alog("SMTP: error expected code 250 got %d",code);
- return 0;
- }
-
- if (!smtp_send("DATA\r\n"))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
-
- if (!smtp_read(buf, 1024))
- {
- alog("SMTP: error reading buffer");
- return 0;
- }
-
- code = smtp_get_code(buf);
- if (code != 354)
- {
- alog("SMTP: error expected code 354 got %d",code);
- return 0;
- }
-
- for (std::vector<std::string>::const_iterator it = smail.smtp_headers.begin(), it_end = smail.smtp_headers.end(); it != it_end; ++it)
- if (!smtp_send(it->c_str()))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
-
- if (!smtp_send("\r\n"))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
-
- bool skip_done = false;
- for (std::vector<std::string>::const_iterator it = smail.smtp_body.begin(), it_end = smail.smtp_body.end(); it != it_end; ++it)
- if (skip_done)
- {
- if (!smtp_send(it->c_str()))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
- }
- else
- skip_done = true;
-
- if (!smtp_send("\r\n.\r\n"))
- {
- alog("SMTP: error writting to socket");
- return 0;
- }
-
- return 1;
-}
-
-void smtp_disconnect()
-{
- smtp_send("QUIT\r\n");
- ano_sockclose(smail.sock);
-}
-
-int main(int argc, char *argv[])
-{
- /* Win32 stuff */
-#ifdef _WIN32
- WSADATA wsa;
-#endif
-
- if (argc == 1)
- return 0;
-
- if (argc == 3 && !strcmp(argv[2], "--debug"))
- smtp_debug = 1;
-
- char *server = strtok(argv[1], ":"), *aport;
- short port;
- if ((aport = strtok(NULL, "")))
- port = atoi(aport);
- else
- port = 25;
-
- if (!server)
- {
- alog("No Server");
- /* Bad, bad, bad. This was a return from main with no value! -GD */
- return 0;
- }
- else
- alog("SMTP: server %s port %d",server,port);
-
- /* The WSAStartup function initiates use of WS2_32.DLL by a process. */
- /* guessing we can skip it under *nix */
-#ifdef _WIN32
- if (WSAStartup(MAKEWORD(1, 1), &wsa))
- return 0;
-#endif
-
- char buf[8192];
- bool headers_done = false;
- /* Read the message and parse it */
- while (fgets(buf, 8192, stdin))
- {
- if (smtp_is_header(buf) && !headers_done)
- {
- smail.smtp_headers.push_back(strip(buf) + "\r\n");
- std::string header, value;
- smtp_parse_header(buf, header, value);
- if (header == "From:")
- {
- alog("SMTP: from: %s", value.c_str());
- smail.from = value;
- }
- else if (header == "To:")
- {
- alog("SMTP: to: %s", value.c_str());
- smtp_set_to(value);
- }
- else if (smtp_is_end(buf))
- break;
- else
- {
- headers_done = true;
- smail.smtp_body.push_back(strip(buf) + "\r\n");
- }
- }
- else
- smail.smtp_body.push_back(strip(buf) + "\r\n");
- }
-
- if (!smtp_connect(server, port))
- {
- alog("SMTP: failed to connect to %s:%d", server, port);
- return 0;
- }
- if (!smtp_send_email())
- {
- alog("SMTP: error during sending of mail");
- return 0;
- }
- smtp_disconnect();
-
- return 1;
-}
diff --git a/src/uplink.cpp b/src/uplink.cpp
index df38f98f2..c2b7579c5 100644
--- a/src/uplink.cpp
+++ b/src/uplink.cpp
@@ -1,12 +1,20 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2012-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "uplink.h"
@@ -14,6 +22,10 @@
#include "config.h"
#include "protocol.h"
#include "servers.h"
+#include "event.h"
+#include "bots.h"
+#include "timers.h"
+#include "modules.h"
UplinkSocket *UplinkSock = NULL;
@@ -22,7 +34,7 @@ class ReconnectTimer : public Timer
public:
ReconnectTimer(int wait) : Timer(wait) { }
- void Tick(time_t)
+ void Tick(time_t) override
{
try
{
@@ -49,9 +61,9 @@ void Uplink::Connect()
Configuration::Uplink &u = Config->Uplinks[Anope::CurrentUplink];
new UplinkSocket();
- if (!Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost").empty())
- UplinkSock->Bind(Config->GetBlock("serverinfo")->Get<const Anope::string>("localhost"));
- FOREACH_MOD(OnPreServerConnect, ());
+ if (!Config->GetBlock("serverinfo")->Get<Anope::string>("localhost").empty())
+ UplinkSock->Bind(Config->GetBlock("serverinfo")->Get<Anope::string>("localhost"));
+ EventManager::Get()->Dispatch(&Event::PreServerConnect::OnPreServerConnect);
Anope::string ip = Anope::Resolve(u.host, u.ipv6 ? AF_INET6 : AF_INET);
Log(LOG_TERMINAL) << "Attempting to connect to uplink #" << (Anope::CurrentUplink + 1) << " " << u.host << " (" << ip << "), port " << u.port;
UplinkSock->Connect(ip, u.port);
@@ -77,7 +89,7 @@ UplinkSocket::~UplinkSocket()
if (IRCD && Servers::GetUplink() && Servers::GetUplink()->IsSynced())
{
- FOREACH_MOD(OnServerDisconnect, ());
+ EventManager::Get()->Dispatch(&Event::ServerDisconnect::OnServerDisconnect);
for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
{
@@ -87,7 +99,7 @@ UplinkSocket::~UplinkSocket()
{
/* Don't use quitmsg here, it may contain information you don't want people to see */
IRCD->SendQuit(u, "Shutting down");
- BotInfo* bi = BotInfo::Find(u->GetUID());
+ ServiceBot* bi = ServiceBot::Find(u->GetUID());
if (bi != NULL)
bi->introduced = false;
}
@@ -144,7 +156,7 @@ void UplinkSocket::OnConnect()
{
Log(LOG_TERMINAL) << "Successfully connected to uplink #" << (Anope::CurrentUplink + 1) << " " << Config->Uplinks[Anope::CurrentUplink].host << ":" << Config->Uplinks[Anope::CurrentUplink].port;
IRCD->SendConnect();
- FOREACH_MOD(OnServerConnect, ());
+ EventManager::Get()->Dispatch(&Event::ServerConnect::OnServerConnect);
}
void UplinkSocket::OnError(const Anope::string &err)
@@ -154,60 +166,45 @@ void UplinkSocket::OnError(const Anope::string &err)
error |= !err.empty();
}
-UplinkSocket::Message::Message() : source(Me)
-{
-}
-
-UplinkSocket::Message::Message(const MessageSource &src) : source(src)
-{
-}
-
-UplinkSocket::Message::~Message()
+void Uplink::SendMessage(IRCMessage &message)
{
- Anope::string message_source;
+ const MessageSource &source = message.GetSource();
+ Anope::string buffer = IRCD->Format(message);
- if (this->source.GetServer() != NULL)
+ if (source.GetServer() != NULL)
{
- const Server *s = this->source.GetServer();
+ const Server *s = source.GetServer();
if (s != Me && !s->IsJuped())
{
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << s->GetName() << " who is not from me?";
+ Log(LOG_DEBUG) << "Attempted to send \"" << buffer << "\" from " << s->GetName() << " who is not from me?";
return;
}
-
- message_source = s->GetSID();
}
- else if (this->source.GetUser() != NULL)
+ else if (source.GetUser() != NULL)
{
- const User *u = this->source.GetUser();
+ const User *u = source.GetUser();
if (u->server != Me && !u->server->IsJuped())
{
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << u->nick << " who is not from me?";
+ Log(LOG_DEBUG) << "Attempted to send \"" << buffer << "\" from " << u->nick << " who is not from me?";
return;
}
- const BotInfo *bi = this->source.GetBot();
+ const ServiceBot *bi = source.GetBot();
if (bi != NULL && bi->introduced == false)
{
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" from " << bi->nick << " when not introduced";
+ Log(LOG_DEBUG) << "Attempted to send \"" << buffer << "\" from " << bi->nick << " when not introduced";
return;
}
-
- message_source = u->GetUID();
}
if (!UplinkSock)
{
- if (!message_source.empty())
- Log(LOG_DEBUG) << "Attempted to send \"" << message_source << " " << this->buffer.str() << "\" with UplinkSock NULL";
- else
- Log(LOG_DEBUG) << "Attempted to send \"" << this->buffer.str() << "\" with UplinkSock NULL";
+ Log(LOG_DEBUG) << "Attempted to send \"" << buffer << "\" with UplinkSock NULL";
return;
}
- Anope::string sent = IRCD->Format(message_source, this->buffer.str());
- UplinkSock->Write(sent);
- Log(LOG_RAWIO) << "Sent: " << sent;
+ UplinkSock->Write(buffer);
+ Log(LOG_RAWIO) << "Sent: " << buffer;
}
diff --git a/src/users.cpp b/src/users.cpp
index 264f5ceba..3d4b7e1b7 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -1,18 +1,25 @@
-/* Routines to maintain a list of online users.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
#include "modules.h"
#include "users.h"
-#include "account.h"
#include "protocol.h"
#include "servers.h"
#include "channels.h"
@@ -22,16 +29,17 @@
#include "language.h"
#include "sockets.h"
#include "uplink.h"
+#include "event.h"
+#include "modules/nickserv.h"
-user_map UserListByNick, UserListByUID;
+user_map UserListByNick;
+uid_map UserListByUID;
int OperCount = 0;
-unsigned MaxUserCount = 0;
-time_t MaxUserTime = 0;
std::list<User *> User::quitting_users;
-User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *account) : ip(uip)
+User::User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &uip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickServ::Account *account) : ip(uip)
{
if (snick.empty() || sident.empty() || shost.empty())
throw CoreException("Bad args passed to User::User");
@@ -53,7 +61,6 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
this->SetModesInternal(sserver, "%s", smodes.c_str());
this->uid = suid;
this->super_admin = false;
- this->nc = NULL;
size_t old = UserListByNick.size();
UserListByNick[snick] = this;
@@ -72,18 +79,10 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope:
Log(this, "connect") << (!vhost.empty() && vhost != host ? "(" + vhost + ") " : "") << "(" << srealname << ") " << (!uip.empty() && uip != host ? "[" + uip + "] " : "") << "connected to the network (" << sserver->GetName() << ")";
}
- if (UserListByNick.size() > MaxUserCount)
- {
- MaxUserCount = UserListByNick.size();
- MaxUserTime = Anope::CurTime;
- if (sserver && sserver->IsSynced())
- Log(this, "maxusers") << "connected - new maximum user count: " << UserListByNick.size();
- }
-
bool exempt = false;
if (server && server->IsULined())
exempt = true;
- FOREACH_MOD(OnUserConnect, (this, exempt));
+ EventManager::Get()->Dispatch(&Event::UserConnect::OnUserConnect, this, exempt);
}
static void CollideKill(User *target, const Anope::string &reason)
@@ -96,7 +95,7 @@ static void CollideKill(User *target, const Anope::string &reason)
IRCD->SendQuit(target, "%s", reason.c_str());
// Reintroduce my client
- if (BotInfo *bi = dynamic_cast<BotInfo *>(target))
+ if (ServiceBot *bi = dynamic_cast<ServiceBot *>(target))
bi->OnKill();
else
target->Quit(reason);
@@ -111,7 +110,7 @@ static void Collide(User *u, const Anope::string &id, const Anope::string &type)
CollideKill(u, type);
}
-User* User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickCore *nc)
+User* User::OnIntroduce(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &svhost, const Anope::string &sip, Server *sserver, const Anope::string &srealname, time_t ts, const Anope::string &smodes, const Anope::string &suid, NickServ::Account *nc)
{
// How IRCds handle collisions varies a lot, for safety well just always kill both sides
// With properly set qlines, this can almost never happen anyway
@@ -141,7 +140,7 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts)
/* Sanity check to make sure we don't segfault */
if (newnick.empty())
throw CoreException("User::ChangeNick() got a bad argument");
-
+
this->super_admin = false;
Log(this, "nick") << "(" << this->realname << ") changed nick to " << newnick;
@@ -152,10 +151,10 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts)
this->nick = newnick;
else
{
- NickAlias *old_na = NickAlias::Find(this->nick);
+ NickServ::Nick *old_na = NickServ::FindNick(this->nick);
if (old_na && (this->IsIdentified(true) || this->IsRecognized()))
- old_na->last_seen = Anope::CurTime;
-
+ old_na->SetLastSeen(Anope::CurTime);
+
UserListByNick.erase(this->nick);
this->nick = newnick;
@@ -170,18 +169,23 @@ void User::ChangeNick(const Anope::string &newnick, time_t ts)
other = this;
on_access = false;
- NickAlias *na = NickAlias::Find(this->nick);
- if (na)
- on_access = na->nc->IsOnAccess(this);
-
- if (na && na->nc == this->Account())
+ if (NickServ::service)
{
- na->last_seen = Anope::CurTime;
- this->UpdateHost();
+ NickServ::Nick *na = NickServ::service->FindNick(this->nick);
+ if (na)
+ {
+ on_access = na->GetAccount()->IsOnAccess(this);
+
+ if (na->GetAccount() == this->Account())
+ {
+ na->SetLastSeen(Anope::CurTime);
+ this->UpdateHost();
+ }
+ }
}
}
- FOREACH_MOD(OnUserNickChange, (this, old));
+ EventManager::Get()->Dispatch(&Event::UserNickChange::OnUserNickChange, this, old);
}
void User::SetDisplayedHost(const Anope::string &shost)
@@ -193,7 +197,7 @@ void User::SetDisplayedHost(const Anope::string &shost)
Log(this, "host") << "changed vhost to " << shost;
- FOREACH_MOD(OnSetDisplayedHost, (this));
+ EventManager::Get()->Dispatch(&Event::SetDisplayedHost::OnSetDisplayedHost, this);
this->UpdateHost();
}
@@ -280,18 +284,18 @@ void User::SetRealname(const Anope::string &srealname)
throw CoreException("realname empty in SetRealname");
this->realname = srealname;
- NickAlias *na = NickAlias::Find(this->nick);
+
+ //XXX event
+ NickServ::Nick *na = NickServ::FindNick(this->nick);
if (na && (this->IsIdentified(true) || this->IsRecognized()))
- na->last_realname = srealname;
+ na->SetLastRealname(srealname);
Log(this, "realname") << "changed realname to " << srealname;
}
User::~User()
{
- UnsetExtensibles();
-
if (this->server != NULL)
{
if (this->server->IsSynced())
@@ -299,7 +303,7 @@ User::~User()
--this->server->users;
}
- FOREACH_MOD(OnPreUserLogoff, (this));
+ EventManager::Get()->Dispatch(&Event::PreUserLogoff::OnPreUserLogoff, this);
ModeManager::StackerDel(this);
this->Logout();
@@ -314,25 +318,10 @@ User::~User()
if (!this->uid.empty())
UserListByUID.erase(this->uid);
- FOREACH_MOD(OnPostUserLogoff, (this));
+ EventManager::Get()->Dispatch(&Event::PostUserLogoff::OnPostUserLogoff, this);
}
-void User::SendMessage(BotInfo *source, const char *fmt, ...)
-{
- va_list args;
- char buf[BUFSIZE] = "";
-
- const char *translated_message = Language::Translate(this, fmt);
-
- va_start(args, fmt);
- vsnprintf(buf, BUFSIZE - 1, translated_message, args);
-
- this->SendMessage(source, Anope::string(buf));
-
- va_end(args);
-}
-
-void User::SendMessage(BotInfo *source, const Anope::string &msg)
+void User::SendMessage(const MessageSource &source, const Anope::string &msg)
{
const char *translated_message = Language::Translate(this, msg.c_str());
@@ -341,54 +330,77 @@ void User::SendMessage(BotInfo *source, const Anope::string &msg)
* - The user is not registered and NSDefMsg is enabled
* - The user is registered and has set /ns set msg on
*/
- bool send_privmsg = Config->UsePrivmsg && ((!this->nc && Config->DefPrivmsg) || (this->nc && this->nc->HasExt("MSG")));
+ bool send_privmsg = Config->UsePrivmsg && ((!this->nc && Config->DefPrivmsg) || (this->nc && this->nc->HasFieldS("MSG")));
sepstream sep(translated_message, '\n', true);
for (Anope::string tok; sep.GetToken(tok);)
{
- if (send_privmsg)
- IRCD->SendPrivmsg(source, this->GetUID(), "%s", tok.c_str());
- else
- IRCD->SendNotice(source, this->GetUID(), "%s", tok.c_str());
+ if (tok.empty())
+ tok = " ";
+ spacesepstream ssep(tok, true);
+ Anope::string buf;
+ for (Anope::string word; ssep.GetToken(word);)
+ {
+ Anope::string add = buf.empty() ? word : " " + word;
+ if (buf.length() + add.length() > Config->LineWrap)
+ {
+ if (send_privmsg)
+ IRCD->SendPrivmsg(source, this->GetUID(), "%s", buf.c_str());
+ else
+ IRCD->SendNotice(source, this->GetUID(), "%s", buf.c_str());
+ buf.clear();
+ add = word;
+ }
+ buf.append(add);
+ }
+
+ if (!buf.empty())
+ {
+ if (send_privmsg)
+ IRCD->SendPrivmsg(source, this->GetUID(), "%s", buf.c_str());
+ else
+ IRCD->SendNotice(source, this->GetUID(), "%s", buf.c_str());
+ }
}
}
-void User::Identify(NickAlias *na)
+void User::Identify(NickServ::Nick *na)
{
- if (this->nick.equals_ci(na->nick))
+ if (this->nick.equals_ci(na->GetNick()))
{
- na->last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost();
- na->last_realhost = this->GetIdent() + "@" + this->host;
- na->last_realname = this->realname;
- na->last_seen = Anope::CurTime;
+ na->SetLastUsermask(this->GetIdent() + "@" + this->GetDisplayedHost());
+ na->SetLastRealhost(this->GetIdent() + "@" + this->host);
+ na->SetLastRealname(this->realname);
+ na->SetLastSeen(Anope::CurTime);
}
IRCD->SendLogin(this, na);
- this->Login(na->nc);
+ this->Login(na->GetAccount());
- FOREACH_MOD(OnNickIdentify, (this));
+ EventManager::Get()->Dispatch(&Event::NickIdentify::OnNickIdentify, this);
if (this->IsServicesOper())
{
- if (!this->nc->o->ot->modes.empty())
+ Anope::string m = this->nc->o->GetType()->modes;
+ if (!m.empty())
{
- this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str());
- this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str());
+ this->SetModes(NULL, "%s", m.c_str());
+ this->SendMessage(Me, "Changing your usermodes to \002{0}\002", m.c_str());
UserMode *um = ModeManager::FindUserModeByName("OPER");
- if (um && !this->HasMode("OPER") && this->nc->o->ot->modes.find(um->mchar) != Anope::string::npos)
+ if (um && !this->HasMode("OPER") && m.find(um->mchar) != Anope::string::npos)
IRCD->SendOper(this);
}
- if (IRCD->CanSetVHost && !this->nc->o->vhost.empty())
+ if (IRCD->CanSetVHost && !this->nc->o->GetVhost().empty())
{
- this->SendMessage(NULL, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str());
- this->SetDisplayedHost(this->nc->o->vhost);
- IRCD->SendVhost(this, "", this->nc->o->vhost);
+ this->SendMessage(Me, "Changing your vhost to \002{0}\002", this->nc->o->GetVhost());
+ this->SetDisplayedHost(this->nc->o->GetVhost());
+ IRCD->SendVhost(this, "", this->nc->o->GetVhost());
}
}
}
-void User::Login(NickCore *core)
+void User::Login(NickServ::Account *core)
{
if (!core || core == this->nc)
return;
@@ -400,26 +412,26 @@ void User::Login(NickCore *core)
this->UpdateHost();
if (this->server->IsSynced())
- Log(this, "account") << "is now identified as " << this->nc->display;
-
- FOREACH_MOD(OnUserLogin, (this));
+ Log(this, "account") << "is now identified as " << this->nc->GetDisplay();
+
+ EventManager::Get()->Dispatch(&Event::UserLogin::OnUserLogin, this);
}
void User::Logout()
{
if (!this->nc)
return;
-
- Log(this, "account") << "is no longer identified as " << this->nc->display;
- std::list<User *>::iterator it = std::find(this->nc->users.begin(), this->nc->users.end(), this);
+ Log(this, "account") << "is no longer identified as " << this->nc->GetDisplay();
+
+ auto it = std::find(this->nc->users.begin(), this->nc->users.end(), this);
if (it != this->nc->users.end())
this->nc->users.erase(it);
this->nc = NULL;
}
-NickCore *User::Account() const
+NickServ::Account *User::Account() const
{
return this->nc;
}
@@ -428,8 +440,8 @@ bool User::IsIdentified(bool check_nick) const
{
if (check_nick && this->nc)
{
- NickAlias *na = NickAlias::Find(this->nick);
- return na && *na->nc == *this->nc;
+ NickServ::Nick *na = NickServ::FindNick(nick);
+ return na && na->GetAccount() == *this->nc;
}
return this->nc ? true : false;
@@ -439,9 +451,9 @@ bool User::IsRecognized(bool check_secure) const
{
if (check_secure && on_access)
{
- const NickAlias *na = NickAlias::Find(this->nick);
+ NickServ::Nick *na = NickServ::FindNick(nick);
- if (!na || na->nc->HasExt("NS_SECURE"))
+ if (!na || na->GetAccount()->HasFieldS("NS_SECURE"))
return false;
}
@@ -453,24 +465,27 @@ bool User::IsServicesOper()
if (!this->nc || !this->nc->IsServicesOper())
// No opertype.
return false;
- else if (this->nc->o->require_oper && !this->HasMode("OPER"))
+ else if (this->nc->o->GetRequireOper() && !this->HasMode("OPER"))
return false;
- else if (!this->nc->o->certfp.empty() && this->fingerprint != this->nc->o->certfp)
+ else if (!this->nc->o->GetCertFP().empty() && this->fingerprint != this->nc->o->GetCertFP())
// Certfp mismatch
return false;
- else if (!this->nc->o->hosts.empty())
+ else if (!this->nc->o->GetHost().empty())
{
+ std::vector<Anope::string> hosts;
+ spacesepstream(this->nc->o->GetHost()).GetTokens(hosts);
+
bool match = false;
Anope::string match_host = this->GetIdent() + "@" + this->host;
- for (unsigned i = 0; i < this->nc->o->hosts.size(); ++i)
- if (Anope::Match(match_host, this->nc->o->hosts[i]))
+ for (Anope::string h : hosts)
+ if (Anope::Match(match_host, h))
match = true;
if (match == false)
return false;
}
EventReturn MOD_RESULT;
- FOREACH_RESULT(IsServicesOper, MOD_RESULT, (this));
+ MOD_RESULT = EventManager::Get()->Dispatch(&Event::IsServicesOperEvent::IsServicesOper, this);
if (MOD_RESULT == EVENT_STOP)
return false;
@@ -480,14 +495,14 @@ bool User::IsServicesOper()
bool User::HasCommand(const Anope::string &command)
{
if (this->IsServicesOper())
- return this->nc->o->ot->HasCommand(command);
+ return this->nc->o->GetType()->HasCommand(command);
return false;
}
bool User::HasPriv(const Anope::string &priv)
{
if (this->IsServicesOper())
- return this->nc->o->ot->HasPriv(priv);
+ return this->nc->o->GetType()->HasPriv(priv);
return false;
}
@@ -496,19 +511,20 @@ void User::UpdateHost()
if (this->host.empty())
return;
- NickAlias *na = NickAlias::Find(this->nick);
+ //XXX event
+ NickServ::Nick *na = NickServ::FindNick(this->nick);
on_access = false;
if (na)
- on_access = na->nc->IsOnAccess(this);
+ on_access = na->GetAccount()->IsOnAccess(this);
if (na && (this->IsIdentified(true) || this->IsRecognized()))
{
Anope::string last_usermask = this->GetIdent() + "@" + this->GetDisplayedHost();
Anope::string last_realhost = this->GetIdent() + "@" + this->host;
- na->last_usermask = last_usermask;
- na->last_realhost = last_realhost;
+ na->SetLastUsermask(last_usermask);
+ na->SetLastRealhost(last_realhost);
// This is called on signon, and if users are introduced with an account it won't update
- na->last_realname = this->realname;
+ na->SetLastRealname(this->realname);
}
}
@@ -530,19 +546,20 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop
if (this->IsServicesOper())
{
- if (!this->nc->o->ot->modes.empty())
+ Anope::string m = this->nc->o->GetType()->modes;
+ if (!m.empty())
{
- this->SetModes(NULL, "%s", this->nc->o->ot->modes.c_str());
- this->SendMessage(NULL, "Changing your usermodes to \002%s\002", this->nc->o->ot->modes.c_str());
+ this->SetModes(NULL, "%s", m.c_str());
+ this->SendMessage(Me, "Changing your usermodes to \002{0}\002", m);
UserMode *oper = ModeManager::FindUserModeByName("OPER");
- if (oper && !this->HasMode("OPER") && this->nc->o->ot->modes.find(oper->mchar) != Anope::string::npos)
+ if (oper && !this->HasMode("OPER") && m.find(oper->mchar) != Anope::string::npos)
IRCD->SendOper(this);
}
- if (IRCD->CanSetVHost && !this->nc->o->vhost.empty())
+ if (IRCD->CanSetVHost && !this->nc->o->GetVhost().empty())
{
- this->SendMessage(NULL, "Changing your vhost to \002%s\002", this->nc->o->vhost.c_str());
- this->SetDisplayedHost(this->nc->o->vhost);
- IRCD->SendVhost(this, "", this->nc->o->vhost);
+ this->SendMessage(Me, "Changing your vhost to \002{0}\002", this->nc->o->GetVhost());
+ this->SetDisplayedHost(this->nc->o->GetVhost());
+ IRCD->SendVhost(this, "", this->nc->o->GetVhost());
}
}
}
@@ -550,7 +567,7 @@ void User::SetModeInternal(const MessageSource &source, UserMode *um, const Anop
if (um->name == "CLOAK" || um->name == "VHOST")
this->UpdateHost();
- FOREACH_MOD(OnUserModeSet, (source, this, um->name));
+ EventManager::Get()->Dispatch(&Event::UserModeSet::OnUserModeSet, source, this, um->name);
}
void User::RemoveModeInternal(const MessageSource &source, UserMode *um)
@@ -569,10 +586,10 @@ void User::RemoveModeInternal(const MessageSource &source, UserMode *um)
this->UpdateHost();
}
- FOREACH_MOD(OnUserModeUnset, (source, this, um->name));
+ EventManager::Get()->Dispatch(&Event::UserModeUnset::OnUserModeUnset, source, this, um->name);
}
-void User::SetMode(BotInfo *bi, UserMode *um, const Anope::string &param)
+void User::SetMode(ServiceBot *bi, UserMode *um, const Anope::string &param)
{
if (!um || HasMode(um->name))
return;
@@ -581,12 +598,12 @@ void User::SetMode(BotInfo *bi, UserMode *um, const Anope::string &param)
SetModeInternal(bi, um, param);
}
-void User::SetMode(BotInfo *bi, const Anope::string &uname, const Anope::string &param)
+void User::SetMode(ServiceBot *bi, const Anope::string &uname, const Anope::string &param)
{
SetMode(bi, ModeManager::FindUserModeByName(uname), param);
}
-void User::RemoveMode(BotInfo *bi, UserMode *um, const Anope::string &param)
+void User::RemoveMode(ServiceBot *bi, UserMode *um, const Anope::string &param)
{
if (!um || !HasMode(um->name))
return;
@@ -595,12 +612,12 @@ void User::RemoveMode(BotInfo *bi, UserMode *um, const Anope::string &param)
RemoveModeInternal(bi, um);
}
-void User::RemoveMode(BotInfo *bi, const Anope::string &name, const Anope::string &param)
+void User::RemoveMode(ServiceBot *bi, const Anope::string &name, const Anope::string &param)
{
RemoveMode(bi, ModeManager::FindUserModeByName(name), param);
}
-void User::SetModes(BotInfo *bi, const char *umodes, ...)
+void User::SetModes(ServiceBot *bi, const char *umodes, ...)
{
char buf[BUFSIZE] = "";
va_list args;
@@ -756,7 +773,7 @@ void User::Quit(const Anope::string &reason)
return;
}
- FOREACH_MOD(OnUserQuit, (this, reason));
+ EventManager::Get()->Dispatch(&Event::UserQuit::OnUserQuit, this, reason);
this->quit = true;
quitting_users.push_back(this);
@@ -818,7 +835,7 @@ User* User::Find(const Anope::string &name, bool nick_only)
{
if (!nick_only && IRCD->RequiresID)
{
- user_map::iterator it = UserListByUID.find(name);
+ uid_map::iterator it = UserListByUID.find(name);
if (it != UserListByUID.end())
return it->second;
diff --git a/src/version.sh b/src/version.sh
index ef928b914..db1881df3 100644
--- a/src/version.sh
+++ b/src/version.sh
@@ -1,7 +1,7 @@
#!/bin/sh
VERSION_MAJOR=2
-VERSION_MINOR=0
-VERSION_PATCH=4
-VERSION_EXTRA="-git"
+VERSION_MINOR=1
+VERSION_PATCH=0
+VERSION_EXTRA="-exploding-tacos"
diff --git a/src/win32/Config.cs b/src/win32/Config.cs
deleted file mode 100644
index d7c9661ec..000000000
--- a/src/win32/Config.cs
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Config.cs - Windows Configuration
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * This program is free but copyrighted software; see the file COPYING for
- * details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- *
- * Written by Scott <stealtharcher.scott@gmail.com>
- * Written by Adam <Adam@anope.org>
- * Cleaned up by Naram Qashat <cyberbotx@anope.org>
- *
- * Compile with: csc /out:../../Config.exe /win32icon:anope-icon.ico Config.cs
- */
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Reflection;
-
-namespace Config
-{
- class Config
- {
- static string ExecutablePath, InstallDirectory, ExtraIncludeDirs, ExtraLibDirs, ExtraArguments;
- static bool UseNMake = true, BuildDebug = false;
-
- static bool CheckResponse(string InstallerResponse)
- {
- if (string.Compare(InstallerResponse, "yes", true) == 0 || string.Compare(InstallerResponse, "y", true) == 0)
- return true;
- return false;
- }
-
- static bool LoadCache()
- {
- try
- {
- string[] cache = File.ReadAllLines(string.Format(@"{0}\config.cache", ExecutablePath));
- 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 == "EXTRAINCLUDE")
- ExtraIncludeDirs = value;
- else if (name == "EXTRALIBS")
- ExtraLibDirs = value;
- else if (name == "EXTRAARGS")
- ExtraArguments = value;
- }
-
- return true;
- }
- catch (Exception)
- {
- }
-
- return false;
- }
-
- static void SaveCache()
- {
- using (TextWriter tw = new StreamWriter(string.Format(@"{0}\config.cache", ExecutablePath)))
- {
- tw.WriteLine("INSTDIR={0}", InstallDirectory);
- tw.WriteLine("DEBUG={0}", BuildDebug ? "yes" : "no");
- tw.WriteLine("USENMAKE={0}", UseNMake ? "yes" : "no");
- tw.WriteLine("EXTRAINCLUDE={0}", ExtraIncludeDirs);
- tw.WriteLine("EXTRALIBS={0}", ExtraLibDirs);
- tw.WriteLine("EXTRAARGS={0}", ExtraArguments);
- }
- }
-
- static string HandleCache(int i)
- {
- switch (i)
- {
- case 0:
- Console.Write("[{0}] ", InstallDirectory);
- return InstallDirectory;
- case 1:
- Console.Write("[{0}] ", UseNMake ? "yes" : "no");
- return UseNMake ? "yes" : "no";
- case 2:
- Console.Write("[{0}] ", BuildDebug ? "yes" : "no");
- return BuildDebug ? "yes" : "no";
- case 3:
- Console.Write("[{0}] ", ExtraIncludeDirs);
- return ExtraIncludeDirs;
- case 4:
- Console.Write("[{0}] ", ExtraLibDirs);
- return ExtraLibDirs;
- case 5:
- Console.Write("[{0}] ", ExtraArguments);
- return ExtraArguments;
- default:
- break;
- }
-
- return null;
- }
-
- static string FindAnopeVersion()
- {
- if (!File.Exists(string.Format(@"{0}\src\version.sh", ExecutablePath)))
- return "Unknown";
-
- Dictionary<string, string> versions = new Dictionary<string, string>();
- string[] versionfile = File.ReadAllLines(string.Format(@"{0}\src\version.sh", ExecutablePath));
- foreach (string line in versionfile)
- if (line.StartsWith("VERSION_"))
- {
- string key = line.Split('_')[1].Split('=')[0];
- if (!versions.ContainsKey(key))
- versions.Add(key, line.Split('=')[1].Replace("\"", "").Replace("\'", ""));
- }
-
- try
- {
- if (versions.ContainsKey("BUILD"))
- return string.Format("{0}.{1}.{2}.{3}{4}", versions["MAJOR"], versions["MINOR"], versions["PATCH"], versions["BUILD"], versions["EXTRA"]);
- else
- return string.Format("{0}.{1}.{2}{3}", versions["MAJOR"], versions["MINOR"], versions["PATCH"], versions["EXTRA"]);
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- return "Unknown";
- }
- }
-
- static void RunCMake(string cMake)
- {
- Console.WriteLine("cmake {0}", cMake);
- try
- {
- ProcessStartInfo processStartInfo = new ProcessStartInfo("cmake")
- {
- RedirectStandardError = true,
- RedirectStandardOutput = true,
- UseShellExecute = false,
- Arguments = cMake
- };
- Process pCMake = Process.Start(processStartInfo);
- StreamReader stdout = pCMake.StandardOutput, stderr = pCMake.StandardError;
- string stdoutr, stderrr;
- List<string> errors = new List<string>();
- while (!pCMake.HasExited)
- {
- if ((stdoutr = stdout.ReadLine()) != null)
- Console.WriteLine(stdoutr);
- if ((stderrr = stderr.ReadLine()) != null)
- errors.Add(stderrr);
- }
- foreach (string error in errors)
- Console.WriteLine(error);
- Console.WriteLine();
- if (pCMake.ExitCode == 0)
- {
- if (UseNMake)
- Console.WriteLine("To compile Anope, run 'nmake'. To install, run 'nmake install'");
- else
- Console.WriteLine("To compile Anope, open Anope.sln and build the solution. To install, do a build on the INSTALL project");
- }
- else
- Console.WriteLine("There was an error attempting to run CMake! Check the above error message, and contact the Anope team if you are unsure how to proceed.");
- }
- catch (Exception e)
- {
- Console.WriteLine();
- Console.WriteLine(DateTime.UtcNow + " UTC: " + e.Message);
- Console.WriteLine("There was an error attempting to run CMake! Check the above error message, and contact the Anope team if you are unsure how to proceed.");
- }
- }
-
- static int Main(string[] args)
- {
- bool IgnoreCache = false, NoIntro = false, DoQuick = false;
-
- if (args.Length > 0)
- {
- if (args[0] == "--help")
- {
- Console.WriteLine("Config utility for Anope");
- Console.WriteLine("------------------------");
- Console.WriteLine("Syntax: .\\Config.exe [options]");
- Console.WriteLine("-nocache Ignore settings saved in config.cache");
- Console.WriteLine("-nointro Skip intro (disclaimer, etc)");
- Console.WriteLine("-quick or -q Skip questions, go straight to cmake");
- return 0;
- }
- else if (args[0] == "-nocache")
- IgnoreCache = true;
- else if (args[0] == "-nointro")
- NoIntro = true;
- else if (args[0] == "-quick" || args[0] == "-q")
- DoQuick = true;
- }
-
- ExecutablePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
-
- string AnopeVersion = FindAnopeVersion();
-
- if (!NoIntro && File.Exists(string.Format(@"{0}\.BANNER", ExecutablePath)))
- Console.WriteLine(File.ReadAllText(string.Format(@"{0}\.BANNER", ExecutablePath)).Replace("CURVER", AnopeVersion).Replace("For more options type SOURCE_DIR/Config --help", ""));
-
- Console.WriteLine("Press Enter to begin");
- Console.WriteLine();
- Console.ReadKey();
-
- bool UseCache = false;
-
- if (DoQuick || !IgnoreCache)
- {
- UseCache = LoadCache();
- if (DoQuick && !UseCache)
- {
- Console.WriteLine("Can't find cache file (config.cache), aborting...");
- return 1;
- }
- }
-
- if (!DoQuick)
- {
- List<string> InstallerQuestions = new List<string>()
- {
- "Where do you want Anope to be installed?",
- "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]",
- "Would you like to build a debug version of Anope? [y/n]",
- "Are there any extra include directories you wish to use?\nYou may only need to do this if CMake is unable to locate missing dependencies without hints.\nSeparate directories with semicolons and use slashes (aka /) instead of backslashes (aka \\).\nIf you need no extra include directories, enter NONE in all caps.",
- "Are there any extra library directories you wish to use?\nYou may only need to do this if CMake is unable to locate missing dependencies without hints.\nSeparate directories with semicolons and use slashes (aka /) instead of backslashes (aka \\).\nIf you need no extra library directories, enter NONE in all caps.",
- "Are there any extra arguments you wish to pass to CMake?\nIf you need no extra arguments to CMake, enter NONE in all caps."
- };
-
- 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 (!string.IsNullOrWhiteSpace(CacheResponse) && string.IsNullOrWhiteSpace(InstallerResponse))
- InstallerResponse = CacheResponse;
-
- // Question 4+ are optional
- if (i < 3 && string.IsNullOrWhiteSpace(InstallerResponse))
- {
- Console.WriteLine("Invalid option");
- --i;
- continue;
- }
-
- switch (i)
- {
- case 0:
- if (!Directory.Exists(InstallerResponse))
- {
- Console.WriteLine("Directory does not exist! Creating directory.");
- Console.WriteLine();
- try
- {
- Directory.CreateDirectory(InstallerResponse);
- InstallDirectory = InstallerResponse;
- }
- catch (Exception e)
- {
- Console.WriteLine("Unable to create directory: " + e.Message);
- --i;
- }
- }
- else if (File.Exists(InstallerResponse + @"\include\services.h"))
- {
- Console.WriteLine("You cannot use the Anope source directory as the target directory!");
- --i;
- }
- else
- InstallDirectory = InstallerResponse;
- break;
- case 1:
- UseNMake = CheckResponse(InstallerResponse);
- if (UseNMake)
- ++i;
- break;
- case 2:
- BuildDebug = CheckResponse(InstallerResponse);
- break;
- case 3:
- if (InstallerResponse == "NONE")
- ExtraIncludeDirs = null;
- else
- ExtraIncludeDirs = InstallerResponse;
- break;
- case 4:
- if (InstallerResponse == "NONE")
- ExtraLibDirs = null;
- else
- ExtraLibDirs = InstallerResponse;
- break;
- case 5:
- if (InstallerResponse == "NONE")
- ExtraArguments = null;
- else
- ExtraArguments = InstallerResponse;
- break;
- default:
- break;
- }
- }
- }
-
- Console.WriteLine("Anope will be compiled with the following options:");
- Console.WriteLine("Install directory: {0}", InstallDirectory);
- Console.WriteLine("Use NMake: {0}", UseNMake ? "Yes" : "No");
- Console.WriteLine("Build debug: {0}", BuildDebug ? "Yes" : "No");
- Console.WriteLine("Anope Version: {0}", AnopeVersion);
- Console.WriteLine("Extra Include Directories: {0}", ExtraIncludeDirs);
- Console.WriteLine("Extra Library Directories: {0}", ExtraLibDirs);
- Console.WriteLine("Extra Arguments: {0}", ExtraArguments);
- Console.WriteLine("Press Enter to continue...");
- Console.ReadKey();
-
- SaveCache();
-
- if (!string.IsNullOrWhiteSpace(ExtraIncludeDirs))
- ExtraIncludeDirs = string.Format("-DEXTRA_INCLUDE:STRING={0} ", ExtraIncludeDirs);
- else
- ExtraIncludeDirs = "";
- if (!string.IsNullOrWhiteSpace(ExtraLibDirs))
- ExtraLibDirs = string.Format("-DEXTRA_LIBS:STRING={0} ", ExtraLibDirs);
- else
- ExtraLibDirs = "";
- if (!string.IsNullOrWhiteSpace(ExtraArguments))
- ExtraArguments += " ";
- else
- 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 + ExtraIncludeDirs + ExtraLibDirs + ExtraArguments + "\"" + ExecutablePath.Replace('\\', '/') + "\"";
- RunCMake(cMake);
-
- return 0;
- }
- }
-}
diff --git a/src/win32/anope_windows.h b/src/win32/anope_windows.h
index 14c83b4d4..061934752 100644
--- a/src/win32/anope_windows.h
+++ b/src/win32/anope_windows.h
@@ -1,7 +1,7 @@
/* POSIX emulation layer for Windows.
*
- * (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
- * (C) 2008-2016 Anope Team <team@anope.org>
+ * Copyright (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
+ * Copyright (C) 2008-2014 Anope Team <info@anope.org>
*
* Please read COPYING and README for further details.
*
@@ -42,6 +42,13 @@
/* VS2008 hates having this define before its own */
#define vsnprintf _vsnprintf
+#define popen _popen
+#define pclose _pclose
+
+#define PATH_MAX MAX_PATH
+
+#define sleep(x) Sleep(x * 1000)
+
#define anope_close windows_close
#define stat _stat
@@ -56,7 +63,6 @@
#include "dir/dir.h"
#include "dl/dl.h"
#include "pipe/pipe.h"
-#include "pthread/pthread.h"
#include "sigaction/sigaction.h"
typedef int ssize_t;
diff --git a/src/win32/dir/dir.cpp b/src/win32/dir/dir.cpp
index d660c9694..16809bd9c 100644
--- a/src/win32/dir/dir.cpp
+++ b/src/win32/dir/dir.cpp
@@ -1,14 +1,13 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
#include "dir.h"
#include <stdio.h>
-
+
DIR *opendir(const char *path)
{
char real_path[MAX_PATH];
diff --git a/src/win32/dir/dir.h b/src/win32/dir/dir.h
index a6c9a055f..4d1433658 100644
--- a/src/win32/dir/dir.h
+++ b/src/win32/dir/dir.h
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
@@ -21,7 +20,7 @@ struct DIR
WIN32_FIND_DATA data;
bool read_first;
};
-
+
DIR *opendir(const char *);
dirent *readdir(DIR *);
int closedir(DIR *);
diff --git a/src/win32/dl/dl.cpp b/src/win32/dl/dl.cpp
index bdcbe636c..5b19d7441 100644
--- a/src/win32/dl/dl.cpp
+++ b/src/win32/dl/dl.cpp
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
diff --git a/src/win32/dl/dl.h b/src/win32/dl/dl.h
index 81c115fef..02a2f1d3d 100644
--- a/src/win32/dl/dl.h
+++ b/src/win32/dl/dl.h
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
diff --git a/src/win32/pipe/pipe.cpp b/src/win32/pipe/pipe.cpp
index 70690ab2b..676909b9a 100644
--- a/src/win32/pipe/pipe.cpp
+++ b/src/win32/pipe/pipe.cpp
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
@@ -56,6 +55,7 @@ int pipe(int fds[2])
fds[0] = cfd;
fds[1] = afd;
-
+
return 0;
}
+
diff --git a/src/win32/pipe/pipe.h b/src/win32/pipe/pipe.h
index d77d0706b..8e67bafc7 100644
--- a/src/win32/pipe/pipe.h
+++ b/src/win32/pipe/pipe.h
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
diff --git a/src/win32/pthread/pthread.cpp b/src/win32/pthread/pthread.cpp
deleted file mode 100644
index 36b8cd54d..000000000
--- a/src/win32/pthread/pthread.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* POSIX emulation layer for Windows.
- *
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "pthread.h"
-
-struct ThreadInfo
-{
- void *(*entry)(void *);
- void *param;
-};
-
-static DWORD WINAPI entry_point(void *parameter)
-{
- ThreadInfo *ti = static_cast<ThreadInfo *>(parameter);
- ti->entry(ti->param);
- delete ti;
- return 0;
-}
-
-int pthread_attr_init(pthread_attr_t *)
-{
- /* No need for this */
- return 0;
-}
-
-int pthread_attr_setdetachstate(pthread_attr_t *, int)
-{
- /* No need for this */
- return 0;
-}
-
-int pthread_create(pthread_t *thread, const pthread_attr_t *, void *(*entry)(void *), void *param)
-{
- ThreadInfo *ti = new ThreadInfo;
- ti->entry = entry;
- ti->param = param;
-
- *thread = CreateThread(NULL, 0, entry_point, ti, 0, NULL);
- if (!*thread)
- {
- delete ti;
- return -1;
- }
-
- return 0;
-}
-
-int pthread_join(pthread_t thread, void **)
-{
- if (WaitForSingleObject(thread, INFINITE) == WAIT_FAILED)
- return -1;
- CloseHandle(thread);
- return 0;
-}
-
-void pthread_exit(int i)
-{
- ExitThread(i);
-}
-
-int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *)
-{
- InitializeCriticalSection(mutex);
- return 0;
-}
-
-int pthread_mutex_destroy(pthread_mutex_t *mutex)
-{
- DeleteCriticalSection(mutex);
- return 0;
-}
-
-int pthread_mutex_lock(pthread_mutex_t *mutex)
-{
- EnterCriticalSection(mutex);
- return 0;
-}
-
-int pthread_mutex_trylock(pthread_mutex_t *mutex)
-{
- return !TryEnterCriticalSection(mutex);
-}
-
-int pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
- LeaveCriticalSection(mutex);
- return 0;
-}
-
-int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *)
-{
- *cond = CreateEvent(NULL, false, false, NULL);
- if (*cond == NULL)
- return -1;
- return 0;
-}
-
-int pthread_cond_destroy(pthread_cond_t *cond)
-{
- return !CloseHandle(*cond);
-}
-
-int pthread_cond_signal(pthread_cond_t *cond)
-{
- return !PulseEvent(*cond);
-}
-
-int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
-{
- LeaveCriticalSection(mutex);
- WaitForSingleObject(*cond, INFINITE);
- EnterCriticalSection(mutex);
- return 0;
-}
diff --git a/src/win32/pthread/pthread.h b/src/win32/pthread/pthread.h
deleted file mode 100644
index 18909a17d..000000000
--- a/src/win32/pthread/pthread.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* POSIX emulation layer for Windows.
- *
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include <Windows.h>
-
-typedef HANDLE pthread_t;
-typedef CRITICAL_SECTION pthread_mutex_t;
-typedef HANDLE pthread_cond_t;
-typedef int pthread_attr_t;
-typedef void pthread_mutexattr_t;
-typedef void pthread_condattr_t;
-
-#define PTHREAD_CREATE_JOINABLE 0
-
-extern int pthread_attr_init(pthread_attr_t *);
-extern int pthread_attr_setdetachstate(pthread_attr_t *, int);
-extern int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
-extern int pthread_join(pthread_t, void **);
-extern void pthread_exit(int);
-
-extern int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
-extern int pthread_mutex_destroy(pthread_mutex_t *);
-extern int pthread_mutex_lock(pthread_mutex_t *);
-extern int pthread_mutex_trylock(pthread_mutex_t *);
-extern int pthread_mutex_unlock(pthread_mutex_t *);
-
-extern int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
-extern int pthread_cond_destroy(pthread_cond_t *);
-extern int pthread_cond_signal(pthread_cond_t *);
-extern int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
diff --git a/src/win32/resource.h b/src/win32/resource.h
index 0fb755b56..e4fa54b70 100644
--- a/src/win32/resource.h
+++ b/src/win32/resource.h
@@ -1,11 +1,3 @@
-/*
- *
- * (C) 2005-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by Win32GUI.rc
@@ -16,7 +8,7 @@
// Next default values for new objects
-//
+//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
diff --git a/src/win32/sigaction/sigaction.cpp b/src/win32/sigaction/sigaction.cpp
index 17faaf2fb..51615cf39 100644
--- a/src/win32/sigaction/sigaction.cpp
+++ b/src/win32/sigaction/sigaction.cpp
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*
@@ -9,12 +8,12 @@
* Based on the original code of Services by Andy Church.
*/
-#include <windows.h>
-#include "sigaction.h"
-#include <signal.h>
+ #include <windows.h>
+ #include "sigaction.h"
+ #include <signal.h>
-int sigaction(int sig, struct sigaction *action, struct sigaction *old)
-{
+ int sigaction(int sig, struct sigaction *action, struct sigaction *old)
+ {
if (sig == -1)
return 0;
if (old == NULL)
@@ -28,4 +27,4 @@ int sigaction(int sig, struct sigaction *action, struct sigaction *old)
return -1;
}
return 0;
-}
+ }
diff --git a/src/win32/sigaction/sigaction.h b/src/win32/sigaction/sigaction.h
index c517ba16d..9e74eeffa 100644
--- a/src/win32/sigaction/sigaction.h
+++ b/src/win32/sigaction/sigaction.h
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*
@@ -9,20 +8,21 @@
* Based on the original code of Services by Andy Church.
*/
-#define sigemptyset(x) memset((x), 0, sizeof(*(x)))
+ #define sigemptyset(x) memset((x), 0, sizeof(*(x)))
-#ifndef SIGHUP
-# define SIGHUP -1
-#endif
-#ifndef SIGPIPE
-# define SIGPIPE -1
-#endif
+ #ifndef SIGHUP
+ # define SIGHUP -1
+ #endif
+ #ifndef SIGPIPE
+ # define SIGPIPE -1
+ #endif
-struct sigaction
-{
+ struct sigaction
+ {
void (*sa_handler)(int);
int sa_flags;
int sa_mask;
-};
+ };
+
+ extern int sigaction(int, struct sigaction *, struct sigaction *);
-extern int sigaction(int, struct sigaction *, struct sigaction *);
diff --git a/src/win32/socket.cpp b/src/win32/socket.cpp
index 489192679..7f6ef4df1 100644
--- a/src/win32/socket.cpp
+++ b/src/win32/socket.cpp
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
@@ -86,7 +85,7 @@ int windows_inet_pton(int af, const char *src, void *dst)
}
return 1;
}
-
+
return 0;
}
diff --git a/src/win32/socket.h b/src/win32/socket.h
index a8064589e..d587618a9 100644
--- a/src/win32/socket.h
+++ b/src/win32/socket.h
@@ -1,7 +1,6 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2008-2014 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*/
diff --git a/src/win32/win32.rc.cmake b/src/win32/win32.rc.cmake
index 1e86c7e0d..4cca9d89d 100644
--- a/src/win32/win32.rc.cmake
+++ b/src/win32/win32.rc.cmake
@@ -54,7 +54,7 @@ BEGIN
VALUE "FileDescription", "Anope IRC Services"
VALUE "FileVersion", "@VERSION_FULL@"
VALUE "InternalName", "Anope"
- VALUE "LegalCopyright", "Copyright (C) 2003-2016 Anope Team"
+ VALUE "LegalCopyright", "Copyright (C) 2003-2014 Anope Team"
VALUE "OriginalFilename", "anope.exe"
VALUE "ProductName", "Anope"
VALUE "ProductVersion", "@VERSION_DOTTED@"
diff --git a/src/win32/windows.cpp b/src/win32/windows.cpp
index ac6801cba..f5bbde2f8 100644
--- a/src/win32/windows.cpp
+++ b/src/win32/windows.cpp
@@ -1,7 +1,7 @@
-/* POSIX emulation layer for Windows.
+ /* POSIX emulation layer for Windows.
*
- * (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
- * (C) 2008-2016 Anope Team <team@anope.org>
+ * Copyright (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
+ * Copyright (C) 2008-2014 Anope Team <info@anope.org>
*
* Please read COPYING and README for further details.
*
@@ -73,10 +73,10 @@ int gettimeofday(timeval *tv, void *)
{
SYSTEMTIME st;
GetSystemTime(&st);
-
+
tv->tv_sec = Anope::CurTime;
tv->tv_usec = st.wMilliseconds;
-
+
return 0;
}
@@ -248,7 +248,7 @@ int mkstemp(char *input)
errno = EEXIST;
return -1;
}
-
+
int fd = open(input, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE);
return fd;
}
diff --git a/src/xline.cpp b/src/xline.cpp
index 21cbc2501..df65ae7dd 100644
--- a/src/xline.cpp
+++ b/src/xline.cpp
@@ -1,12 +1,20 @@
-/* XLine functions.
+/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2012-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope is free software; you can
+ * redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software
+ * Foundation, version 2.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#include "services.h"
@@ -14,66 +22,67 @@
#include "xline.h"
#include "users.h"
#include "sockets.h"
-#include "regexpr.h"
#include "config.h"
#include "commands.h"
#include "servers.h"
/* List of XLine managers we check users against in XLineManager::CheckAll */
-std::list<XLineManager *> XLineManager::XLineManagers;
-Serialize::Checker<std::multimap<Anope::string, XLine *, ci::less> > XLineManager::XLinesByUID("XLine");
+std::vector<XLineManager *> XLineManager::XLineManagers;
-void XLine::Init()
+void XLine::Recache()
{
- if (this->mask.length() >= 2 && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/' && !Config->GetBlock("options")->Get<const Anope::string>("regexengine").empty())
+ delete regex;
+ regex = nullptr;
+
+ delete c;
+ c = nullptr;
+
+ Anope::string mask = GetMask();
+ if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/' && Config->regex_flags)
{
- Anope::string stripped_mask = this->mask.substr(1, this->mask.length() - 2);
+ Anope::string stripped_mask = mask.substr(1, mask.length() - 2);
- ServiceReference<RegexProvider> provider("Regex", Config->GetBlock("options")->Get<const Anope::string>("regexengine"));
- if (provider)
+ try
{
- try
- {
- this->regex = provider->Compile(stripped_mask);
- }
- catch (const RegexException &ex)
- {
- Log(LOG_DEBUG) << ex.GetReason();
- }
+ this->regex = new std::regex(stripped_mask.str(), Config->regex_flags);
+ }
+ catch (const std::regex_error &ex)
+ {
+ Log(LOG_DEBUG) << ex.what();
}
}
- size_t nick_t = this->mask.find('!');
+ size_t nick_t = mask.find('!');
if (nick_t != Anope::string::npos)
- nick = this->mask.substr(0, nick_t);
+ nick = mask.substr(0, nick_t);
- size_t user_t = this->mask.find('!'), host_t = this->mask.find('@');
+ size_t user_t = mask.find('!'), host_t = mask.find('@');
if (host_t != Anope::string::npos)
{
if (user_t != Anope::string::npos && host_t > user_t)
- user = this->mask.substr(user_t + 1, host_t - user_t - 1);
+ user = mask.substr(user_t + 1, host_t - user_t - 1);
else
- user = this->mask.substr(0, host_t);
+ user = mask.substr(0, host_t);
}
- size_t real_t = this->mask.find('#');
+ size_t real_t = mask.find('#');
if (host_t != Anope::string::npos)
{
if (real_t != Anope::string::npos && real_t > host_t)
- host = this->mask.substr(host_t + 1, real_t - host_t - 1);
+ host = mask.substr(host_t + 1, real_t - host_t - 1);
else
- host = this->mask.substr(host_t + 1);
+ host = mask.substr(host_t + 1);
}
else
{
if (real_t != Anope::string::npos)
- host = this->mask.substr(0, real_t);
+ host = mask.substr(0, real_t);
else
- host = this->mask;
+ host = mask;
}
if (real_t != Anope::string::npos)
- real = this->mask.substr(real_t + 1);
+ real = mask.substr(real_t + 1);
if (host.find('/') != Anope::string::npos)
{
@@ -86,31 +95,80 @@ void XLine::Init()
}
}
-XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(Me->GetName()), created(0), expires(0), reason(r), id(uid)
+XLine::~XLine()
+{
+ delete regex;
+ delete c;
+}
+
+void XLine::SetType(const Anope::string &t)
{
- regex = NULL;
- manager = NULL;
- c = NULL;
+ Set(&XLineType::type, t);
+}
- this->Init();
+Anope::string XLine::GetType()
+{
+ return Get(&XLineType::type);
}
-XLine::XLine(const Anope::string &ma, const Anope::string &b, const time_t ex, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(b), created(Anope::CurTime), expires(ex), reason(r), id(uid)
+void XLine::SetMask(const Anope::string &m)
{
- regex = NULL;
- manager = NULL;
- c = NULL;
+ Set(&XLineType::mask, m);
+}
- this->Init();
+Anope::string XLine::GetMask()
+{
+ return Get<Anope::string>(&XLineType::mask);
}
-XLine::~XLine()
+void XLine::SetBy(const Anope::string &b)
{
- if (manager)
- manager->RemoveXLine(this);
+ Set(&XLineType::by, b);
+}
- delete regex;
- delete c;
+Anope::string XLine::GetBy()
+{
+ return Get(&XLineType::by);
+}
+
+void XLine::SetReason(const Anope::string &r)
+{
+ Set(&XLineType::reason, r);
+}
+
+Anope::string XLine::GetReason()
+{
+ return Get(&XLineType::reason);
+}
+
+void XLine::SetID(const Anope::string &id)
+{
+ Set(&XLineType::id, id);
+}
+
+Anope::string XLine::GetID()
+{
+ return Get(&XLineType::id);
+}
+
+void XLine::SetCreated(const time_t &t)
+{
+ Set(&XLineType::created, t);
+}
+
+time_t XLine::GetCreated()
+{
+ return Get(&XLineType::created);
+}
+
+void XLine::SetExpires(const time_t &e)
+{
+ Set(&XLineType::expires, e);
+}
+
+time_t XLine::GetExpires()
+{
+ return Get(&XLineType::created);
}
const Anope::string &XLine::GetNick() const
@@ -133,11 +191,11 @@ const Anope::string &XLine::GetReal() const
return real;
}
-Anope::string XLine::GetReason() const
+Anope::string XLine::GetReasonWithID()
{
- Anope::string r = this->reason;
- if (!this->id.empty())
- r += " (ID: " + this->id + ")";
+ Anope::string r = this->GetReason();
+ if (!this->GetID().empty())
+ r += " (ID: " + this->GetID() + ")";
return r;
}
@@ -146,67 +204,21 @@ bool XLine::HasNickOrReal() const
return !this->GetNick().empty() || !this->GetReal().empty();
}
-bool XLine::IsRegex() const
+bool XLine::IsRegex()
{
- return !this->mask.empty() && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/';
+ Anope::string mask = GetMask();
+ return mask.length() > 2 && mask[0] == '/' && mask[mask.length() - 1] == '/';
}
-void XLine::Serialize(Serialize::Data &data) const
+XLineManager *XLine::GetManager()
{
- data["mask"] << this->mask;
- data["by"] << this->by;
- data["created"] << this->created;
- data["expires"] << this->expires;
- data["reason"] << this->reason;
- data["uid"] << this->id;
- if (this->manager)
- data["manager"] << this->manager->name;
+ return ServiceManager::Get()->FindService<XLineManager *>(GetType());
}
-Serializable* XLine::Unserialize(Serializable *obj, Serialize::Data &data)
+void XLineType::Mask::SetField(XLine *s, const Anope::string &value)
{
- Anope::string smanager;
-
- data["manager"] >> smanager;
-
- ServiceReference<XLineManager> xlm("XLineManager", smanager);
- if (!xlm)
- return NULL;
-
- XLine *xl;
- if (obj)
- {
- xl = anope_dynamic_static_cast<XLine *>(obj);
- data["mask"] >> xl->mask;
- data["by"] >> xl->by;
- data["reason"] >> xl->reason;
- data["uid"] >> xl->id;
-
- if (xlm != xl->manager)
- {
- xl->manager->DelXLine(xl);
- xlm->AddXLine(xl);
- }
- }
- else
- {
- Anope::string smask, sby, sreason, suid;
- time_t expires;
-
- data["mask"] >> smask;
- data["by"] >> sby;
- data["reason"] >> sreason;
- data["uid"] >> suid;
- data["expires"] >> expires;
-
- xl = new XLine(smask, sby, expires, sreason, suid);
- xlm->AddXLine(xl);
- }
-
- data["created"] >> xl->created;
- xl->manager = xlm;
-
- return xl;
+ Serialize::Field<XLine, Anope::string>::SetField(s, value);
+ s->Recache();
}
void XLineManager::RegisterXLineManager(XLineManager *xlm)
@@ -216,52 +228,35 @@ void XLineManager::RegisterXLineManager(XLineManager *xlm)
void XLineManager::UnregisterXLineManager(XLineManager *xlm)
{
- std::list<XLineManager *>::iterator it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm);
-
+ auto it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm);
if (it != XLineManagers.end())
XLineManagers.erase(it);
}
void XLineManager::CheckAll(User *u)
{
- for (std::list<XLineManager *>::iterator it = XLineManagers.begin(), it_end = XLineManagers.end(); it != it_end; ++it)
- {
- XLineManager *xlm = *it;
-
+ for (XLineManager *xlm : XLineManagers)
if (xlm->CheckAllXLines(u))
break;
- }
}
Anope::string XLineManager::GenerateUID()
{
Anope::string id;
- int count = 0;
- do
- {
- id.clear();
- if (++count > 10)
- {
- Log(LOG_DEBUG) << "Unable to generate XLine UID";
- break;
- }
-
- for (int i = 0; i < 10; ++i)
- {
- char c;
- do
- c = (rand() % 75) + 48;
- while (!isupper(c) && !isdigit(c));
- id += c;
- }
+ for (int i = 0; i < 10; ++i)
+ {
+ char c;
+ do
+ c = (rand() % 75) + 48;
+ while (!isupper(c) && !isdigit(c));
+ id += c;
}
- while (XLinesByUID->count(id) > 0);
return id;
}
-XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, "XLineManager", xname), type(t), xlines("XLine")
+XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, NAME, xname), type(t)
{
}
@@ -270,147 +265,82 @@ XLineManager::~XLineManager()
this->Clear();
}
-const char &XLineManager::Type()
+char XLineManager::Type()
{
return this->type;
}
-size_t XLineManager::GetCount() const
+std::vector<XLine *> XLineManager::GetXLines() const
{
- return this->xlines->size();
-}
+ std::vector<XLine *> xlines;
-const std::vector<XLine *> &XLineManager::GetList() const
-{
- return this->xlines;
-}
+ for (XLine *x : Serialize::GetObjects<XLine *>())
+ if (x->GetType() == this->GetName())
+ xlines.push_back(x);
-void XLineManager::AddXLine(XLine *x)
-{
- if (!x->id.empty())
- XLinesByUID->insert(std::make_pair(x->id, x));
- this->xlines->push_back(x);
- x->manager = this;
+ return xlines;
}
-void XLineManager::RemoveXLine(XLine *x)
-{
- /* called from the destructor */
-
- std::vector<XLine *>::iterator it = std::find(this->xlines->begin(), this->xlines->end(), x);
-
- if (!x->id.empty())
- {
- std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->id), it3 = XLinesByUID->upper_bound(x->id);
- for (; it2 != XLinesByUID->end() && it2 != it3; ++it2)
- if (it2->second == x)
- {
- XLinesByUID->erase(it2);
- break;
- }
- }
-
- if (it != this->xlines->end())
- {
- this->SendDel(x);
- this->xlines->erase(it);
- }
-}
-
-bool XLineManager::DelXLine(XLine *x)
+void XLineManager::AddXLine(XLine *x)
{
- std::vector<XLine *>::iterator it = std::find(this->xlines->begin(), this->xlines->end(), x);
-
- if (!x->id.empty())
- {
- std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->id), it3 = XLinesByUID->upper_bound(x->id);
- for (; it2 != XLinesByUID->end() && it2 != it3; ++it2)
- if (it2->second == x)
- {
- XLinesByUID->erase(it2);
- break;
- }
- }
-
- if (it != this->xlines->end())
- {
- this->SendDel(x);
-
- x->manager = NULL; // Don't call remove
- delete x;
- this->xlines->erase(it);
-
- return true;
- }
-
- return false;
+ x->SetType(this->GetName());
}
XLine* XLineManager::GetEntry(unsigned index)
{
- if (index >= this->xlines->size())
- return NULL;
+ std::vector<XLine *> xlines = GetXLines();
+
+ if (index >= xlines.size())
+ return nullptr;
- XLine *x = this->xlines->at(index);
- x->QueueUpdate();
- return x;
+ return xlines.at(index);
}
void XLineManager::Clear()
{
- std::vector<XLine *> xl;
- this->xlines->swap(xl);
-
- for (unsigned i = 0; i < xl.size(); ++i)
- {
- XLine *x = xl[i];
- if (!x->id.empty())
- XLinesByUID->erase(x->id);
- delete x;
- }
+ for (XLine *x : GetXLines())
+ x->Delete();
}
bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time_t expires, const Anope::string &reason)
{
- for (unsigned i = this->GetCount(); i > 0; --i)
+ for (XLine *x : GetXLines())
{
- XLine *x = this->GetEntry(i - 1);
-
- if (x->mask.equals_ci(mask))
+ if (x->GetMask().equals_ci(mask))
{
- if (!x->expires || x->expires >= expires)
+ if (!x->GetExpires() || x->GetExpires() >= expires)
{
- if (x->reason != reason)
+ if (x->GetReason() != reason)
{
- x->reason = reason;
- source.Reply(_("Reason for %s updated."), x->mask.c_str());
+ x->SetReason(reason);
+ source.Reply(_("Reason for %s updated."), x->GetMask().c_str());
}
else
source.Reply(_("%s already exists."), mask.c_str());
}
else
{
- x->expires = expires;
- if (x->reason != reason)
+ x->SetExpires(expires);
+ if (x->GetReason() != reason)
{
- x->reason = reason;
- source.Reply(_("Expiry and reason updated for %s."), x->mask.c_str());
+ x->SetReason(reason);
+ source.Reply(_("Expiry and reason updated for %s."), x->GetMask().c_str());
}
else
- source.Reply(_("Expiry for %s updated."), x->mask.c_str());
+ source.Reply(_("Expiry for %s updated."), x->GetMask().c_str());
}
return false;
}
- else if (Anope::Match(mask, x->mask) && (!x->expires || x->expires >= expires))
+ else if (Anope::Match(mask, x->GetMask()) && (!x->GetExpires() || x->GetExpires() >= expires))
{
- source.Reply(_("%s is already covered by %s."), mask.c_str(), x->mask.c_str());
+ source.Reply(_("%s is already covered by %s."), mask.c_str(), x->GetMask().c_str());
return false;
}
- else if (Anope::Match(x->mask, mask) && (!expires || x->expires <= expires))
+ else if (Anope::Match(x->GetMask(), mask) && (!expires || x->GetExpires() <= expires))
{
- source.Reply(_("Removing %s because %s covers it."), x->mask.c_str(), mask.c_str());
- this->DelXLine(x);
+ source.Reply(_("Removing %s because %s covers it."), x->GetMask().c_str(), mask.c_str());
+ x->Delete();
}
}
@@ -419,38 +349,21 @@ bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time
XLine* XLineManager::HasEntry(const Anope::string &mask)
{
- std::multimap<Anope::string, XLine *, ci::less>::iterator it = XLinesByUID->find(mask);
- if (it != XLinesByUID->end())
- for (std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->upper_bound(mask); it != it2; ++it)
- if (it->second->manager == NULL || it->second->manager == this)
- {
- it->second->QueueUpdate();
- return it->second;
- }
- for (unsigned i = 0, end = this->xlines->size(); i < end; ++i)
- {
- XLine *x = this->xlines->at(i);
-
- if (x->mask.equals_ci(mask))
- {
- x->QueueUpdate();
+ for (XLine *x : GetXLines())
+ if (x->GetMask().equals_ci(mask))
return x;
- }
- }
- return NULL;
+ return nullptr;
}
XLine *XLineManager::CheckAllXLines(User *u)
{
- for (unsigned i = this->xlines->size(); i > 0; --i)
+ for (XLine *x : Serialize::GetObjects<XLine *>())
{
- XLine *x = this->xlines->at(i - 1);
-
- if (x->expires && x->expires < Anope::CurTime)
+ if (x->GetExpires() && x->GetExpires() < Anope::CurTime)
{
this->OnExpire(x);
- this->DelXLine(x);
+ x->Delete();
continue;
}
@@ -461,10 +374,10 @@ XLine *XLineManager::CheckAllXLines(User *u)
}
}
- return NULL;
+ return nullptr;
}
-void XLineManager::OnExpire(const XLine *x)
+void XLineManager::OnExpire(XLine *x)
{
}