diff options
| author | 2022-01-07 17:12:42 +0000 | |
|---|---|---|
| committer | 2022-01-07 17:16:50 +0000 | |
| commit | 52cc8a418307ae7a551d23e6bd2d367b544e7bf9 (patch) | |
| tree | 9fff020964190f33174e78ff6201381be577d0b3 /src | |
| parent | Merge branch 'insp3' into master. (diff) | |
Refactor CoreException and ModuleException.
Diffstat (limited to 'src')
49 files changed, 210 insertions, 177 deletions
diff --git a/src/base.cpp b/src/base.cpp index 305f8328b..46cabef21 100644 --- a/src/base.cpp +++ b/src/base.cpp @@ -65,8 +65,3 @@ usecountbase::~usecountbase() void ServiceProvider::RegisterService() { } - -ModuleException::ModuleException(const std::string &message, Module* who) - : CoreException(message, who ? who->ModuleSourceFile : "A Module") -{ -} diff --git a/src/commands.cpp b/src/commands.cpp index 5372c9995..4ad6ff2a9 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -53,7 +53,7 @@ Command::~Command() void Command::RegisterService() { if (!ServerInstance->Parser.AddCommand(this)) - throw ModuleException("Command already exists: " + name); + throw ModuleException(creator, "Command already exists: " + name); } void Command::TellNotEnoughParameters(LocalUser* user, const Params& parameters) diff --git a/src/coremods/core_channel/core_channel.cpp b/src/coremods/core_channel/core_channel.cpp index 8859b44f2..5ecae73a3 100644 --- a/src/coremods/core_channel/core_channel.cpp +++ b/src/coremods/core_channel/core_channel.cpp @@ -169,7 +169,7 @@ class CoreModChannel final { std::string::size_type pos = current.find(':'); if (pos == std::string::npos || (pos + 2) > current.size()) - throw ModuleException("Invalid exemptchanops value '" + current + "' at " + optionstag->source.str()); + throw ModuleException(this, "Invalid exemptchanops value '" + current + "' at " + optionstag->source.str()); const std::string restriction = current.substr(0, pos); const char prefix = current[pos + 1]; diff --git a/src/coremods/core_dns.cpp b/src/coremods/core_dns.cpp index c23f43c17..49560e57d 100644 --- a/src/coremods/core_dns.cpp +++ b/src/coremods/core_dns.cpp @@ -45,10 +45,13 @@ using namespace DNS; class Packet final : public Query { + private: + const Module* creator; + void PackName(unsigned char* output, unsigned short output_size, unsigned short& pos, const std::string& name) { if (pos + name.length() + 2 > output_size) - throw Exception("Unable to pack name"); + throw Exception(creator, "Unable to pack name"); ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Packing name " + name); @@ -72,7 +75,7 @@ class Packet final bool compressed = false; if (pos_ptr >= input_size) - throw Exception("Unable to unpack name - no input"); + throw Exception(creator, "Unable to unpack name - no input"); while (input[pos_ptr] > 0) { @@ -81,9 +84,9 @@ class Packet final if (offset & POINTER) { if ((offset & POINTER) != POINTER) - throw Exception("Unable to unpack name - bogus compression header"); + throw Exception(creator, "Unable to unpack name - bogus compression header"); if (pos_ptr + 1 >= input_size) - throw Exception("Unable to unpack name - bogus compression header"); + throw Exception(creator, "Unable to unpack name - bogus compression header"); /* Place pos at the second byte of the first (farthest) compression pointer */ if (compressed == false) @@ -96,13 +99,13 @@ class Packet final /* Pointers can only go back */ if (pos_ptr >= lowest_ptr) - throw Exception("Unable to unpack name - bogus compression pointer"); + throw Exception(creator, "Unable to unpack name - bogus compression pointer"); lowest_ptr = pos_ptr; } else { if (pos_ptr + offset + 1 >= input_size) - throw Exception("Unable to unpack name - offset too large"); + throw Exception(creator, "Unable to unpack name - offset too large"); if (!name.empty()) name += "."; for (unsigned i = 1; i <= offset; ++i) @@ -119,7 +122,7 @@ class Packet final ++pos; if (name.empty()) - throw Exception("Unable to unpack name - no name"); + throw Exception(creator, "Unable to unpack name - no name"); ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Unpack name " + name); @@ -133,7 +136,7 @@ class Packet final q.name = this->UnpackName(input, input_size, pos); if (pos + 4 > input_size) - throw Exception("Unable to unpack question"); + throw Exception(creator, "Unable to unpack question"); q.type = static_cast<QueryType>(input[pos] << 8 | input[pos + 1]); pos += 2; @@ -149,7 +152,7 @@ class Packet final ResourceRecord record = static_cast<ResourceRecord>(this->UnpackQuestion(input, input_size, pos)); if (pos + 6 > input_size) - throw Exception("Unable to unpack resource record"); + throw Exception(creator, "Unable to unpack resource record"); record.ttl = (input[pos] << 24) | (input[pos + 1] << 16) | (input[pos + 2] << 8) | input[pos + 3]; pos += 4; @@ -162,7 +165,7 @@ class Packet final case QUERY_A: { if (pos + 4 > input_size) - throw Exception("Unable to unpack A resource record"); + throw Exception(creator, "Unable to unpack A resource record"); irc::sockets::sockaddrs addrs; memset(&addrs, 0, sizeof(addrs)); @@ -177,7 +180,7 @@ class Packet final case QUERY_AAAA: { if (pos + 16 > input_size) - throw Exception("Unable to unpack AAAA resource record"); + throw Exception(creator, "Unable to unpack AAAA resource record"); irc::sockets::sockaddrs addrs; memset(&addrs, 0, sizeof(addrs)); @@ -196,27 +199,27 @@ class Packet final { record.rdata = this->UnpackName(input, input_size, pos); if (!InspIRCd::IsHost(record.rdata)) - throw Exception("Invalid name in CNAME/PTR resource record"); + throw Exception(creator, "Invalid name in CNAME/PTR resource record"); break; } case QUERY_TXT: { if (pos + rdlength > input_size) - throw Exception("Unable to unpack TXT resource record"); + throw Exception(creator, "Unable to unpack TXT resource record"); record.rdata = std::string(reinterpret_cast<const char *>(input + pos), rdlength); pos += rdlength; if (record.rdata.find_first_of("\r\n\0", 0, 3) != std::string::npos) - throw Exception("Invalid character in TXT resource record"); + throw Exception(creator, "Invalid character in TXT resource record"); break; } case QUERY_SRV: { if (rdlength < 6 || pos + rdlength > input_size) - throw Exception("Unable to unpack SRV resource record"); + throw Exception(creator, "Unable to unpack SRV resource record"); auto srv = std::make_shared<Record::SRV>(); @@ -231,7 +234,7 @@ class Packet final srv->host = this->UnpackName(input, input_size, pos); if (!InspIRCd::IsHost(srv->host)) - throw Exception("Invalid name in SRV resource record"); + throw Exception(creator, "Invalid name in SRV resource record"); record.rdata = InspIRCd::Format("%u %u %u %s", srv->priority, srv->weight, srv->port, srv->host.c_str()); record.rdataobj = srv; @@ -240,7 +243,7 @@ class Packet final default: { if (pos + rdlength > input_size) - throw Exception("Unable to skip resource record"); + throw Exception(creator, "Unable to skip resource record"); pos += rdlength; break; @@ -264,10 +267,15 @@ class Packet final /* Flags on the packet */ unsigned short flags = 0; + Packet(const Module* mod) + : creator(mod) + { + } + void Fill(const unsigned char* input, const unsigned short len) { if (len < HEADER_LENGTH) - throw Exception("Unable to fill packet"); + throw Exception(creator, "Unable to fill packet"); unsigned short packet_pos = 0; @@ -292,7 +300,7 @@ class Packet final ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "qdcount: " + ConvToStr(qdcount) + " ancount: " + ConvToStr(ancount) + " nscount: " + ConvToStr(nscount) + " arcount: " + ConvToStr(arcount)); if (qdcount != 1) - throw Exception("Question count != 1 in incoming packet"); + throw Exception(creator, "Question count != 1 in incoming packet"); this->question = this->UnpackQuestion(input, len, packet_pos); @@ -303,7 +311,7 @@ class Packet final unsigned short Pack(unsigned char* output, unsigned short output_size) { if (output_size < HEADER_LENGTH) - throw Exception("Unable to pack oversized packet header"); + throw Exception(creator, "Unable to pack oversized packet header"); unsigned short pos = 0; @@ -327,7 +335,7 @@ class Packet final { irc::sockets::sockaddrs ip; if (!irc::sockets::aptosa(q.name, 0, ip)) - throw Exception("Unable to pack packet with malformed IP for PTR lookup"); + throw Exception(creator, "Unable to pack packet with malformed IP for PTR lookup"); if (q.name.find(':') != std::string::npos) { @@ -358,7 +366,7 @@ class Packet final this->PackName(output, output_size, pos, q.name); if (pos + 4 >= output_size) - throw Exception("Unable to pack oversized packet body"); + throw Exception(creator, "Unable to pack oversized packet body"); short s = htons(q.type); memcpy(&output[pos], &s, 2); @@ -493,7 +501,7 @@ class MyManager final void Process(DNS::Request* req) override { if ((unloading) || (req->creator->dying)) - throw Exception("Module is being unloaded"); + throw Exception(creator, "Module is being unloaded"); if (!HasFd()) { @@ -527,7 +535,7 @@ class MyManager final } if (id == -1) - throw Exception("DNS: All ids are in use"); + throw Exception(creator, "DNS: All ids are in use"); break; } @@ -537,7 +545,7 @@ class MyManager final req->id = id; this->requests[req->id] = req; - Packet p; + Packet p(creator); p.flags = QUERYFLAGS_RD; p.id = req->id; p.question = req->question; @@ -559,7 +567,7 @@ class MyManager final req->question.name = p.question.name; if (SocketEngine::SendTo(this, buffer, len, 0, this->myserver) != len) - throw Exception("DNS: Unable to send query"); + throw Exception(creator, "DNS: Unable to send query"); // Add timer for timeout ServerInstance->Timers.AddTimer(req); @@ -647,7 +655,7 @@ class MyManager final return; } - Packet recv_packet; + Packet recv_packet(creator); bool valid = false; try diff --git a/src/extensible.cpp b/src/extensible.cpp index b69221570..641d62337 100644 --- a/src/extensible.cpp +++ b/src/extensible.cpp @@ -97,7 +97,7 @@ ExtensionItem::ExtensionItem(Module* mod, const std::string& Key, ExtensionType void ExtensionItem::RegisterService() { if (!ServerInstance->Extensions.Register(this)) - throw ModuleException("Extension already exists: " + name); + throw ModuleException(creator, "Extension already exists: " + name); } void* ExtensionItem::GetRaw(const Extensible* container) const diff --git a/src/listmode.cpp b/src/listmode.cpp index 8b19840f1..3981abad5 100644 --- a/src/listmode.cpp +++ b/src/listmode.cpp @@ -73,7 +73,7 @@ void ListModeBase::DoRehash() ListLimit limit(c->getString("chan", "*", 1), c->getUInt("limit", DEFAULT_LIST_SIZE)); if (limit.mask.empty()) - throw ModuleException(InspIRCd::Format("<maxlist:chan> is empty, at %s", c->source.str().c_str())); + throw ModuleException(creator, InspIRCd::Format("<maxlist:chan> is empty, at %s", c->source.str().c_str())); if (limit.mask == "*" || limit.mask == "#*") seen_default = true; diff --git a/src/mode.cpp b/src/mode.cpp index 5fa1e9332..5bd3ba213 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -560,22 +560,24 @@ void ModeParser::CleanMask(std::string &mask) } } -ModeHandler::Id ModeParser::AllocateModeId(ModeType mt) +ModeHandler::Id ModeParser::AllocateModeId(ModeHandler* mh) { for (ModeHandler::Id i = 0; i != MODEID_MAX; ++i) { - if (!modehandlersbyid[mt][i]) + if (!modehandlersbyid[mh->GetModeType()][i]) return i; } - throw ModuleException("Out of ModeIds"); + throw ModuleException(mh->creator, "Out of mode ids"); } void ModeParser::AddMode(ModeHandler* mh) { if (!ModeParser::IsModeChar(mh->GetModeChar())) - throw ModuleException(InspIRCd::Format("Mode letter for %s is invalid: %c", + { + throw ModuleException(mh->creator, InspIRCd::Format("Mode letter for %s is invalid: %c", mh->name.c_str(), mh->GetModeChar())); + } /* A mode prefix of ',' is not acceptable, it would fuck up server to server. * A mode prefix of ':' will fuck up both server to server, and client to server. @@ -585,31 +587,37 @@ void ModeParser::AddMode(ModeHandler* mh) if (pm) { if ((pm->GetPrefix() > 126) || (pm->GetPrefix() == ',') || (pm->GetPrefix() == ':') || ServerInstance->Channels.IsPrefix(pm->GetPrefix())) - throw ModuleException(InspIRCd::Format("Mode prefix for %s is invalid: %c", + { + throw ModuleException(mh->creator, InspIRCd::Format("Mode prefix for %s is invalid: %c", mh->name.c_str(), pm->GetPrefix())); + } PrefixMode* otherpm = FindPrefix(pm->GetPrefix()); if (otherpm) - throw ModuleException(InspIRCd::Format("Mode prefix for %s already used by %s from %s: %c", + { + throw ModuleException(mh->creator, InspIRCd::Format("Mode prefix for %s already used by %s from %s: %c", mh->name.c_str(), otherpm->name.c_str(), otherpm->creator->ModuleSourceFile.c_str(), pm->GetPrefix())); + } } ModeHandler*& slot = modehandlers[mh->GetModeType()][mh->GetModeChar()-65]; if (slot) - throw ModuleException(InspIRCd::Format("Mode letter for %s already used by %s from %s: %c", + { + throw ModuleException(mh->creator, InspIRCd::Format("Mode letter for %s already used by %s from %s: %c", mh->name.c_str(), slot->name.c_str(), slot->creator->ModuleSourceFile.c_str(), mh->GetModeChar())); + } // The mode needs an id if it is either a user mode, a simple mode (flag) or a parameter mode. // Otherwise (for listmodes and prefix modes) the id remains MODEID_MAX, which is invalid. ModeHandler::Id modeid = MODEID_MAX; if ((mh->GetModeType() == MODETYPE_USER) || (mh->IsParameterMode()) || (!mh->IsListMode())) - modeid = AllocateModeId(mh->GetModeType()); + modeid = AllocateModeId(mh); std::pair<ModeHandlerMap::iterator, bool> res = modehandlersbyname[mh->GetModeType()].emplace(mh->name, mh); if (!res.second) { ModeHandler* othermh = res.first->second; - throw ModuleException(InspIRCd::Format("Mode name %s already used by %c from %s", + throw ModuleException(mh->creator, InspIRCd::Format("Mode name %s already used by %c from %s", mh->name.c_str(), othermh->GetModeChar(), othermh->creator->ModuleSourceFile.c_str())); } diff --git a/src/modules.cpp b/src/modules.cpp index b916f3d27..28a231268 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -589,7 +589,7 @@ void ModuleManager::AddService(ServiceProvider& item) case SERVICE_IOHOOK: { if ((!item.name.compare(0, 5, "mode/", 5)) || (!item.name.compare(0, 6, "umode/", 6))) - throw ModuleException("The \"mode/\" and the \"umode\" service name prefixes are reserved."); + throw ModuleException(item.creator, "The \"mode/\" and the \"umode\" service name prefixes are reserved."); DataProviders.emplace(item.name, &item); std::string::size_type slash = item.name.find('/'); @@ -617,7 +617,7 @@ void ModuleManager::DelService(ServiceProvider& item) { case SERVICE_MODE: if (!ServerInstance->Modes.DelMode(static_cast<ModeHandler*>(&item))) - throw ModuleException("Mode "+std::string(item.name)+" does not exist."); + throw ModuleException(item.creator, "Mode " + std::string(item.name) + " does not exist."); [[fallthrough]]; case SERVICE_DATA: case SERVICE_IOHOOK: @@ -626,7 +626,7 @@ void ModuleManager::DelService(ServiceProvider& item) break; } default: - throw ModuleException("Cannot delete unknown service type"); + throw ModuleException(item.creator, "Cannot delete unknown service type"); } FOREACH_MOD(OnServiceDel, (item)); @@ -646,7 +646,7 @@ ServiceProvider* ModuleManager::FindService(ServiceType type, const std::string& } // TODO implement finding of the other types default: - throw ModuleException("Cannot find unknown service type"); + throw CoreException("Cannot find unknown service type"); } } diff --git a/src/modules/extra/m_argon2.cpp b/src/modules/extra/m_argon2.cpp index 2a5341cd8..80289286e 100644 --- a/src/modules/extra/m_argon2.cpp +++ b/src/modules/extra/m_argon2.cpp @@ -144,7 +144,7 @@ class HashArgon2 final config.version); if (argonResult != ARGON2_OK) - throw ModuleException("Argon2 hashing failed!: " + std::string(argon2_error_message(argonResult))); + throw ModuleException(creator, "Argon2 hashing failed: " + std::string(argon2_error_message(argonResult))); // This isn't the raw version, but we don't have // the facilities to juggle around the extra state required diff --git a/src/modules/extra/m_geo_maxmind.cpp b/src/modules/extra/m_geo_maxmind.cpp index 56ccffef5..bff8c4b78 100644 --- a/src/modules/extra/m_geo_maxmind.cpp +++ b/src/modules/extra/m_geo_maxmind.cpp @@ -173,7 +173,7 @@ class ModuleGeoMaxMind final MMDB_s mmdb; int result = MMDB_open(file.c_str(), MMDB_MODE_MMAP, &mmdb); if (result != MMDB_SUCCESS) - throw ModuleException(InspIRCd::Format("Unable to load the MaxMind database (%s): %s", + throw ModuleException(this, InspIRCd::Format("Unable to load the MaxMind database (%s): %s", file.c_str(), MMDB_strerror(result))); // Swap the new database with the old database. diff --git a/src/modules/extra/m_mysql.cpp b/src/modules/extra/m_mysql.cpp index 05637a6a6..23bbdce3d 100644 --- a/src/modules/extra/m_mysql.cpp +++ b/src/modules/extra/m_mysql.cpp @@ -432,7 +432,7 @@ class SQLConnection final void ModuleSQL::init() { if (mysql_library_init(0, NULL, NULL)) - throw ModuleException("Unable to initialise the MySQL library!"); + throw ModuleException(this, "Unable to initialise the MySQL library!"); Dispatcher = new DispatcherThread(this); Dispatcher->Start(); diff --git a/src/modules/extra/m_regex_pcre.cpp b/src/modules/extra/m_regex_pcre.cpp index 368e3618d..681dd4021 100644 --- a/src/modules/extra/m_regex_pcre.cpp +++ b/src/modules/extra/m_regex_pcre.cpp @@ -43,7 +43,7 @@ class PCREPattern final pcre2_code* regex; public: - PCREPattern(const std::string& pattern, uint8_t options) + PCREPattern(const Module* mod, const std::string& pattern, uint8_t options) : Regex::Pattern(pattern, options) { int flags = 0; @@ -57,7 +57,7 @@ class PCREPattern final { PCRE2_UCHAR errorstr[128]; pcre2_get_error_message(errorcode, errorstr, sizeof errorstr); - throw Regex::Exception(pattern, reinterpret_cast<const char*>(errorstr), erroroffset); + throw Regex::Exception(mod, pattern, reinterpret_cast<const char*>(errorstr), erroroffset); } } diff --git a/src/modules/extra/m_regex_posix.cpp b/src/modules/extra/m_regex_posix.cpp index eaa5b37ee..bbde6ab35 100644 --- a/src/modules/extra/m_regex_posix.cpp +++ b/src/modules/extra/m_regex_posix.cpp @@ -35,7 +35,7 @@ class POSIXPattern final regex_t regex; public: - POSIXPattern(const std::string& pattern, uint8_t options) + POSIXPattern(const Module* mod, const std::string& pattern, uint8_t options) : Regex::Pattern(pattern, options) { int flags = REG_EXTENDED | REG_NOSUB; @@ -54,7 +54,7 @@ class POSIXPattern final regerror(error, ®ex, &errormsg[0], errormsg.size()); regfree(®ex); - throw Regex::Exception(pattern, std::string(&errormsg[0], errormsg.size())); + throw Regex::Exception(mod, pattern, std::string(&errormsg[0], errormsg.size())); } ~POSIXPattern() override diff --git a/src/modules/extra/m_regex_re2.cpp b/src/modules/extra/m_regex_re2.cpp index 78ccccd0a..a9f1843bb 100644 --- a/src/modules/extra/m_regex_re2.cpp +++ b/src/modules/extra/m_regex_re2.cpp @@ -46,12 +46,12 @@ class RE2Pattern final } public: - RE2Pattern(const std::string& pattern, uint8_t options) + RE2Pattern(const Module* mod, const std::string& pattern, uint8_t options) : Regex::Pattern(pattern, options) , regex(pattern, BuildOptions(options)) { if (!regex.ok()) - throw Regex::Exception(pattern, regex.error()); + throw Regex::Exception(mod, pattern, regex.error()); } bool IsMatch(const std::string& text) override diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index d5cd626a0..1db07d94a 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -81,8 +81,10 @@ namespace GnuTLS : public ModuleException { public: - Exception(const std::string& reason) - : ModuleException(reason) { } + Exception(const std::string& msg) + : ModuleException(thismod, msg) + { + } }; void ThrowOnError(int errcode, const char* msg) @@ -1108,7 +1110,7 @@ class ModuleSSLGnuTLS final auto tags = ServerInstance->Config->ConfTags("sslprofile"); if (tags.empty()) - throw ModuleException("You have not specified any <sslprofile> tags that are usable by this module!"); + throw ModuleException(this, "You have not specified any <sslprofile> tags that are usable by this module!"); for (const auto& [_, tag] : tags) { @@ -1133,7 +1135,7 @@ class ModuleSSLGnuTLS final } catch (CoreException& ex) { - throw ModuleException("Error while initializing TLS profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); + throw ModuleException(this, "Error while initializing TLS profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); } newprofiles.push_back(prov); diff --git a/src/modules/extra/m_ssl_mbedtls.cpp b/src/modules/extra/m_ssl_mbedtls.cpp index 8e1c382a9..f58f519db 100644 --- a/src/modules/extra/m_ssl_mbedtls.cpp +++ b/src/modules/extra/m_ssl_mbedtls.cpp @@ -51,14 +51,18 @@ #include <mbedtls/debug.h> #endif +static Module* thismod; + namespace mbedTLS { class Exception final : public ModuleException { public: - Exception(const std::string& reason) - : ModuleException(reason) { } + Exception(const std::string& msg) + : ModuleException(thismod, msg) + { + } }; std::string ErrorToString(int errcode) @@ -880,7 +884,7 @@ class ModuleSSLmbedTLS final auto tags = ServerInstance->Config->ConfTags("sslprofile"); if (tags.empty()) - throw ModuleException("You have not specified any <sslprofile> tags that are usable by this module!"); + throw ModuleException(this, "You have not specified any <sslprofile> tags that are usable by this module!"); for (const auto& [_, tag] : tags) { @@ -905,7 +909,7 @@ class ModuleSSLmbedTLS final } catch (CoreException& ex) { - throw ModuleException("Error while initializing TLS profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); + throw ModuleException(this, "Error while initializing TLS profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); } newprofiles.push_back(prov); @@ -923,6 +927,7 @@ class ModuleSSLmbedTLS final ModuleSSLmbedTLS() : Module(VF_VENDOR, "Allows TLS encrypted connections using the mbedTLS library.") { + thismod = this; } void init() override @@ -932,7 +937,7 @@ class ModuleSSLmbedTLS final ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "mbedTLS lib version %s module was compiled for " MBEDTLS_VERSION_STRING, verbuf); if (!ctr_drbg.Seed(entropy)) - throw ModuleException("CTR DRBG seed failed"); + throw ModuleException(this, "CTR DRBG seed failed"); } void ReadConfig(ConfigStatus& status) override diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 98cb1527f..d4db4d180 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -54,6 +54,7 @@ static bool SelfSigned = false; static int exdataindex; +static Module* thismod; char* get_error() { @@ -69,8 +70,10 @@ namespace OpenSSL : public ModuleException { public: - Exception(const std::string& reason) - : ModuleException(reason) { } + Exception(const std::string& msg) + : ModuleException(thismod, msg) + { + } }; class DHParams final @@ -211,14 +214,14 @@ namespace OpenSSL } else if (!stdalgo::string::equalsci(crlmode, "leaf")) { - throw ModuleException("Unknown mode '" + crlmode + "'; expected either 'chain' (default) or 'leaf'"); + throw ModuleException(thismod, "Unknown mode '" + crlmode + "'; expected either 'chain' (default) or 'leaf'"); } /* Load CRL files */ X509_STORE* store = SSL_CTX_get_cert_store(ctx); if (!store) { - throw ModuleException("Unable to get X509_STORE from TLS context; this should never happen"); + throw ModuleException(thismod, "Unable to get X509_STORE from TLS context; this should never happen"); } ERR_clear_error(); if (!X509_STORE_load_locations(store, @@ -226,13 +229,13 @@ namespace OpenSSL crlpath.empty() ? NULL : crlpath.c_str())) { unsigned long err = ERR_get_error(); - throw ModuleException("Unable to load CRL file '" + crlfile + "' or CRL path '" + crlpath + "': '" + (err ? ERR_error_string(err, NULL) : "unknown") + "'"); + throw ModuleException(thismod, "Unable to load CRL file '" + crlfile + "' or CRL path '" + crlpath + "': '" + (err ? ERR_error_string(err, NULL) : "unknown") + "'"); } /* Set CRL mode */ if (X509_STORE_set_flags(store, crlflags) != 1) { - throw ModuleException("Unable to set X509 CRL flags"); + throw ModuleException(thismod, "Unable to set X509 CRL flags"); } } @@ -930,7 +933,7 @@ class ModuleSSLOpenSSL final ProfileList newprofiles; auto tags = ServerInstance->Config->ConfTags("sslprofile"); if (tags.empty()) - throw ModuleException("You have not specified any <sslprofile> tags that are usable by this module!"); + throw ModuleException(this, "You have not specified any <sslprofile> tags that are usable by this module!"); for (const auto& [_, tag] : tags) { @@ -954,7 +957,7 @@ class ModuleSSLOpenSSL final } catch (CoreException& ex) { - throw ModuleException("Error while initializing TLS profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); + throw ModuleException(this, "Error while initializing TLS profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); } newprofiles.push_back(prov); @@ -973,6 +976,8 @@ class ModuleSSLOpenSSL final // Initialize OpenSSL OPENSSL_init_ssl(0, NULL); biomethods = OpenSSL::BIOMethod::alloc(); + + thismod = this; } ~ModuleSSLOpenSSL() override @@ -988,7 +993,7 @@ class ModuleSSLOpenSSL final char exdatastr[] = "inspircd"; exdataindex = SSL_get_ex_new_index(0, exdatastr, NULL, NULL, NULL); if (exdataindex < 0) - throw ModuleException("Failed to register application specific data"); + throw ModuleException(this, "Failed to register application specific data"); } void ReadConfig(ConfigStatus& status) override diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index 8ce6a5a9f..4dc1aa477 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -89,11 +89,11 @@ class ModuleAlias final Alias a; a.AliasedCommand = tag->getString("text"); if (a.AliasedCommand.empty()) - throw ModuleException("<alias:text> is empty! at " + tag->source.str()); + throw ModuleException(this, "<alias:text> is empty! at " + tag->source.str()); tag->readString("replace", a.ReplaceFormat, true); if (a.ReplaceFormat.empty()) - throw ModuleException("<alias:replace> is empty! at " + tag->source.str()); + throw ModuleException(this, "<alias:replace> is empty! at " + tag->source.str()); a.RequiredNick = tag->getString("requires"); a.ServiceOnly = tag->getBool("service", tag->getBool("uline")); diff --git a/src/modules/m_bcrypt.cpp b/src/modules/m_bcrypt.cpp index 5768f42a8..c6eebbb96 100644 --- a/src/modules/m_bcrypt.cpp +++ b/src/modules/m_bcrypt.cpp @@ -37,7 +37,7 @@ class BCryptProvider final char salt[32]; if (!_crypt_gensalt_blowfish_rn("$2a$", rounds, entropy, sizeof(entropy), salt, sizeof(salt))) - throw ModuleException("Could not generate salt - this should never happen"); + throw ModuleException(creator, "Could not generate salt - this should never happen"); return salt; } diff --git a/src/modules/m_cap.cpp b/src/modules/m_cap.cpp index 15d2f9ca4..ccb01851f 100644 --- a/src/modules/m_cap.cpp +++ b/src/modules/m_cap.cpp @@ -83,7 +83,7 @@ class Cap::ManagerImpl final if (!(used & bit)) return bit; } - throw ModuleException("Too many caps"); + throw ModuleException(creator, "Too many caps"); } void OnReloadModuleSave(Module* mod, ReloadModule::CustomData& cd) override diff --git a/src/modules/m_chanlog.cpp b/src/modules/m_chanlog.cpp index 84cea2d0d..c0be029b1 100644 --- a/src/modules/m_chanlog.cpp +++ b/src/modules/m_chanlog.cpp @@ -51,7 +51,7 @@ class ModuleChanLog final std::string snomasks = tag->getString("snomasks"); if (channel.empty() || snomasks.empty()) { - throw ModuleException("Malformed chanlog tag at " + tag->source.str()); + throw ModuleException(this, "Malformed chanlog tag at " + tag->source.str()); } for (const auto& snomask : snomasks) diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp index f52c3bc54..03d4a9db2 100644 --- a/src/modules/m_cloaking.cpp +++ b/src/modules/m_cloaking.cpp @@ -469,7 +469,7 @@ class ModuleCloaking final { auto tags = ServerInstance->Config->ConfTags("cloak"); if (tags.empty()) - throw ModuleException("You have loaded the cloaking module but not configured any <cloak> tags!"); + throw ModuleException(this, "You have loaded the cloaking module but not configured any <cloak> tags!"); bool firstcloak = true; std::vector<CloakInfo> newcloaks; @@ -478,11 +478,11 @@ class ModuleCloaking final // Ensure that we have the <cloak:key> parameter. const std::string key = tag->getString("key"); if (key.empty()) - throw ModuleException("You have not defined a cloaking key. Define <cloak:key> as a " + ConvToStr(minkeylen) + "+ character network-wide secret, at " + tag->source.str()); + throw ModuleException(this, "You have not defined a cloaking key. Define <cloak:key> as a " + ConvToStr(minkeylen) + "+ character network-wide secret, at " + tag->source.str()); // If we are the first cloak method then mandate a strong key. if (firstcloak && key.length() < minkeylen) - throw ModuleException("Your cloaking key is not secure. It should be at least " + ConvToStr(minkeylen) + " characters long, at " + tag->source.str()); + throw ModuleException(this, "Your cloaking key is not secure. It should be at least " + ConvToStr(minkeylen) + " characters long, at " + tag->source.str()); firstcloak = false; const bool ignorecase = tag->getBool("ignorecase"); @@ -497,7 +497,7 @@ class ModuleCloaking final else if (stdalgo::string::equalsci(mode, "full")) newcloaks.emplace_back(MODE_OPAQUE, key, prefix, suffix, ignorecase); else - throw ModuleException(mode + " is an invalid value for <cloak:mode>; acceptable values are 'half' and 'full', at " + tag->source.str()); + throw ModuleException(this, mode + " is an invalid value for <cloak:mode>; acceptable values are 'half' and 'full', at " + tag->source.str()); } // The cloak configuration was valid so we can apply it. diff --git a/src/modules/m_codepage.cpp b/src/modules/m_codepage.cpp index 5d75e18d7..78b67bcf1 100644 --- a/src/modules/m_codepage.cpp +++ b/src/modules/m_codepage.cpp @@ -262,18 +262,18 @@ class ModuleCodepage final const std::string name = codepagetag->getString("name"); if (name.empty()) - throw ModuleException("<codepage:name> is a required field!"); + throw ModuleException(this, "<codepage:name> is a required field!"); std::unique_ptr<Codepage> newcodepage = std::make_unique<SingleByteCodepage>(); for (const auto& [_, tag] : ServerInstance->Config->ConfTags("cpchars")) { unsigned long begin = tag->getUInt("begin", tag->getUInt("index", 0)); if (!begin) - throw ModuleException("<cpchars> tag without index or begin specified at " + tag->source.str()); + throw ModuleException(this, "<cpchars> tag without index or begin specified at " + tag->source.str()); unsigned long end = tag->getUInt("end", begin); if (begin > end) - throw ModuleException("<cpchars:begin> must be lower than <cpchars:end> at " + tag->source.str()); + throw ModuleException(this, "<cpchars:begin> must be lower than <cpchars:end> at " + tag->source.str()); bool front = tag->getBool("front", false); for (unsigned long pos = begin; pos <= end; ++pos) @@ -287,11 +287,11 @@ class ModuleCodepage final break; case Codepage::ACR_NOT_VALID: - throw ModuleException(InspIRCd::Format("<cpchars> tag contains a forbidden character: %lu at %s", + throw ModuleException(this, InspIRCd::Format("<cpchars> tag contains a forbidden character: %lu at %s", pos, tag->source.str().c_str())); case Codepage::ACR_NOT_VALID_AT_FRONT: - throw ModuleException(InspIRCd::Format("<cpchars> tag contains a forbidden front character: %lu at %s", + throw ModuleException(this, InspIRCd::Format("<cpchars> tag contains a forbidden front character: %lu at %s", pos, tag->source.str().c_str())); } } @@ -301,14 +301,14 @@ class ModuleCodepage final { unsigned long lower = tag->getUInt("lower", 0); if (!lower) - throw ModuleException("<cpcase:lower> is required at " + tag->source.str()); + throw ModuleException(this, "<cpcase:lower> is required at " + tag->source.str()); unsigned long upper = tag->getUInt("upper", 0); if (!upper) - throw ModuleException("<cpcase:upper> is required at " + tag->source.str()); + throw ModuleException(this, "<cpcase:upper> is required at " + tag->source.str()); if (!newcodepage->Map(upper, lower)) - throw ModuleException("Malformed <cpcase> tag at " + tag->source.str()); + throw ModuleException(this, "Malformed <cpcase> tag at " + tag->source.str()); ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Marked %lu (%.4s) as the lower case version of %lu (%.4s)", lower, reinterpret_cast<unsigned char*>(&lower), upper, reinterpret_cast<unsigned char*>(&upper)); diff --git a/src/modules/m_customprefix.cpp b/src/modules/m_customprefix.cpp index 52af6e846..b077ef7e9 100644 --- a/src/modules/m_customprefix.cpp +++ b/src/modules/m_customprefix.cpp @@ -61,20 +61,20 @@ class ModuleCustomPrefix final { const std::string name = tag->getString("name"); if (name.empty()) - throw ModuleException("<customprefix:name> must be specified at " + tag->source.str()); + throw ModuleException(this, "<customprefix:name> must be specified at " + tag->source.str()); if (name.find(' ') != std::string::npos) - throw ModuleException("<customprefix:name> must not contain spaces at " + tag->source.str()); + throw ModuleException(this, "<customprefix:name> must not contain spaces at " + tag->source.str()); if (tag->getBool("change")) { ModeHandler* mh = ServerInstance->Modes.FindMode(name, MODETYPE_CHANNEL); if (!mh) - throw ModuleException("<customprefix:change> specified for a nonexistent mode at " + tag->source.str()); + throw ModuleException(this, "<customprefix:change> specified for a nonexistent mode at " + tag->source.str()); PrefixMode* pm = mh->IsPrefixMode(); if (!pm) - throw ModuleException("<customprefix:change> specified for a non-prefix mode at " + tag->source.str()); + throw ModuleException(this, "<customprefix:change> specified for a non-prefix mode at " + tag->source.str()); unsigned int rank = static_cast<unsigned int>(tag->getUInt("rank", pm->GetPrefixRank(), 0, UINT_MAX)); unsigned int setrank = static_cast<unsigned int>(tag->getUInt("ranktoset", pm->GetLevelRequired(true), rank, UINT_MAX)); @@ -89,11 +89,11 @@ class ModuleCustomPrefix final const std::string letter = tag->getString("letter"); if (letter.length() != 1) - throw ModuleException("<customprefix:letter> must be set to a mode character at " + tag->source.str()); + throw ModuleException(this, "<customprefix:letter> must be set to a mode character at " + tag->source.str()); const std::string prefix = tag->getString("prefix"); if (prefix.length() != 1) - throw ModuleException("<customprefix:prefix> must be set to a mode prefix at " + tag->source.str()); + throw ModuleException(this, "<customprefix:prefix> must be set to a mode prefix at " + tag->source.str()); try { @@ -103,7 +103,7 @@ class ModuleCustomPrefix final } catch (ModuleException& e) { - throw ModuleException(e.GetReason() + " (while creating mode from " + tag->source.str() + ")"); + throw ModuleException(this, e.GetReason() + " (while creating mode from " + tag->source.str() + ")"); } } } diff --git a/src/modules/m_customtitle.cpp b/src/modules/m_customtitle.cpp index ef9c0ae1c..9833c70f7 100644 --- a/src/modules/m_customtitle.cpp +++ b/src/modules/m_customtitle.cpp @@ -118,11 +118,11 @@ class ModuleCustomTitle final { std::string name = tag->getString("name", "", 1); if (name.empty()) - throw ModuleException("<title:name> is empty at " + tag->source.str()); + throw ModuleException(this, "<title:name> is empty at " + tag->source.str()); std::string pass = tag->getString("password"); if (pass.empty()) - throw ModuleException("<title:password> is empty at " + tag->source.str()); + throw ModuleException(this, "<title:password> is empty at " + tag->source.str()); const std::string hash = tag->getString("hash", "plaintext", 1); if (stdalgo::string::equalsci(hash, "plaintext")) diff --git a/src/modules/m_denychans.cpp b/src/modules/m_denychans.cpp index 30541920b..a2a64d15b 100644 --- a/src/modules/m_denychans.cpp +++ b/src/modules/m_denychans.cpp @@ -78,7 +78,7 @@ class ModuleDenyChannels final // Ensure that we have the <goodchan:name> parameter. const std::string name = tag->getString("name"); if (name.empty()) - throw ModuleException("<goodchan:name> is a mandatory field, at " + tag->source.str()); + throw ModuleException(this, "<goodchan:name> is a mandatory field, at " + tag->source.str()); goodchans.push_back(name); } @@ -89,19 +89,19 @@ class ModuleDenyChannels final // Ensure that we have the <badchan:name> parameter. const std::string name = tag->getString("name"); if (name.empty()) - throw ModuleException("<badchan:name> is a mandatory field, at " + tag->source.str()); + throw ModuleException(this, "<badchan:name> is a mandatory field, at " + tag->source.str()); // Ensure that we have the <badchan:reason> parameter. const std::string reason = tag->getString("reason"); if (reason.empty()) - throw ModuleException("<badchan:reason> is a mandatory field, at " + tag->source.str()); + throw ModuleException(this, "<badchan:reason> is a mandatory field, at " + tag->source.str()); const std::string redirect = tag->getString("redirect"); if (!redirect.empty()) { // Ensure that <badchan:redirect> contains a channel name. if (!ServerInstance->Channels.IsChannel(redirect)) - throw ModuleException("<badchan:redirect> is not a valid channel name, at " + tag->source.str()); + throw ModuleException(this, "<badchan:redirect> is not a valid channel name, at " + tag->source.str()); // We defer the rest of the validation of the redirect channel until we have // finished parsing all of the badchans. @@ -136,7 +136,7 @@ class ModuleDenyChannels final for (const auto& badchanredir : badchans) { if (InspIRCd::Match(badchan.redirect, badchanredir.name)) - throw ModuleException("<badchan:redirect> cannot be a blacklisted channel name"); + throw ModuleException(this, "<badchan:redirect> cannot be a blacklisted channel name"); } } diff --git a/src/modules/m_disable.cpp b/src/modules/m_disable.cpp index fc9ae90e9..a49e487ff 100644 --- a/src/modules/m_disable.cpp +++ b/src/modules/m_disable.cpp @@ -48,13 +48,13 @@ class ModuleDisable final { // Check that the character is a valid mode letter. if (!ModeParser::IsModeChar(chr)) - throw ModuleException(InspIRCd::Format("Invalid mode '%c' was specified in <disabled:%s> at %s", + throw ModuleException(this, InspIRCd::Format("Invalid mode '%c' was specified in <disabled:%s> at %s", chr, field.c_str(), tag->source.str().c_str())); // Check that the mode actually exists. ModeHandler* mh = ServerInstance->Modes.FindMode(chr, type); if (!mh) - throw ModuleException(InspIRCd::Format("Nonexistent mode '%c' was specified in <disabled:%s> at %s", + throw ModuleException(this, InspIRCd::Format("Nonexistent mode '%c' was specified in <disabled:%s> at %s", chr, field.c_str(), tag->source.str().c_str())); // Disable the mode. @@ -93,7 +93,7 @@ class ModuleDisable final // Check that the command actually exists. Command* handler = ServerInstance->Parser.GetHandler(command); if (!handler) - throw ModuleException(InspIRCd::Format("Nonexistent command '%s' was specified in <disabled:commands> at %s", + throw ModuleException(this, InspIRCd::Format("Nonexistent command '%s' was specified in <disabled:commands> at %s", command.c_str(), tag->source.str().c_str())); // Prevent admins from disabling MODULES for transparency reasons. diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index 6c9e56a2a..db9c2ed01 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -103,15 +103,15 @@ public: // If action is set to gline, kline, or zline then the duration for an X-line to last for. unsigned long xlineduration; - DNSBLEntry(std::shared_ptr<ConfigTag> tag) + DNSBLEntry(const Module* mod, std::shared_ptr<ConfigTag> tag) { name = tag->getString("name"); if (name.empty()) - throw ModuleException("<dnsbl:name> can not be empty at " + tag->source.str()); + throw ModuleException(mod, "<dnsbl:name> can not be empty at " + tag->source.str()); domain = tag->getString("domain"); if (domain.empty()) - throw ModuleException("<dnsbl:domain> can not be empty at " + tag->source.str()); + throw ModuleException(mod, "<dnsbl:domain> can not be empty at " + tag->source.str()); action = tag->getEnum("action", Action::KILL, { { "gline", Action::GLINE }, @@ -137,14 +137,14 @@ public: for (long record = 0; (record = recordrange.GetToken()); ) { if (record < 0 || record > UCHAR_MAX) - throw ModuleException("<dnsbl:records> can only hold records between 0 and 255 at " + tag->source.str()); + throw ModuleException(mod, "<dnsbl:records> can only hold records between 0 and 255 at " + tag->source.str()); records.set(record); } } else { - throw ModuleException(typestr + " is an invalid value for <dnsbl:type>; acceptable values are 'bitmask' or 'records' at " + throw ModuleException(mod, typestr + " is an invalid value for <dnsbl:type>; acceptable values are 'bitmask' or 'records' at " + tag->source.str()); } @@ -387,7 +387,7 @@ class ModuleDNSBL final DNSBLEntries newdnsbls; for (const auto& [_, tag] : ServerInstance->Config->ConfTags("dnsbl")) { - auto entry = std::make_shared<DNSBLEntry>(tag); + auto entry = std::make_shared<DNSBLEntry>(this, tag); newdnsbls.push_back(entry); } dnsbls.swap(newdnsbls); diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index f32da94ca..09fe913f9 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -62,6 +62,8 @@ enum FilterAction FA_NONE }; +static Module* thismod; + class FilterResult final { public: @@ -88,7 +90,7 @@ class FilterResult final , from_config(cfg) { if (!RegexEngine) - throw ModuleException("Regex module implementing '"+RegexEngine.GetProvider()+"' is not loaded!"); + throw ModuleException(thismod, "Regex module implementing '"+RegexEngine.GetProvider()+"' is not loaded!"); regex = RegexEngine->Create(free); this->FillFlags(fla); } @@ -359,6 +361,7 @@ ModuleFilter::ModuleFilter() , filtcommand(this) , RegexEngine(this) { + thismod = this; } void ModuleFilter::init() @@ -701,13 +704,13 @@ FilterResult ModuleFilter::DecodeFilter(const std::string &data) tokens.GetMiddle(res.freeform); tokens.GetMiddle(filteraction); if (!StringToFilterAction(filteraction, res.action)) - throw ModuleException("Invalid action: " + filteraction); + throw ModuleException(this, "Invalid action: " + filteraction); std::string filterflags; tokens.GetMiddle(filterflags); char c = res.FillFlags(filterflags); if (c != 0) - throw ModuleException("Invalid flag: '" + std::string(1, c) + "'"); + throw ModuleException(this, "Invalid flag: '" + std::string(1, c) + "'"); std::string duration; tokens.GetMiddle(duration); diff --git a/src/modules/m_gateway.cpp b/src/modules/m_gateway.cpp index 4cc1e0eae..b408afd24 100644 --- a/src/modules/m_gateway.cpp +++ b/src/modules/m_gateway.cpp @@ -368,7 +368,7 @@ class ModuleGateway final // Ensure that we have the <gateway:mask> parameter. if (masks.empty()) - throw ModuleException("<" + tag->name + ":mask> is a mandatory field, at " + tag->source.str()); + throw ModuleException(this, "<" + tag->name + ":mask> is a mandatory field, at " + tag->source.str()); // Determine what lookup type this host uses. const std::string type = tag->getString("type"); @@ -388,7 +388,7 @@ class ModuleGateway final // WebIRC blocks require a password. if (fingerprint.empty() && password.empty()) - throw ModuleException("When using <" + tag->name + " type=\"webirc\"> either the fingerprint or password field is required, at " + tag->source.str()); + throw ModuleException(this, "When using <" + tag->name + " type=\"webirc\"> either the fingerprint or password field is required, at " + tag->source.str()); if (!password.empty() && stdalgo::string::equalsci(passwordhash, "plaintext")) { @@ -400,7 +400,7 @@ class ModuleGateway final } else { - throw ModuleException(type + " is an invalid <" + tag->name + ":mask> type, at " + tag->source.str()); + throw ModuleException(this, type + " is an invalid <" + tag->name + ":mask> type, at " + tag->source.str()); } } diff --git a/src/modules/m_helpop.cpp b/src/modules/m_helpop.cpp index 4ad952479..0984ac91c 100644 --- a/src/modules/m_helpop.cpp +++ b/src/modules/m_helpop.cpp @@ -115,23 +115,23 @@ class ModuleHelpop final HelpMap newhelp; auto tags = ServerInstance->Config->ConfTags("helpop"); if (tags.empty()) - throw ModuleException("You have loaded the helpop module but not configured any help topics!"); + throw ModuleException(this, "You have loaded the helpop module but not configured any help topics!"); for (const auto& [_, tag] : tags) { // Attempt to read the help key. const std::string key = tag->getString("key"); if (key.empty()) - throw ModuleException(InspIRCd::Format("<helpop:key> is empty at %s", tag->source.str().c_str())); + throw ModuleException(this, InspIRCd::Format("<helpop:key> is empty at %s", tag->source.str().c_str())); else if (irc::equals(key, "index")) - throw ModuleException(InspIRCd::Format("<helpop:key> is set to \"index\" which is reserved at %s", tag->source.str().c_str())); + throw ModuleException(this, InspIRCd::Format("<helpop:key> is set to \"index\" which is reserved at %s", tag->source.str().c_str())); else if (key.length() > longestkey) longestkey = key.length(); // Attempt to read the help value. std::string value; if (!tag->readString("value", value, true) || value.empty()) - throw ModuleException(InspIRCd::Format("<helpop:value> is empty at %s", tag->source.str().c_str())); + throw ModuleException(this, InspIRCd::Format("<helpop:value> is empty at %s", tag->source.str().c_str())); // Parse the help body. Empty lines are replaced with a single // space because some clients are unable to show blank lines. @@ -144,7 +144,7 @@ class ModuleHelpop final const std::string title = tag->getString("title", InspIRCd::Format("*** Help for %s", key.c_str()), 1); if (!newhelp.emplace(key, HelpTopic(helpmsg, title)).second) { - throw ModuleException(InspIRCd::Format("<helpop> tag with duplicate key '%s' at %s", + throw ModuleException(this, InspIRCd::Format("<helpop> tag with duplicate key '%s' at %s", key.c_str(), tag->source.str().c_str())); } } diff --git a/src/modules/m_hidelist.cpp b/src/modules/m_hidelist.cpp index e52f9de32..7dde09e97 100644 --- a/src/modules/m_hidelist.cpp +++ b/src/modules/m_hidelist.cpp @@ -67,7 +67,7 @@ class ModuleHideList final { std::string modename = tag->getString("mode"); if (modename.empty()) - throw ModuleException("Empty <hidelist:mode> at " + tag->source.str()); + throw ModuleException(this, "Empty <hidelist:mode> at " + tag->source.str()); // If rank is set to 0 everyone inside the channel can view the list, // but non-members may not unsigned long rank = tag->getUInt("rank", HALFOP_VALUE); diff --git a/src/modules/m_hidemode.cpp b/src/modules/m_hidemode.cpp index f5d7c0c6a..b303b1841 100644 --- a/src/modules/m_hidemode.cpp +++ b/src/modules/m_hidemode.cpp @@ -38,7 +38,7 @@ class Settings final return 0; } - void Load() + void Load(const Module* mod) { RanksToSeeMap newranks; @@ -46,11 +46,11 @@ class Settings final { const std::string modename = tag->getString("mode"); if (modename.empty()) - throw ModuleException("<hidemode:mode> is empty at " + tag->source.str()); + throw ModuleException(mod, "<hidemode:mode> is empty at " + tag->source.str()); unsigned long rank = tag->getUInt("rank", 0); if (!rank) - throw ModuleException("<hidemode:rank> must be greater than 0 at " + tag->source.str()); + throw ModuleException(mod, "<hidemode:rank> must be greater than 0 at " + tag->source.str()); ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Hiding the %s mode from users below rank %lu", modename.c_str(), rank); newranks.emplace(modename, rank); @@ -197,7 +197,7 @@ class ModuleHideMode final void ReadConfig(ConfigStatus& status) override { - modehook.settings.Load(); + modehook.settings.Load(this); } }; diff --git a/src/modules/m_hostchange.cpp b/src/modules/m_hostchange.cpp index d1f3426b2..5016ed5c4 100644 --- a/src/modules/m_hostchange.cpp +++ b/src/modules/m_hostchange.cpp @@ -156,7 +156,7 @@ private: // Ensure that we have the <hostchange:mask> parameter. const std::string mask = tag->getString("mask"); if (mask.empty()) - throw ModuleException("<hostchange:mask> is a mandatory field, at " + tag->source.str()); + throw ModuleException(this, "<hostchange:mask> is a mandatory field, at " + tag->source.str()); // Determine what type of host rule this is. const std::string action = tag->getString("action"); @@ -175,7 +175,7 @@ private: // Ensure that we have the <hostchange:value> parameter. const std::string value = tag->getString("value"); if (value.empty()) - throw ModuleException("<hostchange:value> is a mandatory field when using the 'set' action, at " + tag->source.str()); + throw ModuleException(this, "<hostchange:value> is a mandatory field when using the 'set' action, at " + tag->source.str()); // The hostname is in the format <value>. rules.emplace_back(tag, mask, value); @@ -183,7 +183,7 @@ private: } else { - throw ModuleException(action + " is an invalid <hostchange:action> type, at " + tag->source.str()); + throw ModuleException(this, action + " is an invalid <hostchange:action> type, at " + tag->source.str()); } } diff --git a/src/modules/m_httpd_acl.cpp b/src/modules/m_httpd_acl.cpp index afdbf2c08..7510725fe 100644 --- a/src/modules/m_httpd_acl.cpp +++ b/src/modules/m_httpd_acl.cpp @@ -88,7 +88,7 @@ class ModuleHTTPAccessList final } else { - throw ModuleException("Invalid HTTP ACL type '" + type + "'"); + throw ModuleException(this, "Invalid HTTP ACL type '" + type + "'"); } } diff --git a/src/modules/m_ident.cpp b/src/modules/m_ident.cpp index b40546fec..caaa8f116 100644 --- a/src/modules/m_ident.cpp +++ b/src/modules/m_ident.cpp @@ -109,13 +109,14 @@ class IdentRequestSocket final time_t age; bool done; /* True if lookup is finished */ - IdentRequestSocket(LocalUser* u) : user(u) + IdentRequestSocket(const Module* mod, LocalUser* luser) + : user(luser) { age = ServerInstance->Time(); SetFd(socket(user->server_sa.family(), SOCK_STREAM, 0)); if (!HasFd()) - throw ModuleException("Could not create socket"); + throw ModuleException(mod, "Could not create socket"); done = false; @@ -140,7 +141,7 @@ class IdentRequestSocket final if (SocketEngine::Bind(GetFd(), bindaddr) < 0) { this->Close(); - throw ModuleException("failed to bind()"); + throw ModuleException(mod, "failed to bind()"); } SocketEngine::NonBlocking(GetFd()); @@ -149,14 +150,14 @@ class IdentRequestSocket final if (SocketEngine::Connect(this, connaddr) == -1 && errno != EINPROGRESS) { this->Close(); - throw ModuleException("connect() failed"); + throw ModuleException(mod, "connect() failed"); } /* Add fd to socket engine */ if (!SocketEngine::AddFd(this, FD_WANT_NO_READ | FD_WANT_POLL_WRITE)) { this->Close(); - throw ModuleException("out of fds"); + throw ModuleException(mod, "out of fds"); } } @@ -343,7 +344,7 @@ class ModuleIdent final try { - isock = new IdentRequestSocket(user); + isock = new IdentRequestSocket(this, user); socket.Set(user, isock); } catch (ModuleException &e) diff --git a/src/modules/m_ircv3_sts.cpp b/src/modules/m_ircv3_sts.cpp index b59025130..3b9794a96 100644 --- a/src/modules/m_ircv3_sts.cpp +++ b/src/modules/m_ircv3_sts.cpp @@ -163,15 +163,15 @@ class ModuleIRCv3STS final // TODO: Multiple SNI profiles auto tag = ServerInstance->Config->ConfValue("sts"); if (tag == ServerInstance->Config->EmptyTag) - throw ModuleException("You must define a STS policy!"); + throw ModuleException(this, "You must define a STS policy!"); const std::string host = tag->getString("host"); if (host.empty()) - throw ModuleException("<sts:host> must contain a hostname, at " + tag->source.str()); + throw ModuleException(this, "<sts:host> must contain a hostname, at " + tag->source.str()); unsigned int port = static_cast<unsigned int>(tag->getUInt("port", 0, 0, UINT16_MAX)); if (!HasValidSSLPort(port)) - throw ModuleException("<sts:port> must be a TLS port, at " + tag->source.str()); + throw ModuleException(this, "<sts:port> must be a TLS port, at " + tag->source.str()); unsigned long duration = tag->getDuration("duration", 5*60, 60); bool preload = tag->getBool("preload"); diff --git a/src/modules/m_nationalchars.cpp b/src/modules/m_nationalchars.cpp index c673078c7..54f1dc962 100644 --- a/src/modules/m_nationalchars.cpp +++ b/src/modules/m_nationalchars.cpp @@ -275,7 +275,7 @@ class ModuleNationalChars final charset = tag->getString("file"); std::string casemapping = tag->getString("casemapping", FileSystem::GetFileName(charset), 1); if (casemapping.find(' ') != std::string::npos) - throw ModuleException("<nationalchars:casemapping> must not contain any spaces!"); + throw ModuleException(this, "<nationalchars:casemapping> must not contain any spaces!"); ServerInstance->Config->CaseMapping = std::move(casemapping); #if defined _WIN32 if (!FileSystem::StartsWithWindowsDriveLetter(charset)) @@ -286,7 +286,7 @@ class ModuleNationalChars final #endif unsigned char* tables[8] = { m_additional, m_additionalMB, m_additionalUp, m_lower, m_upper, m_additionalUtf8, m_additionalUtf8range, m_additionalUtf8interval }; if (!loadtables(charset, tables, 8, 5)) - throw ModuleException("The locale file failed to load. Check your log file for more information."); + throw ModuleException(this, "The locale file failed to load. Check your log file for more information."); forcequit = tag->getBool("forcequit"); CheckForceQuit("National character set changed"); CheckRehash(); diff --git a/src/modules/m_regex_glob.cpp b/src/modules/m_regex_glob.cpp index a0b25e193..569a40731 100644 --- a/src/modules/m_regex_glob.cpp +++ b/src/modules/m_regex_glob.cpp @@ -30,7 +30,7 @@ class GlobPattern final : public Regex::Pattern { public: - GlobPattern(const std::string& pattern, uint8_t options) + GlobPattern(const Module* mod, const std::string& pattern, uint8_t options) : Regex::Pattern(pattern, options) { } diff --git a/src/modules/m_regex_stdlib.cpp b/src/modules/m_regex_stdlib.cpp index 580934400..714ed05aa 100644 --- a/src/modules/m_regex_stdlib.cpp +++ b/src/modules/m_regex_stdlib.cpp @@ -32,7 +32,7 @@ class StdLibPattern final std::regex regex; public: - StdLibPattern(const std::string& pattern, uint8_t options, std::regex::flag_type type) + StdLibPattern(const Module* mod, const std::string& pattern, uint8_t options, std::regex::flag_type type) : Regex::Pattern(pattern, options) { // Convert the generic pattern options to stdlib pattern flags. @@ -46,7 +46,7 @@ class StdLibPattern final } catch(const std::regex_error& error) { - throw Regex::Exception(pattern, error.what()); + throw Regex::Exception(mod, pattern, error.what()); } } @@ -69,7 +69,7 @@ class StdLibEngine final Regex::PatternPtr Create(const std::string& pattern, uint8_t options) const override { - return std::make_shared<StdLibPattern>(pattern, options, regextype); + return std::make_shared<StdLibPattern>(creator, pattern, options, regextype); } }; diff --git a/src/modules/m_restrictchans.cpp b/src/modules/m_restrictchans.cpp index ed47dc31b..12c0de77c 100644 --- a/src/modules/m_restrictchans.cpp +++ b/src/modules/m_restrictchans.cpp @@ -66,7 +66,7 @@ class ModuleRestrictChans final { const std::string name = tag->getString("name"); if (name.empty()) - throw ModuleException("Empty <allowchannel:name> at " + tag->source.str()); + throw ModuleException(this, "Empty <allowchannel:name> at " + tag->source.str()); newallows.insert(name); } diff --git a/src/modules/m_rline.cpp b/src/modules/m_rline.cpp index e52224738..bc599147a 100644 --- a/src/modules/m_rline.cpp +++ b/src/modules/m_rline.cpp @@ -97,9 +97,15 @@ class RLine final class RLineFactory final : public XLineFactory { - public: + private: + const Module* creator; Regex::EngineReference& rxfactory; - RLineFactory(Regex::EngineReference& rx) : XLineFactory("R"), rxfactory(rx) + + public: + RLineFactory(const Module* mod, Regex::EngineReference& rx) + : XLineFactory("R") + , creator(mod) + , rxfactory(rx) { } @@ -110,7 +116,7 @@ class RLineFactory final if (!rxfactory) { ServerInstance->SNO.WriteToSnoMask('a', "Cannot create regexes until engine is set to a loaded provider!"); - throw ModuleException("Regex engine not set or loaded!"); + throw ModuleException(creator, "Regex engine not set or loaded!"); } return new RLine(set_time, duration, source, reason, xline_specific_mask, rxfactory); @@ -213,7 +219,7 @@ class ModuleRLine final : Module(VF_VENDOR | VF_COMMON, "Adds the /RLINE command which allows server operators to prevent users matching a nickname!username@hostname+realname regular expression from connecting to the server.") , Stats::EventListener(this) , rxfactory(this) - , f(rxfactory) + , f(this, rxfactory) , r(this, f) { } diff --git a/src/modules/m_sasl.cpp b/src/modules/m_sasl.cpp index 7aefb000c..eed0e73c0 100644 --- a/src/modules/m_sasl.cpp +++ b/src/modules/m_sasl.cpp @@ -430,7 +430,7 @@ class ModuleSASL final const std::string target = tag->getString("target"); if (target.empty()) - throw ModuleException("<sasl:target> must be set to the name of your services server!"); + throw ModuleException(this, "<sasl:target> must be set to the name of your services server!"); cap.requiressl = tag->getBool("requiressl"); sasl_target = target; diff --git a/src/modules/m_securelist.cpp b/src/modules/m_securelist.cpp index a475c9255..59b704362 100644 --- a/src/modules/m_securelist.cpp +++ b/src/modules/m_securelist.cpp @@ -57,7 +57,7 @@ class ModuleSecureList final { const std::string host = tag->getString("exception"); if (host.empty()) - throw ModuleException("<securehost:exception> is a required field at " + tag->source.str()); + throw ModuleException(this, "<securehost:exception> is a required field at " + tag->source.str()); newallows.push_back(host); } diff --git a/src/modules/m_showfile.cpp b/src/modules/m_showfile.cpp index 3de8df9d3..cb952e127 100644 --- a/src/modules/m_showfile.cpp +++ b/src/modules/m_showfile.cpp @@ -108,13 +108,13 @@ class ModuleShowFile final { std::string cmdname = tag->getString("name"); if (cmdname.empty()) - throw ModuleException("Empty value for 'name'"); + throw ModuleException(this, "Empty value for 'name'"); std::transform(cmdname.begin(), cmdname.end(), cmdname.begin(), ::toupper); const std::string file = tag->getString("file", cmdname); if (file.empty()) - throw ModuleException("Empty value for 'file'"); + throw ModuleException(this, "Empty value for 'file'"); FileReader reader(file); CommandShowFile* sfcmd; @@ -123,12 +123,12 @@ class ModuleShowFile final { // Command exists, check if it is ours if (handler->creator != this) - throw ModuleException("Command " + cmdname + " already exists"); + throw ModuleException(this, "Command " + cmdname + " already exists"); // This is our command, make sure we don't have the same entry twice sfcmd = static_cast<CommandShowFile*>(handler); if (stdalgo::isin(newcmds, sfcmd)) - throw ModuleException("Command " + cmdname + " is already used in a <showfile> tag"); + throw ModuleException(this, "Command " + cmdname + " is already used in a <showfile> tag"); } else { diff --git a/src/modules/m_spanningtree/servercommand.h b/src/modules/m_spanningtree/servercommand.h index 379dbbc19..d530ad666 100644 --- a/src/modules/m_spanningtree/servercommand.h +++ b/src/modules/m_spanningtree/servercommand.h @@ -28,7 +28,7 @@ class ProtocolException final { public: ProtocolException(const std::string& msg) - : ModuleException("Protocol violation: " + msg) + : ModuleException((Module*)Utils->Creator, "Protocol violation: " + msg) { } }; diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index ce822b607..aad601251 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -270,25 +270,25 @@ void SpanningTreeUtilities::ReadConfiguration() L->Hidden = tag->getBool("hidden"); if (L->Name.empty()) - throw ModuleException("Invalid configuration, found a link tag without a name!" + (!L->IPAddr.empty() ? " IP address: "+L->IPAddr : "")); + throw ModuleException((Module*)Creator, "Invalid configuration, found a link tag without a name!" + (!L->IPAddr.empty() ? " IP address: "+L->IPAddr : "")); if (L->Name.find('.') == std::string::npos) - throw ModuleException("The link name '"+L->Name+"' is invalid as it must contain at least one '.' character"); + throw ModuleException((Module*)Creator, "The link name '"+L->Name+"' is invalid as it must contain at least one '.' character"); if (L->Name.length() > ServerInstance->Config->Limits.MaxHost) - throw ModuleException("The link name '"+L->Name+"' is invalid as it is longer than " + ConvToStr(ServerInstance->Config->Limits.MaxHost) + " characters"); + throw ModuleException((Module*)Creator, "The link name '"+L->Name+"' is invalid as it is longer than " + ConvToStr(ServerInstance->Config->Limits.MaxHost) + " characters"); if (L->RecvPass.empty()) - throw ModuleException("Invalid configuration for server '"+L->Name+"', recvpass not defined"); + throw ModuleException((Module*)Creator, "Invalid configuration for server '"+L->Name+"', recvpass not defined"); if (L->SendPass.empty()) - throw ModuleException("Invalid configuration for server '"+L->Name+"', sendpass not defined"); + throw ModuleException((Module*)Creator, "Invalid configuration for server '"+L->Name+"', sendpass not defined"); if ((L->SendPass.find(' ') != std::string::npos) || (L->RecvPass.find(' ') != std::string::npos)) - throw ModuleException("Link block '" + L->Name + "' has a password set that contains a space character which is invalid"); + throw ModuleException((Module*)Creator, "Link block '" + L->Name + "' has a password set that contains a space character which is invalid"); if ((L->SendPass[0] == ':') || (L->RecvPass[0] == ':')) - throw ModuleException("Link block '" + L->Name + "' has a password set that begins with a colon (:) which is invalid"); + throw ModuleException((Module*)Creator, "Link block '" + L->Name + "' has a password set that begins with a colon (:) which is invalid"); if (L->IPAddr.empty()) { @@ -318,7 +318,7 @@ void SpanningTreeUtilities::ReadConfiguration() if (A->servers.empty()) { - throw ModuleException("Invalid configuration for autoconnect, server cannot be empty!"); + throw ModuleException((Module*)Creator, "Invalid configuration for autoconnect, server cannot be empty!"); } AutoconnectBlocks.push_back(A); diff --git a/src/modules/m_vhost.cpp b/src/modules/m_vhost.cpp index f4d813ce7..5539ebb86 100644 --- a/src/modules/m_vhost.cpp +++ b/src/modules/m_vhost.cpp @@ -98,15 +98,15 @@ class ModuleVHost final { std::string mask = tag->getString("host"); if (mask.empty()) - throw ModuleException("<vhost:host> is empty! at " + tag->source.str()); + throw ModuleException(this, "<vhost:host> is empty! at " + tag->source.str()); std::string username = tag->getString("user"); if (username.empty()) - throw ModuleException("<vhost:user> is empty! at " + tag->source.str()); + throw ModuleException(this, "<vhost:user> is empty! at " + tag->source.str()); std::string pass = tag->getString("pass"); if (pass.empty()) - throw ModuleException("<vhost:pass> is empty! at " + tag->source.str()); + throw ModuleException(this, "<vhost:pass> is empty! at " + tag->source.str()); const std::string hash = tag->getString("hash", "plaintext", 1); if (stdalgo::string::equalsci(hash, "plaintext")) diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 0df7e0818..139abd59d 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -594,7 +594,7 @@ class ModuleWebSocket final { auto tags = ServerInstance->Config->ConfTags("wsorigin"); if (tags.empty()) - throw ModuleException("You have loaded the websocket module but not configured any allowed origins!"); + throw ModuleException(this, "You have loaded the websocket module but not configured any allowed origins!"); WebSocketConfig config; for (const auto& [_, tag] : tags) @@ -602,7 +602,7 @@ class ModuleWebSocket final // Ensure that we have the <wsorigin:allow> parameter. const std::string allow = tag->getString("allow"); if (allow.empty()) - throw ModuleException("<wsorigin:allow> is a mandatory field, at " + tag->source.str()); + throw ModuleException(this, "<wsorigin:allow> is a mandatory field, at " + tag->source.str()); config.allowedorigins.push_back(allow); } @@ -617,7 +617,7 @@ class ModuleWebSocket final else if (stdalgo::string::equalsci(defaultmodestr, "text")) config.defaultmode = WebSocketConfig::DM_TEXT; else - throw ModuleException(defaultmodestr + " is an invalid value for <websocket:defaultmode>; acceptable values are 'binary', 'text' and 'reject', at " + tag->source.str()); + throw ModuleException(this, defaultmodestr + " is an invalid value for <websocket:defaultmode>; acceptable values are 'binary', 'text' and 'reject', at " + tag->source.str()); irc::spacesepstream proxyranges(tag->getString("proxyranges")); for (std::string proxyrange; proxyranges.GetToken(proxyrange); ) |
