mirror of
https://github.com/anope/anope.git
synced 2026-06-12 17:04:47 +02:00
168 lines
3.7 KiB
C++
168 lines
3.7 KiB
C++
// Anope IRC Services <https://www.anope.org/>
|
|
//
|
|
// Copyright (C) 2003-2026 Anope Contributors
|
|
//
|
|
// Anope is free software. You can use, modify, and/or distribute it under the
|
|
// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt
|
|
// for the complete terms of this license and docs/AUTHORS.txt for a list of
|
|
// contributors.
|
|
//
|
|
// Based on the original code of Epona by Lara
|
|
// Based on the original code of Services by Andy Church
|
|
//
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
#include "module.h"
|
|
|
|
class LoadData final
|
|
: public Serialize::Data
|
|
{
|
|
public:
|
|
std::fstream *fs;
|
|
Serializable::Id id = 0;
|
|
std::map<Anope::string, Anope::string> data;
|
|
bool read = false;
|
|
|
|
LoadData(std::fstream &fsref)
|
|
: fs(&fsref)
|
|
{
|
|
}
|
|
|
|
bool LoadInternal(const Anope::string &key, Anope::string &value) override
|
|
{
|
|
if (!read)
|
|
{
|
|
for (Anope::string token; std::getline(*this->fs, token.str());)
|
|
{
|
|
if (token.find("ID ") == 0)
|
|
{
|
|
this->id = Anope::Convert<Serializable::Id>(token.substr(3), 0);
|
|
continue;
|
|
}
|
|
else if (token.find("DATA ") != 0)
|
|
break;
|
|
|
|
size_t sp = token.find(' ', 5); // Skip DATA
|
|
if (sp != Anope::string::npos)
|
|
data[token.substr(5, sp - 5)] = token.substr(sp + 1);
|
|
}
|
|
|
|
read = true;
|
|
}
|
|
|
|
value = this->data[key];
|
|
return true;
|
|
}
|
|
|
|
bool StoreInternal(const Anope::string &key, const Anope::string &value) override
|
|
{
|
|
return false; // This module can only load data.
|
|
}
|
|
|
|
size_t Hash() const override
|
|
{
|
|
size_t hash = 0;
|
|
for (const auto &[_, value] : this->data)
|
|
if (!value.empty())
|
|
hash ^= Anope::hash_cs()(value);
|
|
return hash;
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
id = 0;
|
|
read = false;
|
|
data.clear();
|
|
}
|
|
};
|
|
|
|
class DBFlatFile final
|
|
: public Module
|
|
{
|
|
private:
|
|
bool loaded = false;
|
|
|
|
public:
|
|
DBFlatFile(const Anope::string &modname, const Anope::string &creator)
|
|
: Module(modname, creator, DATABASE | DEPRECATED | VENDOR)
|
|
{
|
|
}
|
|
|
|
EventReturn OnLoadDatabase() override
|
|
{
|
|
std::set<Anope::string> tried_dbs;
|
|
|
|
const auto db_name = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
|
|
|
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
|
|
if (!fd.is_open())
|
|
{
|
|
Log(this) << "Unable to open " << db_name << " for reading!";
|
|
return EVENT_STOP;
|
|
}
|
|
|
|
std::map<Anope::string, std::vector<std::streampos> > positions;
|
|
|
|
for (Anope::string buf; std::getline(fd, buf.str());)
|
|
if (buf.find("OBJECT ") == 0)
|
|
positions[buf.substr(7)].push_back(fd.tellg());
|
|
|
|
LoadData ld(fd);
|
|
for (const auto &type_order : Serialize::Type::GetTypeOrder())
|
|
{
|
|
Serialize::Type *stype = Serialize::Type::Find(type_order);
|
|
if (!stype || stype->GetOwner())
|
|
continue;
|
|
|
|
for (const auto &position : positions[stype->GetName()])
|
|
{
|
|
fd.clear();
|
|
fd.seekg(position);
|
|
|
|
Serializable *obj = stype->Unserialize(NULL, ld);
|
|
if (obj != NULL)
|
|
obj->object_id = ld.id;
|
|
ld.Reset();
|
|
}
|
|
}
|
|
|
|
fd.close();
|
|
|
|
loaded = true;
|
|
return EVENT_STOP;
|
|
}
|
|
|
|
void OnSerializeTypeCreate(Serialize::Type *stype) override
|
|
{
|
|
if (!loaded)
|
|
return;
|
|
|
|
Anope::string db_name;
|
|
if (stype->GetOwner())
|
|
db_name = Anope::ExpandData("module_" + stype->GetOwner()->name + ".db");
|
|
else
|
|
db_name = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
|
|
|
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
|
|
if (!fd.is_open())
|
|
{
|
|
Log(this) << "Unable to open " << db_name << " for reading!";
|
|
return;
|
|
}
|
|
|
|
LoadData ld(fd);
|
|
for (Anope::string buf; std::getline(fd, buf.str());)
|
|
{
|
|
if (buf == "OBJECT " + stype->GetName())
|
|
{
|
|
stype->Unserialize(NULL, ld);
|
|
ld.Reset();
|
|
}
|
|
}
|
|
|
|
fd.close();
|
|
}
|
|
};
|
|
|
|
MODULE_INIT(DBFlatFile)
|