aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Sadie Powell2023-07-03 17:26:40 +0100
committerGravatar Sadie Powell2023-07-03 18:43:58 +0100
commit386f0dafd55897723356c75299cd02ed0b882f5b (patch)
treebe31de75870a0e1da815cf5f4203fed793eb66ba /src
parentFix a minor Doxygen comment issue. (diff)
Replace FileReader with something more sensible.
Diffstat (limited to 'src')
-rw-r--r--src/configparser.cpp25
-rw-r--r--src/configreader.cpp45
-rw-r--r--src/coremods/core_info/cmd_motd.cpp2
-rw-r--r--src/coremods/core_info/core_info.cpp19
-rw-r--r--src/coremods/core_info/core_info.h3
-rw-r--r--src/fileutils.cpp66
-rw-r--r--src/modules/extra/m_ssl_gnutls.cpp10
-rw-r--r--src/modules/m_opermotd.cpp15
-rw-r--r--src/modules/m_randquote.cpp14
-rw-r--r--src/modules/m_showfile.cpp16
10 files changed, 89 insertions, 126 deletions
diff --git a/src/configparser.cpp b/src/configparser.cpp
index 985996fda..044897023 100644
--- a/src/configparser.cpp
+++ b/src/configparser.cpp
@@ -452,33 +452,16 @@ void ParseStack::DoReadFile(const std::string& key, const std::string& name, int
if (exec && (flags & FLAG_NO_EXEC))
throw CoreException("Invalid <execfiles> tag in file included with noexec=\"yes\"");
- std::string path = name;
- if (!exec)
- path = ServerInstance->Config->Paths.PrependConfig(name);
-
- auto file = DoOpenFile(path, exec);
- if (!file)
- throw CoreException(INSP_FORMAT("Could not read \"{}\" for {}: {}", path, key, strerror(errno)));
-
- file_cache& cache = FilesOutput[key];
- cache.clear();
-
- char linebuf[5120];
- while (fgets(linebuf, sizeof(linebuf), file.get()))
+ if (FilesOutput.emplace(key, std::make_pair(name, exec)).second)
{
- size_t len = strlen(linebuf);
- if (len)
- {
- if (linebuf[len-1] == '\n')
- len--;
- cache.push_back(std::string(linebuf, len));
- }
+ ServerInstance->Logs.Debug("CONFIG", "Stored config key: {} => {} (executable: {}).",
+ key, name, exec ? "yes" : "no");
}
}
ParseStack::ParseStack(ServerConfig* conf)
: output(conf->config_data)
- , FilesOutput(conf->Files)
+ , FilesOutput(conf->filesources)
, errstr(conf->errstr)
{
vars = {
diff --git a/src/configreader.cpp b/src/configreader.cpp
index 363bc16c4..1c418eae7 100644
--- a/src/configreader.cpp
+++ b/src/configreader.cpp
@@ -40,6 +40,12 @@
#include "configparser.h"
#include "exitcodes.h"
+ServerConfig::ReadResult::ReadResult(const std::string& c, const std::string& e)
+ : contents(c)
+ , error(e)
+{
+}
+
ServerConfig::ServerLimits::ServerLimits(const std::shared_ptr<ConfigTag>& tag)
: MaxLine(tag->getNum<size_t>("maxline", 512, 512))
, MaxNick(tag->getNum<size_t>("maxnick", 30, 1, MaxLine))
@@ -88,6 +94,45 @@ ServerConfig::ServerConfig()
{
}
+ServerConfig::ReadResult ServerConfig::ReadFile(const std::string& file, bool invalidate)
+{
+ auto contents = filecontents.find(file);
+ if (invalidate)
+ filecontents.erase(contents);
+ else if (contents != filecontents.end())
+ return ReadResult(contents->second, {});
+
+ bool executable = false;
+ std::string name = file;
+ std::string path = file;
+
+ // If the caller specified a short name (e.g. <file motd="motd.txt">) then look it up.
+ auto source = filesources.find(file);
+ if (source != filesources.end())
+ {
+ name = source->first;
+ path = source->second.second;
+ executable = source->second.second;
+ }
+
+ // Try to open the file and error out if it fails.
+ auto fh = ParseStack::DoOpenFile(path, executable);
+ if (!fh)
+ return ReadResult({}, strerror(errno));
+
+ std::stringstream datastream;
+ char databuf[4096];
+ while (fgets(databuf, sizeof(databuf), fh.get()))
+ {
+ size_t len = strlen(databuf);
+ if (len)
+ datastream.write(databuf, len);
+ }
+
+ filecontents[name] = datastream.str();
+ return ReadResult(filecontents[name], {});
+}
+
void ServerConfig::CrossCheckOperBlocks()
{
std::unordered_map<std::string, std::shared_ptr<ConfigTag>> operclass;
diff --git a/src/coremods/core_info/cmd_motd.cpp b/src/coremods/core_info/cmd_motd.cpp
index 1f7bf75f8..424912524 100644
--- a/src/coremods/core_info/cmd_motd.cpp
+++ b/src/coremods/core_info/cmd_motd.cpp
@@ -57,7 +57,7 @@ CmdResult CommandMotd::Handle(User* user, const Params& parameters)
tag = localuser->GetClass()->config;
const std::string motd_name = tag->getString("motd", "motd", 1);
- ConfigFileCache::iterator motd = motds.find(motd_name);
+ auto motd = motds.find(motd_name);
if (motd == motds.end())
{
user->WriteRemoteNumeric(ERR_NOMOTD, "There is no message of the day.");
diff --git a/src/coremods/core_info/core_info.cpp b/src/coremods/core_info/core_info.cpp
index da69cddf7..8c2752c65 100644
--- a/src/coremods/core_info/core_info.cpp
+++ b/src/coremods/core_info/core_info.cpp
@@ -21,7 +21,6 @@
#include "inspircd.h"
#include "clientprotocolmsg.h"
-#include "fileutils.h"
#include "timeutils.h"
#include "core_info.h"
@@ -128,7 +127,7 @@ public:
void ReadConfig(ConfigStatus& status) override
{
// Process the escape codes in the MOTDs.
- ConfigFileCache newmotds;
+ CommandMotd::MessageCache newmotds;
for (const auto& klass : ServerInstance->Config->Classes)
{
// Don't process the file if it has already been processed.
@@ -136,23 +135,19 @@ public:
if (newmotds.find(motd) != newmotds.end())
continue;
- FileReader reader;
- try
- {
- reader.Load(motd);
- }
- catch (const CoreException& ce)
+ auto file = ServerInstance->Config->ReadFile(motd);
+ if (!file)
{
// We can't process the file if it doesn't exist.
ServerInstance->Logs.Warning(MODNAME, "Unable to read motd for connect class \"{}\" at {}: {}",
- klass->GetName(), klass->config->source.str(), ce.GetReason());
+ klass->GetName(), klass->config->source.str(), file.error);
continue;
}
// Process the MOTD entry.
- file_cache& newmotd = newmotds[motd];
- newmotd.reserve(reader.GetVector().size());
- for (const auto& line : reader.GetVector())
+ auto& newmotd = newmotds[motd];
+ irc::sepstream linestream(file.contents, '\n');
+ for (std::string line; linestream.GetToken(line); )
{
// Some clients can not handle receiving RPL_MOTD with an empty
// trailing parameter so if a line is empty we replace it with
diff --git a/src/coremods/core_info/core_info.h b/src/coremods/core_info/core_info.h
index db4614098..f68a66434 100644
--- a/src/coremods/core_info/core_info.h
+++ b/src/coremods/core_info/core_info.h
@@ -118,7 +118,8 @@ class CommandMotd final
: public ServerTargetCommand
{
public:
- ConfigFileCache motds;
+ typedef insp::flat_map<std::string, std::vector<std::string>> MessageCache;
+ MessageCache motds;
CommandMotd(Module* parent);
CmdResult Handle(User* user, const Params& parameters) override;
diff --git a/src/fileutils.cpp b/src/fileutils.cpp
deleted file mode 100644
index 7084d8576..000000000
--- a/src/fileutils.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * InspIRCd -- Internet Relay Chat Daemon
- *
- * Copyright (C) 2013, 2019-2020 Sadie Powell <sadie@witchery.services>
- * Copyright (C) 2013 Attila Molnar <attilamolnar@hush.com>
- *
- * This file is part of InspIRCd. InspIRCd is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, version 2.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "inspircd.h"
-#include "fileutils.h"
-
-#include <fstream>
-
-FileReader::FileReader(const std::string& filename)
-{
- Load(filename);
-}
-
-void FileReader::Load(const std::string& filename)
-{
- // If the file is stored in the file cache then we used that version instead.
- ConfigFileCache::const_iterator it = ServerInstance->Config->Files.find(filename);
- if (it != ServerInstance->Config->Files.end())
- {
- this->lines = it->second;
- }
- else
- {
- std::ifstream stream(ServerInstance->Config->Paths.PrependConfig(filename));
- if (!stream.is_open())
- throw CoreException(filename + " does not exist or is not readable!");
-
- lines.clear();
- std::string line;
- while (std::getline(stream, line))
- {
- lines.push_back(line);
- totalSize += line.size() + 2;
- }
-
- stream.close();
- }
-}
-
-std::string FileReader::GetString() const
-{
- std::string buffer;
- for (const auto& line : lines)
- {
- buffer.append(line);
- buffer.append("\r\n");
- }
- return buffer;
-}
diff --git a/src/modules/extra/m_ssl_gnutls.cpp b/src/modules/extra/m_ssl_gnutls.cpp
index 5ee85d3e1..4ac29186d 100644
--- a/src/modules/extra/m_ssl_gnutls.cpp
+++ b/src/modules/extra/m_ssl_gnutls.cpp
@@ -40,7 +40,6 @@
/// $PackageInfo: require_system("ubuntu") gnutls-bin libgnutls28-dev pkg-config
#include "inspircd.h"
-#include "fileutils.h"
#include "modules/ssl.h"
#include "timeutils.h"
@@ -486,11 +485,10 @@ namespace GnuTLS
static std::string ReadFile(const std::string& filename)
{
- FileReader reader(filename);
- std::string ret = reader.GetString();
- if (ret.empty())
- throw Exception("Cannot read file " + filename);
- return ret;
+ auto file = ServerInstance->Config->ReadFile(filename);
+ if (!file)
+ throw Exception("Cannot read file " + filename + ": " + file.error);
+ return file.contents;
}
static std::string GetPrioStr(const std::string& profilename, const std::shared_ptr<ConfigTag>& tag)
diff --git a/src/modules/m_opermotd.cpp b/src/modules/m_opermotd.cpp
index 7a844d8cd..c61d979ff 100644
--- a/src/modules/m_opermotd.cpp
+++ b/src/modules/m_opermotd.cpp
@@ -25,7 +25,6 @@
#include "inspircd.h"
-#include "fileutils.h"
enum
{
@@ -104,23 +103,19 @@ private:
if (motd.empty() || newmotds.find(motd) != newmotds.end())
return;
- FileReader reader;
- try
- {
- reader.Load(motd);
- }
- catch (const CoreException& ce)
+ auto file = ServerInstance->Config->ReadFile(motd);
+ if (!file)
{
// We can't process the file if it doesn't exist.
ServerInstance->Logs.Normal(MODNAME, "Unable to read server operator motd for oper {} \"{}\" at {}: {}",
- type, oper->GetName(), oper->GetConfig()->source.str(), ce.GetReason());
+ type, oper->GetName(), oper->GetConfig()->source.str(), file.error);
return;
}
// Process the MOTD entry.
auto& newmotd = newmotds[motd];
- newmotd.reserve(reader.GetVector().size());
- for (const auto& line : reader.GetVector())
+ irc::sepstream linestream(file.contents, '\n');
+ for (std::string line; linestream.GetToken(line); )
{
// Some clients can not handle receiving RPL_OMOTD with an empty
// trailing parameter so if a line is empty we replace it with
diff --git a/src/modules/m_randquote.cpp b/src/modules/m_randquote.cpp
index ceb2b1982..beecd2680 100644
--- a/src/modules/m_randquote.cpp
+++ b/src/modules/m_randquote.cpp
@@ -22,7 +22,6 @@
#include "inspircd.h"
-#include "fileutils.h"
class ModuleRandQuote final
: public Module
@@ -43,8 +42,17 @@ public:
const auto& conf = ServerInstance->Config->ConfValue("randquote");
prefix = conf->getString("prefix");
suffix = conf->getString("suffix");
- FileReader reader(conf->getString("file", "quotes", 1));
- quotes = reader.GetVector();
+
+ const std::string filestr = conf->getString("file", "quotes", 1);
+ auto file = ServerInstance->Config->ReadFile(filestr);
+ if (!file)
+ throw ModuleException(this, "Unable to read quotes from " + filestr + ": " + file.error);
+
+ std::vector<std::string> newquotes;
+ irc::sepstream linestream(file.contents, '\n');
+ for (std::string line; linestream.GetToken(line); )
+ newquotes.push_back(line);
+ std::swap(quotes, newquotes);
}
void OnUserConnect(LocalUser* user) override
diff --git a/src/modules/m_showfile.cpp b/src/modules/m_showfile.cpp
index 8273885a2..60a3f4a92 100644
--- a/src/modules/m_showfile.cpp
+++ b/src/modules/m_showfile.cpp
@@ -20,7 +20,6 @@
#include "inspircd.h"
#include "clientprotocolmsg.h"
-#include "fileutils.h"
enum
{
@@ -80,7 +79,7 @@ public:
return CmdResult::SUCCESS;
}
- void UpdateSettings(const std::shared_ptr<ConfigTag>& tag, const std::vector<std::string>& filecontents)
+ void UpdateSettings(const std::shared_ptr<ConfigTag>& tag, const std::string& filecontents)
{
introtext = tag->getString("introtext", "Showing " + name);
endtext = tag->getString("endtext", "End of " + name);
@@ -97,8 +96,9 @@ public:
// Process the entry.
contents.clear();
- contents.reserve(filecontents.size());
- for (const auto& line : filecontents)
+
+ irc::sepstream linestream(filecontents, '\n');
+ for (std::string line; linestream.GetToken(line); )
{
// Some clients can not handle receiving NOTICE/PRIVMSG/RPL_RULES
// with an empty trailing parameter so if a line is empty we
@@ -106,6 +106,7 @@ public:
contents.push_back(line.empty() ? " " : line);
}
InspIRCd::ProcessColors(contents);
+ contents.shrink_to_fit();
}
};
@@ -126,7 +127,10 @@ private:
const std::string file = tag->getString("file", cmdname);
if (file.empty())
throw ModuleException(this, "Empty value for 'file'");
- FileReader reader(file);
+
+ auto reader = ServerInstance->Config->ReadFile(file);
+ if (!reader)
+ throw ModuleException(this, "Unable to read " + file + ": " + reader.error);
CommandShowFile* sfcmd;
Command* handler = ServerInstance->Parser.GetHandler(cmdname);
@@ -148,7 +152,7 @@ private:
ServerInstance->Modules.AddService(*sfcmd);
}
- sfcmd->UpdateSettings(tag, reader.GetVector());
+ sfcmd->UpdateSettings(tag, reader.contents);
newcmds.push_back(sfcmd);
}