diff options
| author | 2021-03-14 04:55:01 +0000 | |
|---|---|---|
| committer | 2021-03-17 04:16:24 +0000 | |
| commit | 8cb6691601602e560fbf3cb2122dd4e12bb4bcf1 (patch) | |
| tree | aca1965bdc281e9bbaf4490ccff63ceab09ee166 /src/modules | |
| parent | Merge branch 'insp3' into master. (diff) | |
| parent | Default <permchannelsdb:listmodes> to on. (diff) | |
Merge branch 'insp3' into master.
Diffstat (limited to 'src/modules')
| -rw-r--r-- | src/modules/m_filter.cpp | 84 | ||||
| -rw-r--r-- | src/modules/m_permchannels.cpp | 2 |
2 files changed, 83 insertions, 3 deletions
diff --git a/src/modules/m_filter.cpp b/src/modules/m_filter.cpp index 8709bbbba..ae9ef2431 100644 --- a/src/modules/m_filter.cpp +++ b/src/modules/m_filter.cpp @@ -39,6 +39,8 @@ #include "modules/stats.h" #include "modules/account.h" +#include <fstream> + enum FilterFlags { FLAG_PART = 2, @@ -132,7 +134,7 @@ class FilterResult return 0; } - std::string GetFlags() + std::string GetFlags() const { std::string flags; if (flag_no_opers) @@ -186,12 +188,15 @@ class ModuleFilter : public Module , public ServerProtocol::SyncEventListener , public Stats::EventListener + , public Timer { typedef insp::flat_set<std::string, irc::insensitive_swo> ExemptTargetSet; bool initing = true; bool notifyuser; bool warnonselfmsg; + bool dirty = false; + std::string filterconf; Regex::Engine* factory; void FreeFilters(); @@ -224,6 +229,7 @@ class ModuleFilter ModResult OnStats(Stats::Context& stats) override; ModResult OnPreCommand(std::string& command, CommandBase::Params& parameters, LocalUser* user, bool validated) override; void OnUnloadModule(Module* mod) override; + bool Tick(time_t) override; bool AppliesToMe(User* user, FilterResult* filter, int flags); void ReadFilters(); static bool StringToFilterAction(const std::string& str, FilterAction& fa); @@ -347,6 +353,7 @@ ModuleFilter::ModuleFilter() : Module(VF_VENDOR | VF_COMMON, "Adds the /FILTER command which allows server operators to define regex matches for inappropriate phrases that are not allowed to be used in channel messages, private messages, part messages, or quit messages.") , ServerProtocol::SyncEventListener(this) , Stats::EventListener(this) + , Timer(0, true) , filtcommand(this) , RegexEngine(this) { @@ -366,6 +373,7 @@ Cullable::Result ModuleFilter::Cull() void ModuleFilter::FreeFilters() { filters.clear(); + dirty = true; } ModResult ModuleFilter::OnUserPreMessage(User* user, const MessageTarget& msgtarget, MessageDetails& details) @@ -629,6 +637,10 @@ void ModuleFilter::ReadConfig(ConfigStatus& status) std::string newrxengine = tag->getString("engine"); notifyuser = tag->getBool("notifyuser", true); warnonselfmsg = tag->getBool("warnonselfmsg"); + filterconf = tag->getString("filename"); + if (!filterconf.empty()) + filterconf = ServerInstance->Config->Paths.PrependConfig(filterconf); + SetInterval(tag->getDuration("saveperiod", 5)); factory = RegexEngine ? (RegexEngine.operator->()) : NULL; @@ -767,6 +779,7 @@ bool ModuleFilter::DeleteFilter(const std::string& freeform, std::string& reason { reason.assign(i->reason); filters.erase(i); + dirty = true; return true; } } @@ -786,6 +799,7 @@ std::pair<bool, std::string> ModuleFilter::AddFilter(const std::string& freeform try { filters.push_back(FilterResult(RegexEngine, freeform, reason, type, duration, flgs, config)); + dirty = true; } catch (ModuleException &e) { @@ -863,7 +877,7 @@ void ModuleFilter::ReadFilters() if (!StringToFilterAction(action, fa)) fa = FA_NONE; - std::pair<bool, std::string> result = static_cast<ModuleFilter*>(this)->AddFilter(pattern, fa, reason, duration, flgs, true); + std::pair<bool, std::string> result = static_cast<ModuleFilter*>(this)->AddFilter(pattern, fa, reason, duration, flgs, !tag->getBool("generated")); if (result.first) removedfilters.erase(pattern); else @@ -911,4 +925,70 @@ void ModuleFilter::OnUnloadModule(Module* mod) } } +bool ModuleFilter::Tick(time_t) +{ + if (!dirty) // No need to write. + return true; + + if (filterconf.empty()) // Nothing to write to. + { + dirty = false; + return true; + } + + const std::string newfilterconf = filterconf + ".tmp"; + std::ofstream stream(newfilterconf.c_str()); + if (!stream.is_open()) // Filesystem probably not writable. + { + ServerInstance->SNO.WriteToSnoMask('f', "Unable to save filters to \"%s\": %s (%d)", + newfilterconf.c_str(), strerror(errno), errno); + return true; + } + + stream << "# This file is automatically generated by the filter module. Any changes will be overwritten." << std::endl + << "# If you want to convert this to a normal config file you *MUST* remove the generated=\"yes\" keys!" << std::endl + << std::endl + << "<config format=\"xml\">" << std::endl; + + for (std::vector<FilterResult>::iterator i = filters.begin(); i != filters.end(); ++i) + { + // # <keyword reason="You qwertied!" action="block" flags="pn"> + const FilterResult& filter = (*i); + if (filter.from_config) + continue; + + stream << "<keyword generated=\"yes" + << "\" pattern=\"" << ServerConfig::Escape(filter.freeform) + << "\" reason=\"" << ServerConfig::Escape(filter.reason) + << "\" action=\"" << FilterActionToString(filter.action) + << "\" flags=\"" << filter.GetFlags(); + if (filter.duration) + stream << "\" duration=\"" << InspIRCd::DurationString(filter.duration); + stream << "\">" << std::endl; + } + + if (stream.fail()) // Filesystem probably not writable. + { + ServerInstance->SNO.WriteToSnoMask('f', "Unable to save filters to \"%s\": %s (%d)", + newfilterconf.c_str(), strerror(errno), errno); + return true; + } + stream.close(); + +#ifdef _WIN32 + remove(filterconf.c_str()); +#endif + + // Use rename to move temporary to new db - this is guaranteed not to fuck up, even in case of a crash. + if (rename(newfilterconf.c_str(), filterconf.c_str()) < 0) + { + ServerInstance->SNO.WriteToSnoMask('f', "Unable to replace old filter config \"%s\" with \"%s\": %s (%d)", + filterconf.c_str(), newfilterconf.c_str(), strerror(errno), errno); + return true; + } + + dirty = false; + return true; +} + MODULE_INIT(ModuleFilter) diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index 17f7783a9..da3cd7057 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -185,7 +185,7 @@ public: { auto tag = ServerInstance->Config->ConfValue("permchanneldb"); permchannelsconf = tag->getString("filename"); - save_listmodes = tag->getBool("listmodes"); + save_listmodes = tag->getBool("listmodes", true); SetInterval(tag->getDuration("saveperiod", 5)); if (!permchannelsconf.empty()) |
