diff options
| author | 2020-11-03 19:40:42 +0000 | |
|---|---|---|
| committer | 2020-11-03 19:54:13 +0000 | |
| commit | 373bc208ff8f7eceecd944114cd729b5a348d918 (patch) | |
| tree | 3fc6cc31e70a00cb9670b3724e0c94256f763385 /src | |
| parent | Replace ConfigTag::create with a public constructor. (diff) | |
Move FilePosition to fileutils.h and use in ConfigTag.
Diffstat (limited to 'src')
36 files changed, 117 insertions, 133 deletions
diff --git a/src/configparser.cpp b/src/configparser.cpp index 7bb55bb50..61eb0edb8 100644 --- a/src/configparser.cpp +++ b/src/configparser.cpp @@ -41,30 +41,6 @@ enum ParseFlags FLAG_NO_ENV = 8 }; -// Represents the position within a config file. -struct FilePosition -{ - // The name of the file which is being read. - std::string name; - - // The line of the file that this position points to. - unsigned int line = 1; - - // The column of the file that this position points to. - unsigned int column = 1; - - FilePosition(const std::string& Name) - : name(Name) - { - } - - /** Returns a string that represents this file position. */ - std::string str() - { - return name + ":" + ConvToStr(line) + ":" + ConvToStr(column); - } -}; - // RAII wrapper for FILE* which closes the file when it goes out of scope. class FileWrapper { @@ -286,7 +262,7 @@ struct Parser if (name.empty()) throw CoreException("Empty tag name"); - tag = std::make_shared<ConfigTag>(name, current.name, current.line); + tag = std::make_shared<ConfigTag>(name, current); while (kv()) { // Do nothing here (silences a GCC warning). @@ -366,7 +342,7 @@ struct Parser { stack.errstr << err.GetReason() << " at " << current.str(); if (tag) - stack.errstr << " (inside tag " << tag->tag << " at line " << tag->src_line << ")\n"; + stack.errstr << " (inside tag " << tag->tag << " at line " << tag->source.line << ")\n"; else stack.errstr << " (last tag was on line " << last_tag.line << ")\n"; } @@ -495,7 +471,7 @@ bool ConfigTag::readString(const std::string& key, std::string& value, bool allo value = ivalue; if (!allow_lf && (value.find('\n') != std::string::npos)) { - ServerInstance->Logs.Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + + ServerInstance->Logs.Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + source.str() + " contains a linefeed, and linefeeds in this value are not permitted -- stripped to spaces."); for (std::string::iterator n = value.begin(); n != value.end(); n++) if (*n == '\n') @@ -641,7 +617,7 @@ unsigned long ConfigTag::getDuration(const std::string& key, unsigned long def, unsigned long ret; if (!InspIRCd::Duration(duration, ret)) { - ServerInstance->Logs.Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + + ServerInstance->Logs.Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + source.str() + " is not a duration; value set to " + ConvToStr(def) + "."); return def; } @@ -673,18 +649,14 @@ bool ConfigTag::getBool(const std::string& key, bool def) const if (stdalgo::string::equalsci(result, "no") || stdalgo::string::equalsci(result, "false") || stdalgo::string::equalsci(result, "off")) return false; - ServerInstance->Logs.Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + getTagLocation() + + ServerInstance->Logs.Log("CONFIG", LOG_DEFAULT, "Value of <" + tag + ":" + key + "> at " + source.str() + " is not valid, ignoring"); return def; } -std::string ConfigTag::getTagLocation() const -{ - return src_name + ":" + ConvToStr(src_line); -} - -ConfigTag::ConfigTag(const std::string& Tag, const std::string& file, int line) - : tag(Tag), src_name(file), src_line(line) +ConfigTag::ConfigTag(const std::string& Tag, const FilePosition& Source) + : tag(Tag) + , source(Source) { } diff --git a/src/configreader.cpp b/src/configreader.cpp index 5a3fc8c1c..c70777ec1 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -61,7 +61,7 @@ ServerConfig::ServerPaths::ServerPaths(std::shared_ptr<ConfigTag> tag) } ServerConfig::ServerConfig() - : EmptyTag(std::make_shared<ConfigTag>("empty", "<auto>", 0)) + : EmptyTag(std::make_shared<ConfigTag>("empty", FilePosition("<auto>", 0, 0))) , Limits(EmptyTag) , Paths(EmptyTag) , CaseMapping("ascii") @@ -76,11 +76,11 @@ static void ReadXLine(ServerConfig* conf, const std::string& tag, const std::str { const std::string mask = ctag->getString(key); if (mask.empty()) - throw CoreException("<" + tag + ":" + key + "> missing at " + ctag->getTagLocation()); + throw CoreException("<" + tag + ":" + key + "> missing at " + ctag->source.str()); const std::string reason = ctag->getString("reason"); if (reason.empty()) - throw CoreException("<" + tag + ":reason> missing at " + ctag->getTagLocation()); + throw CoreException("<" + tag + ":reason> missing at " + ctag->source.str()); XLine* xl = make->Generate(ServerInstance->Time(), 0, ServerInstance->Config->ServerName, reason, mask); xl->from_config = true; @@ -100,9 +100,9 @@ void ServerConfig::CrossCheckOperClassType() { std::string name = tag->getString("name"); if (name.empty()) - throw CoreException("<class:name> missing from tag at " + tag->getTagLocation()); + throw CoreException("<class:name> missing from tag at " + tag->source.str()); if (operclass.find(name) != operclass.end()) - throw CoreException("Duplicate class block with name " + name + " at " + tag->getTagLocation()); + throw CoreException("Duplicate class block with name " + name + " at " + tag->source.str()); operclass[name] = tag; } @@ -110,9 +110,9 @@ void ServerConfig::CrossCheckOperClassType() { std::string name = tag->getString("name"); if (name.empty()) - throw CoreException("<type:name> is missing from tag at " + tag->getTagLocation()); + throw CoreException("<type:name> is missing from tag at " + tag->source.str()); if (OperTypes.find(name) != OperTypes.end()) - throw CoreException("Duplicate type block with name " + name + " at " + tag->getTagLocation()); + throw CoreException("Duplicate type block with name " + name + " at " + tag->source.str()); auto ifo = std::make_shared<OperInfo>(name); OperTypes[name] = ifo; @@ -133,14 +133,14 @@ void ServerConfig::CrossCheckOperClassType() { std::string name = tag->getString("name"); if (name.empty()) - throw CoreException("<oper:name> missing from tag at " + tag->getTagLocation()); + throw CoreException("<oper:name> missing from tag at " + tag->source.str()); std::string type = tag->getString("type"); OperIndex::iterator tblk = OperTypes.find(type); if (tblk == OperTypes.end()) throw CoreException("Oper block " + name + " has missing type " + type); if (oper_blocks.find(name) != oper_blocks.end()) - throw CoreException("Duplicate oper block with name " + name + " at " + tag->getTagLocation()); + throw CoreException("Duplicate oper block with name " + name + " at " + tag->source.str()); auto ifo = std::make_shared<OperInfo>(type); ifo->oper_block = tag; @@ -175,7 +175,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current) if (blk_count == 0) { // No connect blocks found; make a trivial default block - auto tag = std::make_shared<ConfigTag>("connect", "<auto>", 0); + auto tag = std::make_shared<ConfigTag>("connect", FilePosition("<auto>", 0, 0)); tag->GetItems()["allow"] = "*"; config_data.insert(std::make_pair("connect", tag)); blk_count = 1; @@ -207,7 +207,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current) try_again = true; // couldn't find parent this time. If it's the last time, we'll never find it. if (tries >= blk_count) - throw CoreException("Could not find parent connect class \"" + parentName + "\" for connect block at " + tag->getTagLocation()); + throw CoreException("Could not find parent connect class \"" + parentName + "\" for connect block at " + tag->source.str()); i++; continue; @@ -237,7 +237,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current) } else { - throw CoreException("Connect class must have allow, deny, or name specified at " + tag->getTagLocation()); + throw CoreException("Connect class must have allow, deny, or name specified at " + tag->source.str()); } if (name.empty()) @@ -290,7 +290,7 @@ void ServerConfig::CrossCheckConnectBlocks(ServerConfig* current) if (!me->password.empty() && (me->passwordhash.empty() || stdalgo::string::equalsci(me->passwordhash, "plaintext"))) { ServerInstance->Logs.Log("CONNECTCLASS", LOG_DEFAULT, "<connect> tag '%s' at %s contains an plain text password, this is insecure!", - name.c_str(), tag->getTagLocation().c_str()); + name.c_str(), tag->source.str().c_str()); } std::string ports = tag->getString("port"); @@ -408,7 +408,7 @@ void ServerConfig::Fill() else if (stdalgo::string::equalsci(restrictbannedusers, "yes")) RestrictBannedUsers = ServerConfig::BUT_RESTRICT_NOTIFY; else - throw CoreException(restrictbannedusers + " is an invalid <options:restrictbannedusers> value, at " + options->getTagLocation()); + throw CoreException(restrictbannedusers + " is an invalid <options:restrictbannedusers> value, at " + options->source.str()); } // WARNING: it is not safe to use most of the codebase in this function, as it @@ -454,7 +454,7 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid) for (auto& [_, tag] : dietags) { const std::string reason = tag->getString("reason", "You left a <die> tag in your config", 1); - errstr << reason << " (at " << tag->getTagLocation() << ")" << std::endl; + errstr << reason << " (at " << tag->source.str() << ")" << std::endl; } } @@ -493,7 +493,7 @@ void ServerConfig::Apply(ServerConfig* old, const std::string &useruid) { const FailedPort& fp = *iter; errstr << " " << fp.sa.str() << ": " << strerror(fp.error) << std::endl - << " " << "Created from <bind> tag at " << fp.tag->getTagLocation() << std::endl; + << " " << "Created from <bind> tag at " << fp.tag->source.str() << std::endl; } } } @@ -624,7 +624,7 @@ std::shared_ptr<ConfigTag> ServerConfig::ConfValue(const std::string &tag) found.first++; if (found.first != found.second) ServerInstance->Logs.Log("CONFIG", LOG_DEFAULT, "Multiple <" + tag + "> tags found; only first will be used " - "(first at " + rv->getTagLocation() + "; second at " + found.first->second->getTagLocation() + ")"); + "(first at " + rv->source.str() + "; second at " + found.first->second->source.str() + ")"); return rv; } diff --git a/src/coremods/core_channel/core_channel.cpp b/src/coremods/core_channel/core_channel.cpp index 4fef8d83d..4d5484924 100644 --- a/src/coremods/core_channel/core_channel.cpp +++ b/src/coremods/core_channel/core_channel.cpp @@ -168,7 +168,7 @@ class CoreModChannel { std::string::size_type pos = current.find(':'); if (pos == std::string::npos || (pos + 2) > current.size()) - throw ModuleException("Invalid exemptchanops value '" + current + "' at " + optionstag->getTagLocation()); + throw ModuleException("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/fileutils.cpp b/src/fileutils.cpp index 3dca154a7..49c3b555f 100644 --- a/src/fileutils.cpp +++ b/src/fileutils.cpp @@ -26,6 +26,18 @@ # include <dirent.h> #endif +FilePosition::FilePosition(const std::string& Name, unsigned int Line, unsigned int Column) + : name(Name) + , line(Line) + , column(Column) +{ +} + +std::string FilePosition::str() const +{ + return name + ":" + ConvToStr(line) + ":" + ConvToStr(column); +} + FileReader::FileReader(const std::string& filename) { Load(filename); diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 24eac6e9e..2f4db6d4d 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -382,7 +382,7 @@ namespace { const FailedPort& fp = *iter; std::cout << " " << con_bright << fp.sa.str() << con_reset << ": " << strerror(fp.error) << '.' << std::endl - << " " << "Created from <bind> tag at " << fp.tag->getTagLocation() << std::endl + << " " << "Created from <bind> tag at " << fp.tag->source.str() << std::endl << std::endl; } diff --git a/src/listmode.cpp b/src/listmode.cpp index 551f061c0..ecd63484f 100644 --- a/src/listmode.cpp +++ b/src/listmode.cpp @@ -77,7 +77,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->getTagLocation().c_str())); + throw ModuleException(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/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp index 4c0a746bb..2f509bf9e 100644 --- a/src/modules/extra/m_ssl_gnutls.cpp +++ b/src/modules/extra/m_ssl_gnutls.cpp @@ -1133,14 +1133,14 @@ class ModuleSSLGnuTLS : public Module { if (!stdalgo::string::equalsci(tag->getString("provider"), "gnutls")) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring non-GnuTLS <sslprofile> tag at " + tag->getTagLocation()); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring non-GnuTLS <sslprofile> tag at " + tag->source.str()); continue; } std::string name = tag->getString("name"); if (name.empty()) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring <sslprofile> tag without name at " + tag->getTagLocation()); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring <sslprofile> tag without name at " + tag->source.str()); continue; } @@ -1152,7 +1152,7 @@ class ModuleSSLGnuTLS : public Module } catch (CoreException& ex) { - throw ModuleException("Error while initializing TLS (SSL) profile \"" + name + "\" at " + tag->getTagLocation() + " - " + ex.GetReason()); + throw ModuleException("Error while initializing TLS (SSL) 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 916e6fef7..10107e2f9 100644 --- a/src/modules/extra/m_ssl_mbedtls.cpp +++ b/src/modules/extra/m_ssl_mbedtls.cpp @@ -866,14 +866,14 @@ class ModuleSSLmbedTLS : public Module { if (!stdalgo::string::equalsci(tag->getString("provider"), "mbedtls")) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring non-mbedTLS <sslprofile> tag at " + tag->getTagLocation()); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring non-mbedTLS <sslprofile> tag at " + tag->source.str()); continue; } std::string name = tag->getString("name"); if (name.empty()) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring <sslprofile> tag without name at " + tag->getTagLocation()); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring <sslprofile> tag without name at " + tag->source.str()); continue; } @@ -885,7 +885,7 @@ class ModuleSSLmbedTLS : public Module } catch (CoreException& ex) { - throw ModuleException("Error while initializing TLS (SSL) profile \"" + name + "\" at " + tag->getTagLocation() + " - " + ex.GetReason()); + throw ModuleException("Error while initializing TLS (SSL) profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); } newprofiles.push_back(prov); diff --git a/src/modules/extra/m_ssl_openssl.cpp b/src/modules/extra/m_ssl_openssl.cpp index 5cfc0fb76..199fe4189 100644 --- a/src/modules/extra/m_ssl_openssl.cpp +++ b/src/modules/extra/m_ssl_openssl.cpp @@ -913,14 +913,14 @@ class ModuleSSLOpenSSL : public Module { if (!stdalgo::string::equalsci(tag->getString("provider"), "openssl")) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring non-OpenSSL <sslprofile> tag at " + tag->getTagLocation()); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring non-OpenSSL <sslprofile> tag at " + tag->source.str()); continue; } std::string name = tag->getString("name"); if (name.empty()) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring <sslprofile> tag without name at " + tag->getTagLocation()); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Ignoring <sslprofile> tag without name at " + tag->source.str()); continue; } @@ -931,7 +931,7 @@ class ModuleSSLOpenSSL : public Module } catch (CoreException& ex) { - throw ModuleException("Error while initializing TLS (SSL) profile \"" + name + "\" at " + tag->getTagLocation() + " - " + ex.GetReason()); + throw ModuleException("Error while initializing TLS (SSL) profile \"" + name + "\" at " + tag->source.str() + " - " + ex.GetReason()); } newprofiles.push_back(prov); diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp index 58328af88..0cf6e4a08 100644 --- a/src/modules/m_alias.cpp +++ b/src/modules/m_alias.cpp @@ -88,11 +88,11 @@ class ModuleAlias : public Module Alias a; a.AliasedCommand = tag->getString("text"); if (a.AliasedCommand.empty()) - throw ModuleException("<alias:text> is empty! at " + tag->getTagLocation()); + throw ModuleException("<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->getTagLocation()); + throw ModuleException("<alias:replace> is empty! at " + tag->source.str()); a.RequiredNick = tag->getString("requires"); a.ULineOnly = tag->getBool("uline"); diff --git a/src/modules/m_censor.cpp b/src/modules/m_censor.cpp index a576ae287..3d101c4d0 100644 --- a/src/modules/m_censor.cpp +++ b/src/modules/m_censor.cpp @@ -112,7 +112,7 @@ class ModuleCensor : public Module { const std::string text = tag->getString("text"); if (text.empty()) - throw ModuleException("<badword:text> is empty! at " + tag->getTagLocation()); + throw ModuleException("<badword:text> is empty! at " + tag->source.str()); const std::string replace = tag->getString("replace"); newcensors[text] = replace; diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index ea6c22e9c..9a7de76c0 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -290,7 +290,7 @@ class ModuleCgiIRC // Ensure that we have the <cgihost:mask> parameter. const std::string mask = tag->getString("mask"); if (mask.empty()) - throw ModuleException("<cgihost:mask> is a mandatory field, at " + tag->getTagLocation()); + throw ModuleException("<cgihost:mask> is a mandatory field, at " + tag->source.str()); // Determine what lookup type this host uses. const std::string type = tag->getString("type"); @@ -309,19 +309,19 @@ class ModuleCgiIRC // WebIRC blocks require a password. if (fingerprint.empty() && password.empty()) - throw ModuleException("When using <cgihost type=\"webirc\"> either the fingerprint or password field is required, at " + tag->getTagLocation()); + throw ModuleException("When using <cgihost type=\"webirc\"> either the fingerprint or password field is required, at " + tag->source.str()); if (!password.empty() && stdalgo::string::equalsci(passwordhash, "plaintext")) { ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "<cgihost> tag at %s contains an plain text password, this is insecure!", - tag->getTagLocation().c_str()); + tag->source.str().c_str()); } webirchosts.push_back(WebIRCHost(mask, fingerprint, password, passwordhash)); } else { - throw ModuleException(type + " is an invalid <cgihost:mask> type, at " + tag->getTagLocation()); + throw ModuleException(type + " is an invalid <cgihost:mask> type, at " + tag->source.str()); } } diff --git a/src/modules/m_chanlog.cpp b/src/modules/m_chanlog.cpp index 8250a5d98..860067e5b 100644 --- a/src/modules/m_chanlog.cpp +++ b/src/modules/m_chanlog.cpp @@ -49,7 +49,7 @@ class ModuleChanLog : public Module std::string snomasks = tag->getString("snomasks"); if (channel.empty() || snomasks.empty()) { - throw ModuleException("Malformed chanlog tag at " + tag->getTagLocation()); + throw ModuleException("Malformed chanlog tag at " + tag->source.str()); } for (std::string::const_iterator it = snomasks.begin(); it != snomasks.end(); it++) diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp index dcf0463a4..fad072489 100644 --- a/src/modules/m_cloaking.cpp +++ b/src/modules/m_cloaking.cpp @@ -437,11 +437,11 @@ class ModuleCloaking : public Module // 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->getTagLocation()); + throw ModuleException("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->getTagLocation()); + throw ModuleException("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"); @@ -456,7 +456,7 @@ class ModuleCloaking : public Module else if (stdalgo::string::equalsci(mode, "full")) newcloaks.push_back(CloakInfo(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->getTagLocation()); + throw ModuleException(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 fcff62ff5..6cf22dc98 100644 --- a/src/modules/m_codepage.cpp +++ b/src/modules/m_codepage.cpp @@ -129,11 +129,11 @@ class ModuleCodepage { unsigned char begin = tag->getUInt("begin", tag->getUInt("index", 0), 1, UCHAR_MAX); if (!begin) - throw ModuleException("<cpchars> tag without index or begin specified at " + tag->getTagLocation()); + throw ModuleException("<cpchars> tag without index or begin specified at " + tag->source.str()); unsigned char end = tag->getUInt("end", begin, 1, UCHAR_MAX); if (begin > end) - throw ModuleException("<cpchars:begin> must be lower than <cpchars:end> at " + tag->getTagLocation()); + throw ModuleException("<cpchars:begin> must be lower than <cpchars:end> at " + tag->source.str()); bool front = tag->getBool("front", false); for (unsigned short pos = begin; pos <= end; ++pos) @@ -141,13 +141,13 @@ class ModuleCodepage if (pos == '\n' || pos == '\r' || pos == ' ') { throw ModuleException(InspIRCd::Format("<cpchars> tag contains a forbidden character: %u at %s", - pos, tag->getTagLocation().c_str())); + pos, tag->source.str().c_str())); } if (front && (pos == ':' || isdigit(pos))) { throw ModuleException(InspIRCd::Format("<cpchars> tag contains a forbidden front character: %u at %s", - pos, tag->getTagLocation().c_str())); + pos, tag->source.str().c_str())); } newallowedchars.set(pos); @@ -165,11 +165,11 @@ class ModuleCodepage { unsigned char lower = tag->getUInt("lower", 0, 1, UCHAR_MAX); if (!lower) - throw ModuleException("<cpcase:lower> is required at " + tag->getTagLocation()); + throw ModuleException("<cpcase:lower> is required at " + tag->source.str()); unsigned char upper = tag->getUInt("upper", 0, 1, UCHAR_MAX); if (!upper) - throw ModuleException("<cpcase:upper> is required at " + tag->getTagLocation()); + throw ModuleException("<cpcase:upper> is required at " + tag->source.str()); newcasemap[upper] = lower; ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Marked %u (%c) as the lower case version of %u (%c)", diff --git a/src/modules/m_customprefix.cpp b/src/modules/m_customprefix.cpp index 958330dfb..20cec66c2 100644 --- a/src/modules/m_customprefix.cpp +++ b/src/modules/m_customprefix.cpp @@ -59,17 +59,17 @@ class ModuleCustomPrefix : public Module { const std::string name = tag->getString("name"); if (name.empty()) - throw ModuleException("<customprefix:name> must be specified at " + tag->getTagLocation()); + throw ModuleException("<customprefix:name> must be specified 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->getTagLocation()); + throw ModuleException("<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->getTagLocation()); + throw ModuleException("<customprefix:change> specified for a non-prefix mode at " + tag->source.str()); unsigned long rank = tag->getUInt("rank", pm->GetPrefixRank(), 0, UINT_MAX); unsigned long setrank = tag->getUInt("ranktoset", pm->GetLevelRequired(true), rank, UINT_MAX); @@ -84,11 +84,11 @@ class ModuleCustomPrefix : public Module const std::string letter = tag->getString("letter"); if (letter.length() != 1) - throw ModuleException("<customprefix:letter> must be set to a mode character at " + tag->getTagLocation()); + throw ModuleException("<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->getTagLocation()); + throw ModuleException("<customprefix:prefix> must be set to a mode prefix at " + tag->source.str()); try { @@ -98,7 +98,7 @@ class ModuleCustomPrefix : public Module } catch (ModuleException& e) { - throw ModuleException(e.GetReason() + " (while creating mode from " + tag->getTagLocation() + ")"); + throw ModuleException(e.GetReason() + " (while creating mode from " + tag->source.str() + ")"); } } } diff --git a/src/modules/m_customtitle.cpp b/src/modules/m_customtitle.cpp index 61b1ed42a..6dca396ac 100644 --- a/src/modules/m_customtitle.cpp +++ b/src/modules/m_customtitle.cpp @@ -131,17 +131,17 @@ class ModuleCustomTitle : public Module, public Whois::LineEventListener { std::string name = tag->getString("name", "", 1); if (name.empty()) - throw ModuleException("<title:name> is empty at " + tag->getTagLocation()); + throw ModuleException("<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->getTagLocation()); + throw ModuleException("<title:password> is empty at " + tag->source.str()); const std::string hash = tag->getString("hash", "plaintext", 1); if (stdalgo::string::equalsci(hash, "plaintext")) { ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "<title> tag for %s at %s contains an plain text password, this is insecure!", - name.c_str(), tag->getTagLocation().c_str()); + name.c_str(), tag->source.str().c_str()); } std::string host = tag->getString("host", "*@*", 1); diff --git a/src/modules/m_denychans.cpp b/src/modules/m_denychans.cpp index 3fa768953..7d9779a18 100644 --- a/src/modules/m_denychans.cpp +++ b/src/modules/m_denychans.cpp @@ -77,7 +77,7 @@ class ModuleDenyChannels : public Module // 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->getTagLocation()); + throw ModuleException("<goodchan:name> is a mandatory field, at " + tag->source.str()); goodchans.push_back(name); } @@ -88,19 +88,19 @@ class ModuleDenyChannels : public Module // 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->getTagLocation()); + throw ModuleException("<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->getTagLocation()); + throw ModuleException("<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->IsChannel(redirect)) - throw ModuleException("<badchan:redirect> is not a valid channel name, at " + tag->getTagLocation()); + throw ModuleException("<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. diff --git a/src/modules/m_disable.cpp b/src/modules/m_disable.cpp index 5b28d7987..531b99925 100644 --- a/src/modules/m_disable.cpp +++ b/src/modules/m_disable.cpp @@ -51,13 +51,13 @@ class ModuleDisable : public Module // 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", - chr, field.c_str(), tag->getTagLocation().c_str())); + 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", - chr, field.c_str(), tag->getTagLocation().c_str())); + chr, field.c_str(), tag->source.str().c_str())); // Disable the mode. ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "The %c (%s) %s mode has been disabled", @@ -96,7 +96,7 @@ class ModuleDisable : public Module Command* handler = ServerInstance->Parser.GetHandler(command); if (!handler) throw ModuleException(InspIRCd::Format("Nonexistent command '%s' was specified in <disabled:commands> at %s", - command.c_str(), tag->getTagLocation().c_str())); + command.c_str(), tag->source.str().c_str())); // Prevent admins from disabling MODULES for transparency reasons. if (handler->name == "MODULES") diff --git a/src/modules/m_dnsbl.cpp b/src/modules/m_dnsbl.cpp index c05161232..57243e66b 100644 --- a/src/modules/m_dnsbl.cpp +++ b/src/modules/m_dnsbl.cpp @@ -317,19 +317,19 @@ class ModuleDNSBL : public Module, public Stats::EventListener /* yeah, logic here is a little messy */ if ((e->bitmask <= 0) && (DNSBLConfEntry::A_BITMASK == e->type)) { - throw ModuleException("Invalid <dnsbl:bitmask> at " + tag->getTagLocation()); + throw ModuleException("Invalid <dnsbl:bitmask> at " + tag->source.str()); } else if (e->name.empty()) { - throw ModuleException("Empty <dnsbl:name> at " + tag->getTagLocation()); + throw ModuleException("Empty <dnsbl:name> at " + tag->source.str()); } else if (e->domain.empty()) { - throw ModuleException("Empty <dnsbl:domain> at " + tag->getTagLocation()); + throw ModuleException("Empty <dnsbl:domain> at " + tag->source.str()); } else if (e->banaction == DNSBLConfEntry::I_UNKNOWN) { - throw ModuleException("Unknown <dnsbl:action> at " + tag->getTagLocation()); + throw ModuleException("Unknown <dnsbl:action> at " + tag->source.str()); } else { diff --git a/src/modules/m_helpop.cpp b/src/modules/m_helpop.cpp index e575820f6..c91534f7a 100644 --- a/src/modules/m_helpop.cpp +++ b/src/modules/m_helpop.cpp @@ -124,16 +124,16 @@ class ModuleHelpop // 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->getTagLocation().c_str())); + throw ModuleException(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->getTagLocation().c_str())); + throw ModuleException(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->getTagLocation().c_str())); + throw ModuleException(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. @@ -147,7 +147,7 @@ class ModuleHelpop if (!newhelp.insert(std::make_pair(key, HelpTopic(helpmsg, title))).second) { throw ModuleException(InspIRCd::Format("<helpop> tag with duplicate key '%s' at %s", - key.c_str(), tag->getTagLocation().c_str())); + key.c_str(), tag->source.str().c_str())); } } diff --git a/src/modules/m_hidelist.cpp b/src/modules/m_hidelist.cpp index 4f8539944..556171abe 100644 --- a/src/modules/m_hidelist.cpp +++ b/src/modules/m_hidelist.cpp @@ -67,7 +67,7 @@ class ModuleHideList : public Module { std::string modename = tag->getString("mode"); if (modename.empty()) - throw ModuleException("Empty <hidelist:mode> at " + tag->getTagLocation()); + throw ModuleException("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 int rank = tag->getUInt("rank", HALFOP_VALUE); diff --git a/src/modules/m_hidemode.cpp b/src/modules/m_hidemode.cpp index 360a7aa56..58e6fa655 100644 --- a/src/modules/m_hidemode.cpp +++ b/src/modules/m_hidemode.cpp @@ -46,11 +46,11 @@ class Settings { const std::string modename = tag->getString("mode"); if (modename.empty()) - throw ModuleException("<hidemode:mode> is empty at " + tag->getTagLocation()); + throw ModuleException("<hidemode:mode> is empty at " + tag->source.str()); unsigned int rank = tag->getUInt("rank", 0); if (!rank) - throw ModuleException("<hidemode:rank> must be greater than 0 at " + tag->getTagLocation()); + throw ModuleException("<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 %u", modename.c_str(), rank); newranks.insert(std::make_pair(modename, rank)); diff --git a/src/modules/m_hostchange.cpp b/src/modules/m_hostchange.cpp index ea719c78a..6a52fbaa2 100644 --- a/src/modules/m_hostchange.cpp +++ b/src/modules/m_hostchange.cpp @@ -138,7 +138,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->getTagLocation()); + throw ModuleException("<hostchange:mask> is a mandatory field, at " + tag->source.str()); insp::flat_set<int> ports; const std::string portlist = tag->getString("ports"); @@ -166,7 +166,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->getTagLocation()); + throw ModuleException("<hostchange:value> is a mandatory field when using the 'set' action, at " + tag->source.str()); // The hostname is in the format <value>. rules.push_back(HostRule(mask, value, ports)); @@ -174,7 +174,7 @@ private: } else { - throw ModuleException(action + " is an invalid <hostchange:action> type, at " + tag->getTagLocation()); + throw ModuleException(action + " is an invalid <hostchange:action> type, at " + tag->source.str()); } } diff --git a/src/modules/m_httpd_config.cpp b/src/modules/m_httpd_config.cpp index 826768d8a..2a05a81bb 100644 --- a/src/modules/m_httpd_config.cpp +++ b/src/modules/m_httpd_config.cpp @@ -50,7 +50,7 @@ class ModuleHttpConfig : public Module, public HTTPRequestEventListener for (auto& [_, tag] : ServerInstance->Config->config_data) { // Show the location of the tag in a comment. - buffer << "# " << tag->getTagLocation() << std::endl + buffer << "# " << tag->source.str() << std::endl << '<' << tag->tag << ' '; // Print out the tag with all keys aligned vertically. diff --git a/src/modules/m_ircv3_sts.cpp b/src/modules/m_ircv3_sts.cpp index 1c8a88e8d..3ece15889 100644 --- a/src/modules/m_ircv3_sts.cpp +++ b/src/modules/m_ircv3_sts.cpp @@ -167,11 +167,11 @@ class ModuleIRCv3STS : public Module const std::string host = tag->getString("host"); if (host.empty()) - throw ModuleException("<sts:host> must contain a hostname, at " + tag->getTagLocation()); + throw ModuleException("<sts:host> must contain a hostname, at " + tag->source.str()); unsigned int port = tag->getUInt("port", 0, 0, UINT16_MAX); if (!HasValidSSLPort(port)) - throw ModuleException("<sts:port> must be a TLS port, at " + tag->getTagLocation()); + throw ModuleException("<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_restrictchans.cpp b/src/modules/m_restrictchans.cpp index 4ed4049c5..ccbc5592e 100644 --- a/src/modules/m_restrictchans.cpp +++ b/src/modules/m_restrictchans.cpp @@ -65,7 +65,7 @@ class ModuleRestrictChans : public Module { const std::string name = tag->getString("name"); if (name.empty()) - throw ModuleException("Empty <allowchannel:name> at " + tag->getTagLocation()); + throw ModuleException("Empty <allowchannel:name> at " + tag->source.str()); newallows.insert(name); } diff --git a/src/modules/m_securelist.cpp b/src/modules/m_securelist.cpp index a0dd8e884..01d566f58 100644 --- a/src/modules/m_securelist.cpp +++ b/src/modules/m_securelist.cpp @@ -55,7 +55,7 @@ class ModuleSecureList { std::string host = tag->getString("exception"); if (host.empty()) - throw ModuleException("<securehost:exception> is a required field at " + tag->getTagLocation()); + throw ModuleException("<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 7f2c062ab..e4f577854 100644 --- a/src/modules/m_showfile.cpp +++ b/src/modules/m_showfile.cpp @@ -158,7 +158,7 @@ class ModuleShowFile : public Module } catch (CoreException& ex) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Error: " + ex.GetReason() + " at " + tag->getTagLocation()); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Error: " + ex.GetReason() + " at " + tag->source.str()); } } diff --git a/src/modules/m_spanningtree/treeserver.cpp b/src/modules/m_spanningtree/treeserver.cpp index ce4469a9a..479ed00b8 100644 --- a/src/modules/m_spanningtree/treeserver.cpp +++ b/src/modules/m_spanningtree/treeserver.cpp @@ -249,7 +249,7 @@ void TreeServer::CheckULine() { if (this->IsRoot()) { - ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Servers should not uline themselves (at " + tag->getTagLocation() + ")"); + ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "Servers should not uline themselves (at " + tag->source.str() + ")"); return; } diff --git a/src/modules/m_sqloper.cpp b/src/modules/m_sqloper.cpp index 05331e3b1..a42b5c7f5 100644 --- a/src/modules/m_sqloper.cpp +++ b/src/modules/m_sqloper.cpp @@ -70,7 +70,7 @@ class OperQuery : public SQL::Query res.GetCols(cols); // Create the oper tag as if we were the conf file. - auto tag = std::make_shared<ConfigTag>("oper", MODNAME, 0); + auto tag = std::make_shared<ConfigTag>("oper", FilePosition("<" MODNAME ">", 0, 0)); /** Iterate through each column in the SQLOpers table. An infinite number of fields can be specified. * Column 'x' with cell value 'y' will be the same as x=y in an OPER block in opers.conf. diff --git a/src/modules/m_vhost.cpp b/src/modules/m_vhost.cpp index 2a519f23d..b5f47b7cd 100644 --- a/src/modules/m_vhost.cpp +++ b/src/modules/m_vhost.cpp @@ -102,21 +102,21 @@ class ModuleVHost : public Module { std::string mask = tag->getString("host"); if (mask.empty()) - throw ModuleException("<vhost:host> is empty! at " + tag->getTagLocation()); + throw ModuleException("<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->getTagLocation()); + throw ModuleException("<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->getTagLocation()); + throw ModuleException("<vhost:pass> is empty! at " + tag->source.str()); const std::string hash = tag->getString("hash", "plaintext", 1); if (stdalgo::string::equalsci(hash, "plaintext")) { ServerInstance->Logs.Log(MODNAME, LOG_DEFAULT, "<vhost> tag for %s at %s contains an plain text password, this is insecure!", - username.c_str(), tag->getTagLocation().c_str()); + username.c_str(), tag->source.str().c_str()); } CustomVhost vhost(username, pass, hash, mask); diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 57887393c..556329be7 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -520,7 +520,7 @@ class ModuleWebSocket : public Module // 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->getTagLocation()); + throw ModuleException("<wsorigin:allow> is a mandatory field, at " + tag->source.str()); config.allowedorigins.push_back(allow); } diff --git a/src/socket.cpp b/src/socket.cpp index d98955f12..87bde3a4c 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -37,7 +37,7 @@ bool InspIRCd::BindPort(std::shared_ptr<ConfigTag> tag, const irc::sockets::sock { // Replace tag, we know addr and port match, but other info (type, ssl) may not. ServerInstance->Logs.Log("SOCKET", LOG_DEFAULT, "Replacing listener on %s from old tag at %s with new tag from %s", - sa.str().c_str(), (*n)->bind_tag->getTagLocation().c_str(), tag->getTagLocation().c_str()); + sa.str().c_str(), (*n)->bind_tag->source.str().c_str(), tag->source.str().c_str()); (*n)->bind_tag = tag; (*n)->ResetIOHookProvider(); @@ -50,12 +50,12 @@ bool InspIRCd::BindPort(std::shared_ptr<ConfigTag> tag, const irc::sockets::sock if (!ll->HasFd()) { ServerInstance->Logs.Log("SOCKET", LOG_DEFAULT, "Failed to listen on %s from tag at %s: %s", - sa.str().c_str(), tag->getTagLocation().c_str(), strerror(errno)); + sa.str().c_str(), tag->source.str().c_str(), strerror(errno)); delete ll; return false; } - ServerInstance->Logs.Log("SOCKET", LOG_DEFAULT, "Added a listener on %s from tag at %s", sa.str().c_str(), tag->getTagLocation().c_str()); + ServerInstance->Logs.Log("SOCKET", LOG_DEFAULT, "Added a listener on %s from tag at %s", sa.str().c_str(), tag->source.str().c_str()); ports.push_back(ll); return true; } @@ -79,7 +79,7 @@ size_t InspIRCd::BindPorts(FailedPortList& failed_ports) // A TCP listener with no ports is not very useful. if (portlist.empty()) this->Logs.Log("SOCKET", LOG_DEFAULT, "TCP listener on %s at %s has no ports specified!", - address.empty() ? "*" : address.c_str(), tag->getTagLocation().c_str()); + address.empty() ? "*" : address.c_str(), tag->source.str().c_str()); irc::portparser portrange(portlist, false); for (int port; (port = portrange.GetToken()); ) @@ -109,7 +109,7 @@ size_t InspIRCd::BindPorts(FailedPortList& failed_ports) if (fullpath.length() > std::min(ServerInstance->Config->Limits.MaxHost, sizeof(bindspec.un.sun_path) - 1)) { this->Logs.Log("SOCKET", LOG_DEFAULT, "UNIX listener on %s at %s specified a path that is too long!", - fullpath.c_str(), tag->getTagLocation().c_str()); + fullpath.c_str(), tag->source.str().c_str()); continue; } @@ -117,7 +117,7 @@ size_t InspIRCd::BindPorts(FailedPortList& failed_ports) if (fullpath.find_first_of("\n\r\t!@: ") != std::string::npos) { this->Logs.Log("SOCKET", LOG_DEFAULT, "UNIX listener on %s at %s specified a path containing invalid characters!", - fullpath.c_str(), tag->getTagLocation().c_str()); + fullpath.c_str(), tag->source.str().c_str()); continue; } diff --git a/src/usermanager.cpp b/src/usermanager.cpp index e60bd23c0..5e50dc730 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -162,7 +162,7 @@ void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs ServerInstance->Logs.Log("USERS", LOG_DEBUG, "Non-existent I/O hook '%s' in <bind:%s> tag at %s", iohookprovref.GetProvider().c_str(), i == via->iohookprovs.begin() ? "hook" : "ssl", - via->bind_tag->getTagLocation().c_str()); + via->bind_tag->source.str().c_str()); this->QuitUser(New, "Internal error handling connection"); return; } diff --git a/src/users.cpp b/src/users.cpp index e8c0e4c56..efe91c4bb 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -1239,7 +1239,7 @@ ConnectClass::ConnectClass(std::shared_ptr<ConfigTag> tag, char t, const std::st // Connect classes can inherit from each other but this is problematic for modules which can't use // ConnectClass::Update so we build a hybrid tag containing all of the values set on this class as // well as the parent class. - config = std::make_shared<ConfigTag>(tag->tag, tag->src_name, tag->src_line); + config = std::make_shared<ConfigTag>(tag->tag, tag->source); for (const auto& [key, value] : parent->config->GetItems()) { // The class name and parent name are not inherited |
