/*
* InspIRCd -- Internet Relay Chat Daemon
*
+ * Copyright (C) 2020 Matt Schatz <genius3000@g3k.solutions>
* Copyright (C) 2019 nia <nia@netbsd.org>
* Copyright (C) 2019 iwalkalone <iwalkalone69@gmail.com>
- * Copyright (C) 2013, 2017-2019 Sadie Powell <sadie@witchery.services>
+ * Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services>
* Copyright (C) 2013 Daniel Vassdal <shutter@canternet.org>
* Copyright (C) 2013 Adam <Adam@anope.org>
* Copyright (C) 2012-2016, 2018 Attila Molnar <attilamolnar@hush.com>
* Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
* Copyright (C) 2007 Oliver Lupton <om@inspircd.org>
* Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
- * Copyright (C) 2006-2010 Craig Edwards <brain@inspircd.org>
+ * Copyright (C) 2005-2010 Craig Edwards <brain@inspircd.org>
*
* This file is part of InspIRCd. InspIRCd is free software: you can
* redistribute it and/or modify it under the terms of the GNU General Public
CullResult Module::cull()
{
+ if (ModuleDLLManager)
+ ServerInstance->GlobalCulls.AddItem(ModuleDLLManager);
return classbase::cull();
}
void Module::OnBackgroundTimer(time_t) { DetachEvent(I_OnBackgroundTimer); }
ModResult Module::OnPreCommand(std::string&, CommandBase::Params&, LocalUser*, bool) { DetachEvent(I_OnPreCommand); return MOD_RES_PASSTHRU; }
void Module::OnPostCommand(Command*, const CommandBase::Params&, LocalUser*, CmdResult, bool) { DetachEvent(I_OnPostCommand); }
+void Module::OnCommandBlocked(const std::string&, const CommandBase::Params&, LocalUser*) { DetachEvent(I_OnCommandBlocked); }
void Module::OnUserInit(LocalUser*) { DetachEvent(I_OnUserInit); }
void Module::OnUserPostInit(LocalUser*) { DetachEvent(I_OnUserPostInit); }
ModResult Module::OnCheckReady(LocalUser*) { DetachEvent(I_OnCheckReady); return MOD_RES_PASSTHRU; }
void Module::OnPostTopicChange(User*, Channel*, const std::string&) { DetachEvent(I_OnPostTopicChange); }
void Module::OnDecodeMetaData(Extensible*, const std::string&, const std::string&) { DetachEvent(I_OnDecodeMetaData); }
void Module::OnChangeHost(User*, const std::string&) { DetachEvent(I_OnChangeHost); }
+void Module::OnChangeRealHost(User*, const std::string&) { DetachEvent(I_OnChangeRealHost); }
void Module::OnChangeRealName(User*, const std::string&) { DetachEvent(I_OnChangeRealName); }
void Module::OnChangeIdent(User*, const std::string&) { DetachEvent(I_OnChangeIdent); }
void Module::OnAddLine(User*, XLine*) { DetachEvent(I_OnAddLine); }
void Module::OnDelLine(User*, XLine*) { DetachEvent(I_OnDelLine); }
void Module::OnExpireLine(XLine*) { DetachEvent(I_OnExpireLine); }
-void Module::OnCleanup(ExtensionItem::ExtensibleType, Extensible*) { }
+void Module::OnCleanup(ExtensionItem::ExtensibleType, Extensible*) { }
ModResult Module::OnChannelPreDelete(Channel*) { DetachEvent(I_OnChannelPreDelete); return MOD_RES_PASSTHRU; }
void Module::OnChannelDelete(Channel*) { DetachEvent(I_OnChannelDelete); }
void Module::OnBuildNeighborList(User*, IncludeChanList&, std::map<User*,bool>&) { DetachEvent(I_OnBuildNeighborList); }
void Module::OnGarbageCollect() { DetachEvent(I_OnGarbageCollect); }
ModResult Module::OnSetConnectClass(LocalUser* user, ConnectClass* myclass) { DetachEvent(I_OnSetConnectClass); return MOD_RES_PASSTHRU; }
-void Module::OnUserMessage(User*, const MessageTarget&, const MessageDetails&) { DetachEvent(I_OnUserMessage); }
+void Module::OnUserMessage(User*, const MessageTarget&, const MessageDetails&) { DetachEvent(I_OnUserMessage); }
ModResult Module::OnNumeric(User*, const Numeric::Numeric&) { DetachEvent(I_OnNumeric); return MOD_RES_PASSTHRU; }
ModResult Module::OnAcceptConnection(int, ListenSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { DetachEvent(I_OnAcceptConnection); return MOD_RES_PASSTHRU; }
void Module::OnSetUserIP(LocalUser*) { DetachEvent(I_OnSetUserIP); }
stdalgo::erase(*ServerInstance->Modules->NewServices, this);
}
+const char* ServiceProvider::GetTypeString() const
+{
+ switch (service)
+ {
+ case SERVICE_COMMAND:
+ return "command";
+ case SERVICE_MODE:
+ return "mode";
+ case SERVICE_METADATA:
+ return "metadata";
+ case SERVICE_IOHOOK:
+ return "iohook";
+ case SERVICE_DATA:
+ return "data service";
+ case SERVICE_CUSTOM:
+ return "module service";
+ }
+ return "unknown service";
+}
+
ModuleManager::ModuleManager()
{
}
}
/* Eh? this module doesnt exist, probably trying to set priority on an event
- * theyre not attached to.
+ * they're not attached to.
*/
return false;
bool ModuleManager::PrioritizeHooks()
{
/* We give every module a chance to re-prioritize when we introduce a new one,
- * not just the one thats loading, as the new module could affect the preference
+ * not just the one that's loading, as the new module could affect the preference
* of others
*/
for (int tries = 0; tries < 20; tries++)
for (user_hash::const_iterator u = users.begin(); u != users.end(); )
{
User* user = u->second;
- // The module may quit the user (e.g. SSL mod unloading) and that will remove it from the container
+ // The module may quit the user (e.g. TLS (SSL) mod unloading) and that will remove it from the container
++u;
mod->OnCleanup(ExtensionItem::EXT_USER, user);
user->doUnhookExtensions(items);
}
- for(std::multimap<std::string, ServiceProvider*>::iterator i = DataProviders.begin(); i != DataProviders.end(); )
+ for (DataProviderMap::iterator i = DataProviders.begin(); i != DataProviders.end(); )
{
- std::multimap<std::string, ServiceProvider*>::iterator curr = i++;
+ DataProviderMap::iterator curr = i++;
if (curr->second->creator == mod)
+ {
DataProviders.erase(curr);
+ FOREACH_MOD(OnServiceDel, (*curr->second));
+ }
}
dynamic_reference_base::reset_all();
Modules.erase(modfind);
ServerInstance->GlobalCulls.AddItem(mod);
- ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "Module %s unloaded",mod->ModuleSourceFile.c_str());
+ ServerInstance->Logs->Log("MODULE", LOG_DEFAULT, "The %s module was unloaded", mod->ModuleSourceFile.c_str());
ServerInstance->ISupport.Build();
}
UnloadAction(Module* m) : mod(m) {}
void Call() CXX11_OVERRIDE
{
- DLLManager* dll = mod->ModuleDLLManager;
ServerInstance->Modules->DoSafeUnload(mod);
ServerInstance->GlobalCulls.Apply();
- // In pure static mode this is always NULL
- delete dll;
ServerInstance->GlobalCulls.AddItem(this);
}
};
for (ConfigIter i = tags.first; i != tags.second; ++i)
{
ConfigTag* tag = i->second;
- std::string name = ExpandModName(tag->getString("name"));
- this->NewServices = &servicemap[name];
+
+ const std::string shortname = tag->getString("name");
+ if (shortname.empty())
+ continue; // Skip malformed module tags.
// Skip modules which are already loaded.
+ const std::string name = ExpandModName(shortname);
if (Modules.find(name) != Modules.end())
continue;
+ this->NewServices = &servicemap[name];
std::cout << "[" << con_green << "*" << con_reset << "] Loading module:\t" << con_green << name << con_reset << std::endl;
if (!this->Load(name, true))
{
void ModuleManager::AddService(ServiceProvider& item)
{
+ ServerInstance->Logs->Log("SERVICE", LOG_DEBUG, "Adding %s %s provided by %s", item.name.c_str(),
+ item.GetTypeString(), item.creator ? item.creator->ModuleSourceFile.c_str() : "the core");
switch (item.service)
{
case SERVICE_DATA:
void ModuleManager::DelService(ServiceProvider& item)
{
+ ServerInstance->Logs->Log("SERVICE", LOG_DEBUG, "Deleting %s %s provided by %s", item.name.c_str(),
+ item.GetTypeString(), item.creator ? item.creator->ModuleSourceFile.c_str() : "the core");
switch (item.service)
{
case SERVICE_MODE:
case SERVICE_IOHOOK:
{
DelReferent(&item);
- return;
+ break;
}
default:
throw ModuleException("Cannot delete unknown service type");
case SERVICE_DATA:
case SERVICE_IOHOOK:
{
- std::multimap<std::string, ServiceProvider*>::iterator i = DataProviders.find(name);
+ DataProviderMap::iterator i = DataProviders.find(name);
if (i != DataProviders.end() && i->second->service == type)
return i->second;
return NULL;
std::string ModuleManager::ExpandModName(const std::string& modname)
{
- // Transform "callerid" -> "m_callerid.so" unless it already has a ".so" extension,
- // so coremods in the "core_*.so" form aren't changed
- std::string ret = modname;
- if ((modname.length() < 3) || (modname.compare(modname.size() - 3, 3, ".so")))
- ret.insert(0, "m_").append(".so");
- return ret;
+ std::string fullname;
+ if (modname.compare(0, 5, "core_") != 0 && modname.compare(0, 2, "m_") != 0)
+ fullname.append("m_");
+ fullname.append(modname);
+ if (modname.length() < 3 || modname.compare(modname.size() - 3, 3, ".so") != 0)
+ fullname.append(".so");
+ return fullname;
}
dynamic_reference_base::dynamic_reference_base(Module* Creator, const std::string& Name)
{
// Because find() may return any element with a matching key in case count(key) > 1 use lower_bound()
// to ensure a dynref with the same name as another one resolves to the same object
- std::multimap<std::string, ServiceProvider*>::iterator i = ServerInstance->Modules.DataProviders.lower_bound(name);
+ ModuleManager::DataProviderMap::iterator i = ServerInstance->Modules.DataProviders.lower_bound(name);
if ((i != ServerInstance->Modules.DataProviders.end()) && (i->first == this->name))
{
ServiceProvider* newvalue = i->second;
void ModuleManager::DelReferent(ServiceProvider* service)
{
- for (std::multimap<std::string, ServiceProvider*>::iterator i = DataProviders.begin(); i != DataProviders.end(); )
+ for (DataProviderMap::iterator i = DataProviders.begin(); i != DataProviders.end(); )
{
ServiceProvider* curr = i->second;
if (curr == service)