summaryrefslogtreecommitdiff
path: root/modules/database
diff options
context:
space:
mode:
Diffstat (limited to 'modules/database')
-rw-r--r--modules/database/CMakeLists.txt2
-rw-r--r--modules/database/db_flatfile.cpp415
-rw-r--r--modules/database/db_redis.cpp644
-rw-r--r--modules/database/db_sql.cpp261
-rw-r--r--modules/database/db_sql_live.cpp265
-rw-r--r--modules/database/flatfile.cpp807
-rw-r--r--modules/database/old.cpp (renamed from modules/database/db_old.cpp)652
-rw-r--r--modules/database/sql.cpp380
8 files changed, 1574 insertions, 1852 deletions
diff --git a/modules/database/CMakeLists.txt b/modules/database/CMakeLists.txt
new file mode 100644
index 000000000..9a236d6d0
--- /dev/null
+++ b/modules/database/CMakeLists.txt
@@ -0,0 +1,2 @@
+build_modules(${CMAKE_CURRENT_SOURCE_DIR})
+build_modules_dependencies(${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/modules/database/db_flatfile.cpp b/modules/database/db_flatfile.cpp
deleted file mode 100644
index 171573d1c..000000000
--- a/modules/database/db_flatfile.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-
-#ifndef _WIN32
-#include <sys/wait.h>
-#endif
-
-class SaveData : public Serialize::Data
-{
- public:
- Anope::string last;
- std::fstream *fs;
-
- SaveData() : fs(NULL) { }
-
- std::iostream& operator[](const Anope::string &key) anope_override
- {
- if (key != last)
- {
- *fs << "\nDATA " << key << " ";
- last = key;
- }
-
- return *fs;
- }
-};
-
-class LoadData : public Serialize::Data
-{
- public:
- std::fstream *fs;
- unsigned int id;
- std::map<Anope::string, Anope::string> data;
- std::stringstream ss;
- bool read;
-
- LoadData() : fs(NULL), id(0), read(false) { }
-
- std::iostream& operator[](const Anope::string &key) anope_override
- {
- if (!read)
- {
- for (Anope::string token; std::getline(*this->fs, token.str());)
- {
- if (token.find("ID ") == 0)
- {
- try
- {
- this->id = convertTo<unsigned int>(token.substr(3));
- }
- catch (const ConvertException &) { }
-
- 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;
- }
-
- ss.clear();
- this->ss << this->data[key];
- return this->ss;
- }
-
- std::set<Anope::string> KeySet() const anope_override
- {
- std::set<Anope::string> keys;
- for (std::map<Anope::string, Anope::string>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- keys.insert(it->first);
- return keys;
- }
-
- size_t Hash() const anope_override
- {
- size_t hash = 0;
- for (std::map<Anope::string, Anope::string>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- if (!it->second.empty())
- hash ^= Anope::hash_cs()(it->second);
- return hash;
- }
-
- void Reset()
- {
- id = 0;
- read = false;
- data.clear();
- }
-};
-
-class DBFlatFile : public Module, public Pipe
-{
- /* Day the last backup was on */
- int last_day;
- /* Backup file names */
- std::map<Anope::string, std::list<Anope::string> > backups;
- bool loaded;
-
- int child_pid;
-
- void BackupDatabase()
- {
- tm *tm = localtime(&Anope::CurTime);
-
- if (tm->tm_mday != last_day)
- {
- last_day = tm->tm_mday;
-
- const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
-
- std::set<Anope::string> dbs;
- dbs.insert(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
-
- for (unsigned i = 0; i < type_order.size(); ++i)
- {
- Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
-
- if (stype && stype->GetOwner())
- dbs.insert("module_" + stype->GetOwner()->name + ".db");
- }
-
-
- for (std::set<Anope::string>::const_iterator it = dbs.begin(), it_end = dbs.end(); it != it_end; ++it)
- {
- const Anope::string &oldname = Anope::DataDir + "/" + *it;
- Anope::string newname = Anope::DataDir + "/backups/" + *it + "-" + stringify(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday);
-
- /* Backup already exists or no database to backup */
- if (Anope::IsFile(newname) || !Anope::IsFile(oldname))
- continue;
-
- Log(LOG_DEBUG) << "db_flatfile: Attempting to rename " << *it << " to " << newname;
- if (rename(oldname.c_str(), newname.c_str()))
- {
- Anope::string err = Anope::LastError();
- Log(this) << "Unable to back up database " << *it << " (" << err << ")!";
-
- if (!Config->GetModule(this)->Get<bool>("nobackupokay"))
- {
- Anope::Quitting = true;
- Anope::QuitReason = "Unable to back up database " + *it + " (" + err + ")";
- }
-
- continue;
- }
-
- backups[*it].push_back(newname);
-
- unsigned keepbackups = Config->GetModule(this)->Get<unsigned>("keepbackups");
- if (keepbackups > 0 && backups[*it].size() > keepbackups)
- {
- unlink(backups[*it].front().c_str());
- backups[*it].pop_front();
- }
- }
- }
- }
-
- public:
- DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), last_day(0), loaded(false), child_pid(-1)
- {
-
- }
-
-#ifndef _WIN32
- void OnRestart() anope_override
- {
- OnShutdown();
- }
-
- void OnShutdown() anope_override
- {
- if (child_pid > -1)
- {
- Log(this) << "Waiting for child to exit...";
-
- int status;
- waitpid(child_pid, &status, 0);
-
- Log(this) << "Done";
- }
- }
-#endif
-
- void OnNotify() anope_override
- {
- char buf[512];
- int i = this->Read(buf, sizeof(buf) - 1);
- if (i <= 0)
- return;
- buf[i] = 0;
-
- child_pid = -1;
-
- if (!*buf)
- {
- Log(this) << "Finished saving databases";
- return;
- }
-
- Log(this) << "Error saving databases: " << buf;
-
- if (!Config->GetModule(this)->Get<bool>("nobackupokay"))
- Anope::Quitting = true;
- }
-
- EventReturn OnLoadDatabase() anope_override
- {
- const std::vector<Anope::string> &type_order = Serialize::Type::GetTypeOrder();
- std::set<Anope::string> tried_dbs;
-
- const Anope::string &db_name = Anope::DataDir + "/" + 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;
- ld.fs = &fd;
-
- for (unsigned i = 0; i < type_order.size(); ++i)
- {
- Serialize::Type *stype = Serialize::Type::Find(type_order[i]);
- if (!stype || stype->GetOwner())
- continue;
-
- std::vector<std::streampos> &pos = positions[stype->GetName()];
-
- for (unsigned j = 0; j < pos.size(); ++j)
- {
- fd.clear();
- fd.seekg(pos[j]);
-
- Serializable *obj = stype->Unserialize(NULL, ld);
- if (obj != NULL)
- obj->id = ld.id;
- ld.Reset();
- }
- }
-
- fd.close();
-
- loaded = true;
- return EVENT_STOP;
- }
-
-
- void OnSaveDatabase() anope_override
- {
- if (child_pid > -1)
- {
- Log(this) << "Database save is already in progress!";
- return;
- }
-
- BackupDatabase();
-
- int i = -1;
-#ifndef _WIN32
- if (!Anope::Quitting && Config->GetModule(this)->Get<bool>("fork"))
- {
- i = fork();
- if (i > 0)
- {
- child_pid = i;
- return;
- }
- else if (i < 0)
- Log(this) << "Unable to fork for database save";
- }
-#endif
-
- try
- {
- std::map<Module *, std::fstream *> databases;
-
- /* First open the databases of all of the registered types. This way, if we have a type with 0 objects, that database will be properly cleared */
- for (std::map<Anope::string, Serialize::Type *>::const_iterator it = Serialize::Type::GetTypes().begin(), it_end = Serialize::Type::GetTypes().end(); it != it_end; ++it)
- {
- Serialize::Type *s_type = it->second;
-
- if (databases[s_type->GetOwner()])
- continue;
-
- Anope::string db_name;
- if (s_type->GetOwner())
- db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
- else
- db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
-
- if (Anope::IsFile(db_name))
- rename(db_name.c_str(), (db_name + ".tmp").c_str());
-
- std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream(db_name.c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
-
- if (!fs->is_open())
- Log(this) << "Unable to open " << db_name << " for writing";
- }
-
- SaveData data;
- const std::list<Serializable *> &items = Serializable::GetItems();
- for (std::list<Serializable *>::const_iterator it = items.begin(), it_end = items.end(); it != it_end; ++it)
- {
- Serializable *base = *it;
- Serialize::Type *s_type = base->GetSerializableType();
-
- data.fs = databases[s_type->GetOwner()];
- if (!data.fs || !data.fs->is_open())
- continue;
-
- *data.fs << "OBJECT " << s_type->GetName();
- if (base->id)
- *data.fs << "\nID " << base->id;
- base->Serialize(data);
- *data.fs << "\nEND\n";
- }
-
- for (std::map<Module *, std::fstream *>::iterator it = databases.begin(), it_end = databases.end(); it != it_end; ++it)
- {
- std::fstream *f = it->second;
- const Anope::string &db_name = Anope::DataDir + "/" + (it->first ? (it->first->name + ".db") : Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
-
- if (!f->is_open() || !f->good())
- {
- this->Write("Unable to write database " + db_name);
-
- f->close();
-
- if (Anope::IsFile((db_name + ".tmp").c_str()))
- rename((db_name + ".tmp").c_str(), db_name.c_str());
- }
- else
- {
- f->close();
- unlink((db_name + ".tmp").c_str());
- }
-
- delete f;
- }
- }
- catch (...)
- {
- if (i)
- throw;
- }
-
- if (!i)
- {
- this->Notify();
- exit(0);
- }
- }
-
- /* Load just one type. Done if a module is reloaded during runtime */
- void OnSerializeTypeCreate(Serialize::Type *stype) anope_override
- {
- if (!loaded)
- return;
-
- Anope::string db_name;
- if (stype->GetOwner())
- db_name = Anope::DataDir + "/module_" + stype->GetOwner()->name + ".db";
- else
- db_name = Anope::DataDir + "/" + 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;
- ld.fs = &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)
-
-
diff --git a/modules/database/db_redis.cpp b/modules/database/db_redis.cpp
deleted file mode 100644
index db12a2c5f..000000000
--- a/modules/database/db_redis.cpp
+++ /dev/null
@@ -1,644 +0,0 @@
-/*
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "module.h"
-#include "modules/redis.h"
-
-using namespace Redis;
-
-class DatabaseRedis;
-static DatabaseRedis *me;
-
-class Data : public Serialize::Data
-{
- public:
- std::map<Anope::string, std::stringstream *> data;
-
- ~Data()
- {
- for (std::map<Anope::string, std::stringstream *>::iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
- delete it->second;
- }
-
- std::iostream& operator[](const Anope::string &key) anope_override
- {
- std::stringstream* &stream = data[key];
- if (!stream)
- stream = new std::stringstream();
- return *stream;
- }
-
- std::set<Anope::string> KeySet() const anope_override
- {
- std::set<Anope::string> keys;
- for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- keys.insert(it->first);
- return keys;
- }
-
- size_t Hash() const anope_override
- {
- size_t hash = 0;
- for (std::map<Anope::string, std::stringstream *>::const_iterator it = this->data.begin(), it_end = this->data.end(); it != it_end; ++it)
- if (!it->second->str().empty())
- hash ^= Anope::hash_cs()(it->second->str());
- return hash;
- }
-};
-
-class TypeLoader : public Interface
-{
- Anope::string type;
- public:
- TypeLoader(Module *creator, const Anope::string &t) : Interface(creator), type(t) { }
-
- void OnResult(const Reply &r) anope_override;
-};
-
-class ObjectLoader : public Interface
-{
- Anope::string type;
- int64_t id;
-
- public:
- ObjectLoader(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
-
- void OnResult(const Reply &r) anope_override;
-};
-
-class IDInterface : public Interface
-{
- Reference<Serializable> o;
- public:
- IDInterface(Module *creator, Serializable *obj) : Interface(creator), o(obj) { }
-
- void OnResult(const Reply &r) anope_override;
-};
-
-class Deleter : public Interface
-{
- Anope::string type;
- int64_t id;
- public:
- Deleter(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
-
- void OnResult(const Reply &r) anope_override;
-};
-
-class Updater : public Interface
-{
- Anope::string type;
- int64_t id;
- public:
- Updater(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
-
- void OnResult(const Reply &r) anope_override;
-};
-
-class ModifiedObject : public Interface
-{
- Anope::string type;
- int64_t id;
- public:
- ModifiedObject(Module *creator, const Anope::string &t, int64_t i) : Interface(creator), type(t), id(i) { }
-
- void OnResult(const Reply &r) anope_override;
-};
-
-class SubscriptionListener : public Interface
-{
- public:
- SubscriptionListener(Module *creator) : Interface(creator) { }
-
- void OnResult(const Reply &r) anope_override;
-};
-
-class DatabaseRedis : public Module, public Pipe
-{
- SubscriptionListener sl;
- std::set<Serializable *> updated_items;
-
- public:
- ServiceReference<Provider> redis;
-
- DatabaseRedis(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), sl(this)
- {
- me = this;
-
- }
-
- /* Insert or update an object */
- void InsertObject(Serializable *obj)
- {
- Serialize::Type *t = obj->GetSerializableType();
-
- /* If there is no id yet for this object, get one */
- if (!obj->id)
- redis->SendCommand(new IDInterface(this, obj), "INCR id:" + t->GetName());
- else
- {
- Data data;
- obj->Serialize(data);
-
- if (obj->IsCached(data))
- return;
-
- obj->UpdateCache(data);
-
- std::vector<Anope::string> args;
- args.push_back("HGETALL");
- args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
-
- /* Get object attrs to clear before updating */
- redis->SendCommand(new Updater(this, t->GetName(), obj->id), args);
- }
- }
-
- void OnNotify() anope_override
- {
- for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it)
- {
- Serializable *s = *it;
-
- this->InsertObject(s);
- }
-
- this->updated_items.clear();
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- Configuration::Block *block = conf->GetModule(this);
- this->redis = ServiceReference<Provider>("Redis::Provider", block->Get<const Anope::string>("engine", "redis/main"));
- }
-
- EventReturn OnLoadDatabase() anope_override
- {
- const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
- for (unsigned i = 0; i < type_order.size(); ++i)
- {
- Serialize::Type *sb = Serialize::Type::Find(type_order[i]);
- this->OnSerializeTypeCreate(sb);
- }
-
- while (redis->BlockAndProcess());
-
- redis->Subscribe(&this->sl, "__keyspace@*__:hash:*");
-
- return EVENT_STOP;
- }
-
- void OnSerializeTypeCreate(Serialize::Type *sb) anope_override
- {
- if (!redis)
- return;
-
- std::vector<Anope::string> args;
- args.push_back("SMEMBERS");
- args.push_back("ids:" + sb->GetName());
-
- redis->SendCommand(new TypeLoader(this, sb->GetName()), args);
- }
-
- void OnSerializableConstruct(Serializable *obj) anope_override
- {
- this->updated_items.insert(obj);
- this->Notify();
- }
-
- void OnSerializableDestruct(Serializable *obj) anope_override
- {
- Serialize::Type *t = obj->GetSerializableType();
-
- std::vector<Anope::string> args;
- args.push_back("HGETALL");
- args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
-
- /* Get all of the attributes for this object */
- redis->SendCommand(new Deleter(this, t->GetName(), obj->id), args);
-
- this->updated_items.erase(obj);
- t->objects.erase(obj->id);
- this->Notify();
- }
-
- void OnSerializableUpdate(Serializable *obj) anope_override
- {
- this->updated_items.insert(obj);
- this->Notify();
- }
-};
-
-void TypeLoader::OnResult(const Reply &r)
-{
- if (r.type != Reply::MULTI_BULK || !me->redis)
- {
- delete this;
- return;
- }
-
- for (unsigned i = 0; i < r.multi_bulk.size(); ++i)
- {
- const Reply *reply = r.multi_bulk[i];
-
- if (reply->type != Reply::BULK)
- continue;
-
- int64_t id;
- try
- {
- id = convertTo<int64_t>(reply->bulk);
- }
- catch (const ConvertException &)
- {
- continue;
- }
-
- std::vector<Anope::string> args;
- args.push_back("HGETALL");
- args.push_back("hash:" + this->type + ":" + stringify(id));
-
- me->redis->SendCommand(new ObjectLoader(me, this->type, id), args);
- }
-
- delete this;
-}
-
-void ObjectLoader::OnResult(const Reply &r)
-{
- Serialize::Type *st = Serialize::Type::Find(this->type);
-
- if (r.type != Reply::MULTI_BULK || r.multi_bulk.empty() || !me->redis || !st)
- {
- delete this;
- return;
- }
-
- Data data;
-
- for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
- {
- const Reply *key = r.multi_bulk[i],
- *value = r.multi_bulk[i + 1];
-
- data[key->bulk] << value->bulk;
- }
-
- Serializable* &obj = st->objects[this->id];
- obj = st->Unserialize(obj, data);
- if (obj)
- {
- obj->id = this->id;
- obj->UpdateCache(data);
- }
-
- delete this;
-}
-
-void IDInterface::OnResult(const Reply &r)
-{
- if (!o || r.type != Reply::INT || !r.i)
- {
- delete this;
- return;
- }
-
- Serializable* &obj = o->GetSerializableType()->objects[r.i];
- if (obj)
- /* This shouldn't be possible */
- obj->id = 0;
-
- o->id = r.i;
- obj = o;
-
- /* Now that we have the id, insert this object for real */
- anope_dynamic_static_cast<DatabaseRedis *>(this->owner)->InsertObject(o);
-
- delete this;
-}
-
-void Deleter::OnResult(const Reply &r)
-{
- if (r.type != Reply::MULTI_BULK || !me->redis || r.multi_bulk.empty())
- {
- delete this;
- return;
- }
-
- /* Transaction start */
- me->redis->StartTransaction();
-
- std::vector<Anope::string> args;
- args.push_back("DEL");
- args.push_back("hash:" + this->type + ":" + stringify(this->id));
-
- /* Delete hash object */
- me->redis->SendCommand(NULL, args);
-
- args.clear();
- args.push_back("SREM");
- args.push_back("ids:" + this->type);
- args.push_back(stringify(this->id));
-
- /* Delete id from ids set */
- me->redis->SendCommand(NULL, args);
-
- for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
- {
- const Reply *key = r.multi_bulk[i],
- *value = r.multi_bulk[i + 1];
-
- args.clear();
- args.push_back("SREM");
- args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
- args.push_back(stringify(this->id));
-
- /* Delete value -> object id */
- me->redis->SendCommand(NULL, args);
- }
-
- /* Transaction end */
- me->redis->CommitTransaction();
-
- delete this;
-}
-
-void Updater::OnResult(const Reply &r)
-{
- Serialize::Type *st = Serialize::Type::Find(this->type);
-
- if (!st)
- {
- delete this;
- return;
- }
-
- Serializable *obj = st->objects[this->id];
- if (!obj)
- {
- delete this;
- return;
- }
-
- Data data;
- obj->Serialize(data);
-
- /* Transaction start */
- me->redis->StartTransaction();
-
- for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
- {
- const Reply *key = r.multi_bulk[i],
- *value = r.multi_bulk[i + 1];
-
- std::vector<Anope::string> args;
- args.push_back("SREM");
- args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
- args.push_back(stringify(this->id));
-
- /* Delete value -> object id */
- me->redis->SendCommand(NULL, args);
- }
-
- /* Add object id to id set for this type */
- std::vector<Anope::string> args;
- args.push_back("SADD");
- args.push_back("ids:" + this->type);
- args.push_back(stringify(obj->id));
- me->redis->SendCommand(NULL, args);
-
- args.clear();
- args.push_back("HMSET");
- args.push_back("hash:" + this->type + ":" + stringify(obj->id));
-
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- {
- const Anope::string &key = it->first;
- std::stringstream *value = it->second;
-
- args.push_back(key);
- args.push_back(value->str());
-
- std::vector<Anope::string> args2;
-
- args2.push_back("SADD");
- args2.push_back("value:" + this->type + ":" + key + ":" + value->str());
- args2.push_back(stringify(obj->id));
-
- /* Add to value -> object id set */
- me->redis->SendCommand(NULL, args2);
- }
-
- ++obj->redis_ignore;
-
- /* Add object */
- me->redis->SendCommand(NULL, args);
-
- /* Transaction end */
- me->redis->CommitTransaction();
-
- delete this;
-}
-
-void SubscriptionListener::OnResult(const Reply &r)
-{
- /*
- * [May 15 13:59:35.645839 2013] Debug: pmessage
- * [May 15 13:59:35.645866 2013] Debug: __keyspace@*__:anope:hash:*
- * [May 15 13:59:35.645880 2013] Debug: __keyspace@0__:anope:hash:type:id
- * [May 15 13:59:35.645893 2013] Debug: hset
- */
- if (r.multi_bulk.size() != 4)
- return;
-
- size_t sz = r.multi_bulk[2]->bulk.find(':');
- if (sz == Anope::string::npos)
- return;
-
- const Anope::string &key = r.multi_bulk[2]->bulk.substr(sz + 1),
- &op = r.multi_bulk[3]->bulk;
-
- sz = key.rfind(':');
- if (sz == Anope::string::npos)
- return;
-
- const Anope::string &id = key.substr(sz + 1);
-
- size_t sz2 = key.rfind(':', sz - 1);
- if (sz2 == Anope::string::npos)
- return;
- const Anope::string &type = key.substr(sz2 + 1, sz - sz2 - 1);
-
- Serialize::Type *s_type = Serialize::Type::Find(type);
-
- if (s_type == NULL)
- return;
-
- uint64_t obj_id;
- try
- {
- obj_id = convertTo<uint64_t>(id);
- }
- catch (const ConvertException &)
- {
- return;
- }
-
- if (op == "hset" || op == "hdel")
- {
- Serializable *s = s_type->objects[obj_id];
-
- if (s && s->redis_ignore)
- {
- --s->redis_ignore;
- Log(LOG_DEBUG) << "redis: notify: got modify for object id " << obj_id << " of type " << type << ", but I am ignoring it";
- }
- else
- {
- Log(LOG_DEBUG) << "redis: notify: got modify for object id " << obj_id << " of type " << type;
-
- std::vector<Anope::string> args;
- args.push_back("HGETALL");
- args.push_back("hash:" + type + ":" + id);
-
- me->redis->SendCommand(new ModifiedObject(me, type, obj_id), args);
- }
- }
- else if (op == "del")
- {
- Serializable* &s = s_type->objects[obj_id];
- if (s == NULL)
- return;
-
- Log(LOG_DEBUG) << "redis: notify: deleting object id " << obj_id << " of type " << type;
-
- Data data;
-
- s->Serialize(data);
-
- /* Transaction start */
- me->redis->StartTransaction();
-
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- {
- const Anope::string &k = it->first;
- std::stringstream *value = it->second;
-
- std::vector<Anope::string> args;
- args.push_back("SREM");
- args.push_back("value:" + type + ":" + k + ":" + value->str());
- args.push_back(id);
-
- /* Delete value -> object id */
- me->redis->SendCommand(NULL, args);
- }
-
- std::vector<Anope::string> args;
- args.push_back("SREM");
- args.push_back("ids:" + type);
- args.push_back(stringify(s->id));
-
- /* Delete object from id set */
- me->redis->SendCommand(NULL, args);
-
- /* Transaction end */
- me->redis->CommitTransaction();
-
- delete s;
- s = NULL;
- }
-}
-
-void ModifiedObject::OnResult(const Reply &r)
-{
- Serialize::Type *st = Serialize::Type::Find(this->type);
-
- if (!st)
- {
- delete this;
- return;
- }
-
- Serializable* &obj = st->objects[this->id];
-
- /* Transaction start */
- me->redis->StartTransaction();
-
- /* Erase old object values */
- if (obj)
- {
- Data data;
-
- obj->Serialize(data);
-
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- {
- const Anope::string &key = it->first;
- std::stringstream *value = it->second;
-
- std::vector<Anope::string> args;
- args.push_back("SREM");
- args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str());
- args.push_back(stringify(this->id));
-
- /* Delete value -> object id */
- me->redis->SendCommand(NULL, args);
- }
- }
-
- Data data;
-
- for (unsigned i = 0; i + 1 < r.multi_bulk.size(); i += 2)
- {
- const Reply *key = r.multi_bulk[i],
- *value = r.multi_bulk[i + 1];
-
- data[key->bulk] << value->bulk;
- }
-
- obj = st->Unserialize(obj, data);
- if (obj)
- {
- obj->id = this->id;
- obj->UpdateCache(data);
-
- /* Insert new object values */
- typedef std::map<Anope::string, std::stringstream *> items;
- for (items::iterator it = data.data.begin(), it_end = data.data.end(); it != it_end; ++it)
- {
- const Anope::string &key = it->first;
- std::stringstream *value = it->second;
-
- std::vector<Anope::string> args;
- args.push_back("SADD");
- args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str());
- args.push_back(stringify(obj->id));
-
- /* Add to value -> object id set */
- me->redis->SendCommand(NULL, args);
- }
-
- std::vector<Anope::string> args;
- args.push_back("SADD");
- args.push_back("ids:" + st->GetName());
- args.push_back(stringify(obj->id));
-
- /* Add to type -> id set */
- me->redis->SendCommand(NULL, args);
- }
-
- /* Transaction end */
- me->redis->CommitTransaction();
-
- delete this;
-}
-
-MODULE_INIT(DatabaseRedis)
diff --git a/modules/database/db_sql.cpp b/modules/database/db_sql.cpp
deleted file mode 100644
index 15501bc5f..000000000
--- a/modules/database/db_sql.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- *
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-#include "modules/sql.h"
-
-using namespace SQL;
-
-class SQLSQLInterface : public Interface
-{
- public:
- SQLSQLInterface(Module *o) : Interface(o) { }
-
- void OnResult(const Result &r) anope_override
- {
- Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query;
- }
-
- void OnError(const Result &r) anope_override
- {
- if (!r.GetQuery().query.empty())
- Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError();
- else
- Log(LOG_DEBUG) << "Error executing query: " << r.GetError();
- }
-};
-
-class ResultSQLSQLInterface : public SQLSQLInterface
-{
- Reference<Serializable> obj;
-
-public:
- ResultSQLSQLInterface(Module *o, Serializable *ob) : SQLSQLInterface(o), obj(ob) { }
-
- void OnResult(const Result &r) anope_override
- {
- SQLSQLInterface::OnResult(r);
- if (r.GetID() > 0 && this->obj)
- this->obj->id = r.GetID();
- delete this;
- }
-
- void OnError(const Result &r) anope_override
- {
- SQLSQLInterface::OnError(r);
- delete this;
- }
-};
-
-class DBSQL : public Module, public Pipe
-{
- ServiceReference<Provider> sql;
- SQLSQLInterface sqlinterface;
- Anope::string prefix;
- bool import;
-
- std::set<Serializable *> updated_items;
- bool shutting_down;
- bool loading_databases;
- bool loaded;
- bool imported;
-
- void RunBackground(const Query &q, Interface *iface = NULL)
- {
- if (!this->sql)
- {
- static time_t last_warn = 0;
- if (last_warn + 300 < Anope::CurTime)
- {
- last_warn = Anope::CurTime;
- Log(this) << "db_sql: Unable to execute query, is SQL configured correctly?";
- }
- }
- else if (!Anope::Quitting)
- {
- if (iface == NULL)
- iface = &this->sqlinterface;
- this->sql->Run(iface, q);
- }
- else
- this->sql->RunQuery(q);
- }
-
- public:
- DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), sql("", ""), sqlinterface(this), shutting_down(false), loading_databases(false), loaded(false), imported(false)
- {
-
-
- if (ModuleManager::FindModule("db_sql_live") != NULL)
- throw ModuleException("db_sql can not be loaded after db_sql_live");
- }
-
- void OnNotify() anope_override
- {
- for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it)
- {
- Serializable *obj = *it;
-
- if (this->sql)
- {
- Data data;
- obj->Serialize(data);
-
- if (obj->IsCached(data))
- continue;
-
- obj->UpdateCache(data);
-
- /* If we didn't load these objects and we don't want to import just update the cache and continue */
- if (!this->loaded && !this->imported && !this->import)
- continue;
-
- Serialize::Type *s_type = obj->GetSerializableType();
- if (!s_type)
- continue;
-
- std::vector<Query> create = this->sql->CreateTable(this->prefix + s_type->GetName(), data);
- for (unsigned i = 0; i < create.size(); ++i)
- this->RunBackground(create[i]);
-
- Query insert = this->sql->BuildInsert(this->prefix + s_type->GetName(), obj->id, data);
- if (this->imported)
- this->RunBackground(insert, new ResultSQLSQLInterface(this, obj));
- else
- {
- /* We are importing objects from another database module, so don't do asynchronous
- * queries in case the core has to shut down, it will cut short the import
- */
- Result r = this->sql->RunQuery(insert);
- if (r.GetID() > 0)
- obj->id = r.GetID();
- }
- }
- }
-
- this->updated_items.clear();
- this->imported = true;
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- Configuration::Block *block = conf->GetModule(this);
- this->sql = ServiceReference<Provider>("SQL::Provider", block->Get<const Anope::string>("engine"));
- this->prefix = block->Get<const Anope::string>("prefix", "anope_db_");
- this->import = block->Get<bool>("import");
- }
-
- void OnShutdown() anope_override
- {
- this->shutting_down = true;
- this->OnNotify();
- }
-
- void OnRestart() anope_override
- {
- this->OnShutdown();
- }
-
- EventReturn OnLoadDatabase() anope_override
- {
- if (!this->sql)
- {
- Log(this) << "Unable to load databases, is SQL configured correctly?";
- return EVENT_CONTINUE;
- }
-
- this->loading_databases = true;
-
- const std::vector<Anope::string> type_order = Serialize::Type::GetTypeOrder();
- for (unsigned i = 0; i < type_order.size(); ++i)
- {
- Serialize::Type *sb = Serialize::Type::Find(type_order[i]);
- this->OnSerializeTypeCreate(sb);
- }
-
- this->loading_databases = false;
- this->loaded = true;
-
- return EVENT_STOP;
- }
-
- void OnSerializableConstruct(Serializable *obj) anope_override
- {
- if (this->shutting_down || this->loading_databases)
- return;
- obj->UpdateTS();
- this->updated_items.insert(obj);
- this->Notify();
- }
-
- void OnSerializableDestruct(Serializable *obj) anope_override
- {
- if (this->shutting_down)
- return;
- Serialize::Type *s_type = obj->GetSerializableType();
- if (s_type && obj->id > 0)
- this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id));
- this->updated_items.erase(obj);
- }
-
- void OnSerializableUpdate(Serializable *obj) anope_override
- {
- if (this->shutting_down || obj->IsTSCached())
- return;
- obj->UpdateTS();
- this->updated_items.insert(obj);
- this->Notify();
- }
-
- void OnSerializeTypeCreate(Serialize::Type *sb) anope_override
- {
- if (!this->loading_databases && !this->loaded)
- return;
-
- Query query("SELECT * FROM `" + this->prefix + sb->GetName() + "`");
- Result res = this->sql->RunQuery(query);
-
- for (int j = 0; j < res.Rows(); ++j)
- {
- Data data;
-
- const std::map<Anope::string, Anope::string> &row = res.Row(j);
- for (std::map<Anope::string, Anope::string>::const_iterator rit = row.begin(), rit_end = row.end(); rit != rit_end; ++rit)
- data[rit->first] << rit->second;
-
- Serializable *obj = sb->Unserialize(NULL, data);
- try
- {
- if (obj)
- obj->id = convertTo<unsigned int>(res.Get(j, "id"));
- }
- catch (const ConvertException &)
- {
- Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName();
- }
-
- if (obj)
- {
- /* The Unserialize operation is destructive so rebuild the data for UpdateCache.
- * Also the old data may contain columns that we don't use, so we reserialize the
- * object to know for sure our cache is consistent
- */
-
- Data data2;
- obj->Serialize(data2);
- obj->UpdateCache(data2); /* We know this is the most up to date copy */
- }
- }
- }
-};
-
-MODULE_INIT(DBSQL)
-
diff --git a/modules/database/db_sql_live.cpp b/modules/database/db_sql_live.cpp
deleted file mode 100644
index 7dfde3d02..000000000
--- a/modules/database/db_sql_live.cpp
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- *
- * (C) 2012-2016 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- */
-
-#include "module.h"
-#include "modules/sql.h"
-
-using namespace SQL;
-
-class DBMySQL : public Module, public Pipe
-{
- private:
- Anope::string prefix;
- ServiceReference<Provider> SQL;
- time_t lastwarn;
- bool ro;
- bool init;
- std::set<Serializable *> updated_items;
-
- bool CheckSQL()
- {
- if (SQL)
- {
- if (Anope::ReadOnly && this->ro)
- {
- Anope::ReadOnly = this->ro = false;
- Log() << "Found SQL again, going out of readonly mode...";
- }
-
- return true;
- }
- else
- {
- if (Anope::CurTime - Config->GetBlock("options")->Get<time_t>("updatetimeout", "5m") > lastwarn)
- {
- Log() << "Unable to locate SQL reference, going to readonly...";
- Anope::ReadOnly = this->ro = true;
- this->lastwarn = Anope::CurTime;
- }
-
- return false;
- }
- }
-
- bool CheckInit()
- {
- return init && SQL;
- }
-
- void RunQuery(const Query &query)
- {
- /* Can this be threaded? */
- this->RunQueryResult(query);
- }
-
- Result RunQueryResult(const Query &query)
- {
- if (this->CheckSQL())
- {
- Result res = SQL->RunQuery(query);
- if (!res.GetError().empty())
- Log(LOG_DEBUG) << "SQL-live got error " << res.GetError() << " for " + res.finished_query;
- else
- Log(LOG_DEBUG) << "SQL-live got " << res.Rows() << " rows for " << res.finished_query;
- return res;
- }
- throw SQL::Exception("No SQL!");
- }
-
- public:
- DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR), SQL("", "")
- {
- this->lastwarn = 0;
- this->ro = false;
- this->init = false;
-
-
- if (ModuleManager::FindFirstOf(DATABASE) != this)
- throw ModuleException("If db_sql_live is loaded it must be the first database module loaded.");
- }
-
- void OnNotify() anope_override
- {
- if (!this->CheckInit())
- return;
-
- for (std::set<Serializable *>::iterator it = this->updated_items.begin(), it_end = this->updated_items.end(); it != it_end; ++it)
- {
- Serializable *obj = *it;
-
- if (obj && this->SQL)
- {
- Data data;
- obj->Serialize(data);
-
- if (obj->IsCached(data))
- continue;
-
- obj->UpdateCache(data);
-
- Serialize::Type *s_type = obj->GetSerializableType();
- if (!s_type)
- continue;
-
- std::vector<Query> create = this->SQL->CreateTable(this->prefix + s_type->GetName(), data);
- for (unsigned i = 0; i < create.size(); ++i)
- this->RunQueryResult(create[i]);
-
- Result res = this->RunQueryResult(this->SQL->BuildInsert(this->prefix + s_type->GetName(), obj->id, data));
- if (res.GetID() && obj->id != res.GetID())
- {
- /* In this case obj is new, so place it into the object map */
- obj->id = res.GetID();
- s_type->objects[obj->id] = obj;
- }
- }
- }
-
- this->updated_items.clear();
- }
-
- EventReturn OnLoadDatabase() anope_override
- {
- init = true;
- return EVENT_STOP;
- }
-
- void OnShutdown() anope_override
- {
- init = false;
- }
-
- void OnRestart() anope_override
- {
- init = false;
- }
-
- void OnReload(Configuration::Conf *conf) anope_override
- {
- Configuration::Block *block = conf->GetModule(this);
- this->SQL = ServiceReference<Provider>("SQL::Provider", block->Get<const Anope::string>("engine"));
- this->prefix = block->Get<const Anope::string>("prefix", "anope_db_");
- }
-
- void OnSerializableConstruct(Serializable *obj) anope_override
- {
- if (!this->CheckInit())
- return;
- obj->UpdateTS();
- this->updated_items.insert(obj);
- this->Notify();
- }
-
- void OnSerializableDestruct(Serializable *obj) anope_override
- {
- if (!this->CheckInit())
- return;
- Serialize::Type *s_type = obj->GetSerializableType();
- if (s_type)
- {
- if (obj->id > 0)
- this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id));
- s_type->objects.erase(obj->id);
- }
- this->updated_items.erase(obj);
- }
-
- void OnSerializeCheck(Serialize::Type *obj) anope_override
- {
- if (!this->CheckInit() || obj->GetTimestamp() == Anope::CurTime)
- return;
-
- Query query("SELECT * FROM `" + this->prefix + obj->GetName() + "` WHERE (`timestamp` >= " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " OR `timestamp` IS NULL)");
-
- obj->UpdateTimestamp();
-
- Result res = this->RunQueryResult(query);
-
- bool clear_null = false;
- for (int i = 0; i < res.Rows(); ++i)
- {
- const std::map<Anope::string, Anope::string> &row = res.Row(i);
-
- unsigned int id;
- try
- {
- id = convertTo<unsigned int>(res.Get(i, "id"));
- }
- catch (const ConvertException &)
- {
- Log(LOG_DEBUG) << "Unable to convert id from " << obj->GetName();
- continue;
- }
-
- if (res.Get(i, "timestamp").empty())
- {
- clear_null = true;
- std::map<uint64_t, Serializable *>::iterator it = obj->objects.find(id);
- if (it != obj->objects.end())
- delete it->second; // This also removes this object from the map
- }
- else
- {
- Data data;
-
- for (std::map<Anope::string, Anope::string>::const_iterator it = row.begin(), it_end = row.end(); it != it_end; ++it)
- data[it->first] << it->second;
-
- Serializable *s = NULL;
- std::map<uint64_t, Serializable *>::iterator it = obj->objects.find(id);
- if (it != obj->objects.end())
- s = it->second;
-
- Serializable *new_s = obj->Unserialize(s, data);
- if (new_s)
- {
- // If s == new_s then s->id == new_s->id
- if (s != new_s)
- {
- new_s->id = id;
- obj->objects[id] = new_s;
-
- /* The Unserialize operation is destructive so rebuild the data for UpdateCache.
- * Also the old data may contain columns that we don't use, so we reserialize the
- * object to know for sure our cache is consistent
- */
-
- Data data2;
- new_s->Serialize(data2);
- new_s->UpdateCache(data2); /* We know this is the most up to date copy */
- }
- }
- else
- {
- if (!s)
- this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + stringify(id));
- else
- delete s;
- }
- }
- }
-
- if (clear_null)
- {
- query = "DELETE FROM `" + this->prefix + obj->GetName() + "` WHERE `timestamp` IS NULL";
- this->RunQuery(query);
- }
- }
-
- void OnSerializableUpdate(Serializable *obj) anope_override
- {
- if (!this->CheckInit() || obj->IsTSCached())
- return;
- obj->UpdateTS();
- this->updated_items.insert(obj);
- this->Notify();
- }
-};
-
-MODULE_INIT(DBMySQL)
-
diff --git a/modules/database/flatfile.cpp b/modules/database/flatfile.cpp
new file mode 100644
index 000000000..ec6911ce2
--- /dev/null
+++ b/modules/database/flatfile.cpp
@@ -0,0 +1,807 @@
+/*
+ * Anope IRC Services
+ *
+ * Copyright (C) 2011-2016 Anope Team <team@anope.org>
+ *
+ * This file is part of Anope. Anope 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 see <http://www.gnu.org/licenses/>.
+ */
+
+#include "module.h"
+#include "modules/botserv/badwords.h"
+#include "modules/chanserv/access.h"
+#include "modules/chanserv/entrymsg.h"
+#include "modules/chanserv/log.h"
+#include "modules/chanserv/set_misc.h"
+#include "modules/chanserv/suspend.h"
+#include "modules/nickserv/access.h"
+#include "modules/nickserv/ajoin.h"
+#include "modules/nickserv/cert.h"
+#include "modules/nickserv/set_misc.h"
+#include "modules/nickserv/suspend.h"
+#include "modules/operserv/forbid.h"
+#include "modules/operserv/news.h"
+#include "modules/operserv/info.h"
+
+class DBFlatFile : public Module
+ , public EventHook<Event::LoadDatabase>
+{
+ void LoadAccount(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ NickServ::Account *account = Serialize::New<NickServ::Account *>();
+
+ if (account == nullptr)
+ return;
+
+ account->SetDisplay(data["display"]);
+ account->SetPassword(data["pass"]);
+ account->SetEmail(data["email"]);
+ account->SetLanguage(data["language"]);
+ account->SetOper(Oper::Find(account->GetDisplay()));
+
+ spacesepstream sep = data["access"];
+ for (Anope::string token; sep.GetToken(token);)
+ {
+ NickAccess *access = Serialize::New<NickAccess *>();
+ if (access != nullptr)
+ {
+ access->SetAccount(account);
+ access->SetMask(token);
+ }
+ }
+
+ MemoServ::MemoInfo *memos = account->GetMemos();
+ if (memos != nullptr)
+ {
+ try
+ {
+ int16_t memomax = convertTo<int16_t>(data["memomax"]);
+ memos->SetMemoMax(memomax);
+ }
+ catch (const ConvertException &) { }
+ }
+
+ sep = data["memoignore"];
+ for (Anope::string token; memos && sep.GetToken(token);)
+ {
+ MemoServ::Ignore *ign = Serialize::New<MemoServ::Ignore *>();
+ if (ign != nullptr)
+ {
+ ign->SetMemoInfo(memos);
+ ign->SetMask(token);
+ }
+ }
+
+ sep = data["cert"];
+ for (Anope::string token; sep.GetToken(token);)
+ {
+ NSCertEntry *e = Serialize::New<NSCertEntry *>();
+ if (e != nullptr)
+ {
+ e->SetAccount(account);
+ e->SetCert(token);
+ }
+ }
+
+ // last_modes
+ }
+
+ void LoadNick(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ NickServ::Account *acc = NickServ::FindAccount(data["nc"]);
+ if (acc == nullptr)
+ return;
+
+ NickServ::Nick *nick = Serialize::New<NickServ::Nick *>();
+
+ if (nick == nullptr)
+ return;
+
+ nick->SetNick(data["nick"]);
+ nick->SetLastQuit(data["last_quit"]);
+ nick->SetLastRealname(data["last_realname"]);
+ nick->SetLastUsermask(data["last_usermask"]);
+ nick->SetLastRealhost(data["last_realhost"]);
+ try
+ {
+ nick->SetTimeRegistered(convertTo<time_t>(data["time_registered"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ nick->SetLastSeen(convertTo<time_t>(data["last_seen"]));
+ }
+ catch (const ConvertException &) { }
+ nick->SetAccount(acc);
+
+ if (data["vhost_host"].empty() == false)
+ {
+ HostServ::VHost *vhost = Serialize::New<HostServ::VHost *>();
+ if (vhost != nullptr)
+ {
+ vhost->SetAccount(acc);
+ vhost->SetIdent(data["vhost_ident"]);
+ vhost->SetHost(data["vhost_host"]);
+ vhost->SetCreator(data["vhost_creator"]);
+ try
+ {
+ vhost->SetCreated(convertTo<time_t>(data["vhost_time"]));
+ }
+ catch (const ConvertException &) { }
+ }
+ }
+ }
+
+ void LoadNSSuspend(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ NickServ::Nick *nick = NickServ::FindNick(data["nick"]);
+
+ if (nick == nullptr)
+ return;
+
+ NSSuspendInfo *si = Serialize::New<NSSuspendInfo *>();
+ if (si == nullptr)
+ return;
+
+ si->SetAccount(nick->GetAccount());
+ si->SetBy(data["by"]);
+ si->SetReason(data["reason"]);
+ try
+ {
+ si->SetWhen(convertTo<time_t>(data["time"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ si->SetExpires(convertTo<time_t>(data["expires"]));
+ }
+ catch (const ConvertException &) { }
+ }
+
+ void LoadAJoin(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ NickServ::Nick *nick = NickServ::FindNick(data["nick"]);
+
+ if (nick == nullptr)
+ return;
+
+ AutoJoin *entry = Serialize::New<AutoJoin *>();
+ if (entry == nullptr)
+ return;
+
+ entry->SetAccount(nick->GetAccount());
+ entry->SetChannel(data["channel"]);
+ entry->SetKey(data["key"]);
+ }
+
+ void LoadNSMiscData(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ NickServ::Nick *nick = NickServ::FindNick(data["nc"]);
+
+ if (nick == nullptr)
+ return;
+
+ NSMiscData *d = Serialize::New<NSMiscData *>();
+ if (d == nullptr)
+ return;
+
+ d->SetAccount(nick->GetAccount());
+ d->SetName(data["name"]);
+ d->SetData(data["data"]);
+ }
+
+ void LoadChannel(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *chan = Serialize::New<ChanServ::Channel *>();
+
+ if (chan == nullptr)
+ return;
+
+ chan->SetName(data["name"]);
+ chan->SetFounder(NickServ::FindAccount(data["founder"]));
+ chan->SetSuccessor(NickServ::FindAccount(data["successor"]));
+ chan->SetDesc(data["description"]);
+ try
+ {
+ chan->SetTimeRegistered(convertTo<time_t>(data["time_registered"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ chan->SetLastUsed(convertTo<time_t>(data["last_used"]));
+ }
+ catch (const ConvertException &) { }
+ chan->SetLastTopic(data["last_topic"]);
+ chan->SetLastTopicSetter(data["last_topic_setter"]);
+ try
+ {
+ chan->SetLastTopicTime(convertTo<time_t>(data["last_topic_time"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ chan->SetBanType(convertTo<int16_t>(data["bantype"]));
+ }
+ catch (const ConvertException &) { }
+
+ spacesepstream sep = data["levels"];
+ for (Anope::string lname, lvalue; sep.GetToken(lname) && sep.GetToken(lvalue);)
+ {
+ try
+ {
+ chan->SetLevel(lname, convertTo<int16_t>(lvalue));
+ }
+ catch (const ConvertException &) { }
+ }
+
+ if (data["bi"].empty() == false)
+ {
+ ServiceBot *sb = ServiceBot::Find(data["bi"], true);
+ if (sb != nullptr)
+ chan->SetBI(sb->bi);
+ }
+
+ try
+ {
+ chan->SetBanExpire(convertTo<time_t>(data["banexpire"]));
+ }
+ catch (const ConvertException &) { }
+
+ MemoServ::MemoInfo *memos = chan->GetMemos();
+ if (memos != nullptr)
+ {
+ try
+ {
+ int16_t memomax = convertTo<int16_t>(data["memomax"]);
+ memos->SetMemoMax(memomax);
+ }
+ catch (const ConvertException &) { }
+ }
+
+ sep = data["memoignore"];
+ for (Anope::string token; memos && sep.GetToken(token);)
+ {
+ MemoServ::Ignore *ign = Serialize::New<MemoServ::Ignore *>();
+ if (ign != nullptr)
+ {
+ ign->SetMemoInfo(memos);
+ ign->SetMask(token);
+ }
+ }
+
+ // last modes
+ // kicker data
+
+ // exts
+ }
+
+ void LoadBot(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ if (ServiceBot::Find(data["nick"], true))
+ return;
+
+ BotInfo *bot = Serialize::New<BotInfo *>();
+ if (bot == nullptr)
+ return;
+
+ bot->SetNick(data["nick"]);
+ bot->SetUser(data["user"]);
+ bot->SetHost(data["host"]);
+ bot->SetRealName(data["realname"]);
+ try
+ {
+ bot->SetCreated(convertTo<time_t>(data["created"]));
+ }
+ catch (const ConvertException &) { }
+ bot->SetOperOnly(data["oper_only"] != "0");
+
+ ServiceBot *sb = new ServiceBot(bot->GetNick(), bot->GetUser(), bot->GetHost(), bot->GetRealName());
+
+ sb->bi = bot;
+ bot->bot = sb;
+ }
+
+ void LoadChanAccess(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ Anope::string mask = data["mask"];
+ if (mask.find('#') == 0)
+ return;
+
+ Anope::string provider = data["provider"];
+ ChanServ::ChanAccess *access;
+
+ if (provider == "access/access")
+ access = Serialize::New<AccessChanAccess *>();
+ else if (provider == "access/xop")
+ access = Serialize::New<XOPChanAccess *>();
+ else if (provider == "access/flags")
+ access = Serialize::New<FlagsChanAccess *>();
+ else
+ return;
+
+ if (access == nullptr)
+ return;
+
+ access->SetChannel(channel);
+ access->SetCreator(data["creator"]);
+ try
+ {
+ access->SetLastSeen(convertTo<time_t>(data["last_seen"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ access->SetCreated(convertTo<time_t>(data["created"]));
+ }
+ catch (const ConvertException &) { }
+ access->SetMask(mask);
+
+ NickServ::Nick *nick = NickServ::FindNick(mask);
+ if (nick != nullptr)
+ access->SetAccount(nick->GetAccount());
+
+ access->AccessUnserialize(data["data"]);
+ }
+
+ void LoadModeLock(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ ModeLock *ml = Serialize::New<ModeLock *>();
+ ml->SetChannel(channel);
+ ml->SetSet(data["set"] == "1");
+ ml->SetName(data["name"]);
+ ml->SetParam(data["param"]);
+ ml->SetSetter(data["setter"]);
+ try
+ {
+ ml->SetCreated(convertTo<time_t>(data["created"]));
+ }
+ catch (const ConvertException &) { }
+ }
+
+ void LoadAutoKick(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ NickServ::Nick *nick = nullptr;
+ if (data["nc"].empty() == false)
+ {
+ nick = NickServ::FindNick(data["nc"]);
+
+ if (nick == nullptr)
+ return;
+ }
+
+ time_t added = 0, lastused = 0;
+
+ try
+ {
+ added = convertTo<time_t>(data["addtime"]);
+ }
+ catch (const ConvertException &) { }
+
+ try
+ {
+ lastused = convertTo<time_t>(data["last_used"]);
+ }
+ catch (const ConvertException &) { }
+
+ if (nick != nullptr)
+ channel->AddAkick(data["creator"], nick->GetAccount(), data["reason"], added, lastused);
+ else
+ channel->AddAkick(data["creator"], data["mask"], data["reason"], added, lastused);
+ }
+
+ void LoadBadWord(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ BadWord *bw = Serialize::New<BadWord *>();
+ if (bw == nullptr)
+ return;
+
+ bw->SetChannel(channel);
+ bw->SetWord(data["word"]);
+ try
+ {
+ bw->SetType(static_cast<BadWordType>(convertTo<int>(data["type"])));
+ }
+ catch (const ConvertException &) { }
+ }
+
+ void LoadCSSuspend(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ CSSuspendInfo *si = Serialize::New<CSSuspendInfo *>();
+ if (si == nullptr)
+ return;
+
+ si->SetChannel(channel);
+ si->SetBy(data["by"]);
+ si->SetReason(data["reason"]);
+ try
+ {
+ si->SetWhen(convertTo<time_t>(data["time"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ si->SetExpires(convertTo<time_t>(data["expires"]));
+ }
+ catch (const ConvertException &) { }
+ }
+
+ void LoadEntrymsg(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ EntryMsg *msg = Serialize::New<EntryMsg *>();
+ if (msg == nullptr)
+ return;
+
+ msg->SetChannel(channel);
+ msg->SetCreator(data["creator"]);
+ msg->SetMessage(data["message"]);
+ }
+
+ void LoadLogSetting(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ LogSetting *log = Serialize::New<LogSetting *>();
+ if (log == nullptr)
+ return;
+
+ log->SetChannel(channel);
+ log->SetServiceName(data["service_name"]);
+ log->SetCommandService(data["command_service"]);
+ log->SetCommandName(data["command_name"]);
+ log->SetMethod(data["method"]);
+ log->SetExtra(data["extra"]);
+ try
+ {
+ log->SetCreated(convertTo<time_t>(data["created"]));
+ }
+ catch (const ConvertException &) { }
+ log->SetCreator(data["creator"]);
+ }
+
+ void LoadCSMiscData(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ChanServ::Channel *channel = ChanServ::Find(data["ci"]);
+ if (channel == nullptr)
+ return;
+
+ CSMiscData *d = Serialize::New<CSMiscData *>();
+ if (d == nullptr)
+ return;
+
+ d->SetChannel(channel);
+ d->SetName(data["name"]);
+ d->SetData(data["data"]);
+ }
+
+ void LoadForbid(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ ForbidData *d = Serialize::New<ForbidData *>();
+ if (d == nullptr)
+ return;
+
+ d->SetMask(data["mask"]);
+ d->SetCreator(data["creator"]);
+ d->SetReason(data["reason"]);
+ try
+ {
+ d->SetCreated(convertTo<time_t>(data["created"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ d->SetExpires(convertTo<time_t>(data["expires"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ d->SetType(static_cast<ForbidType>(convertTo<int>(data["type"])));
+ }
+ catch (const ConvertException &) { }
+ }
+
+ void LoadNews(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ NewsItem *ni = Serialize::New<NewsItem *>();
+ if (ni == nullptr)
+ return;
+
+ try
+ {
+ ni->SetNewsType(static_cast<NewsType>(convertTo<int>(data["type"])));
+ }
+ catch (const ConvertException &) { }
+ ni->SetText(data["text"]);
+ try
+ {
+ ni->SetTime(convertTo<time_t>(data["time"]));
+ }
+ catch (const ConvertException &) { }
+ ni->SetWho(data["who"]);
+ }
+
+ void LoadOperInfo(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ NickServ::Account *acc = NickServ::FindAccount(data["target"]);
+ ChanServ::Channel *chan = ChanServ::Find(data["target"]);
+
+ if (acc == nullptr && chan == nullptr)
+ return;
+
+ OperInfo *o = Serialize::New<OperInfo *>();
+ if (o == nullptr)
+ return;
+
+ o->SetAccount(acc);
+ o->SetChannel(chan);
+ o->SetInfo(data["info"]);
+ o->SetCreator(data["adder"]);
+ try
+ {
+ o->SetCreated(convertTo<time_t>(data["created"]));
+ }
+ catch (const ConvertException &) { }
+ }
+
+ void LoadXLine(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ XLine *x = Serialize::New<XLine *>();
+ if (x == nullptr)
+ return;
+
+ x->SetMask(data["mask"]);
+ x->SetBy(data["by"]);
+ try
+ {
+ x->SetExpires(convertTo<time_t>(data["expires"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ x->SetCreated(convertTo<time_t>(data["created"]));
+ }
+ catch (const ConvertException &) { }
+ x->SetReason(data["reason"]);
+ x->SetID(data["uid"]);
+ x->SetType(data["manager"]);
+ }
+
+ void LoadOper(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+#warning "oper needs account ref"
+#if 0
+ data["name"] << this->name;
+ data["type"] << this->ot->GetName();
+ Oper *o = Serialize::New<Oper *>();
+ o->SetName(na->GetAccount()->GetDisplay());
+ o->SetType(ot);
+ o->SetRequireOper(true);
+#endif
+ }
+
+ void LoadDNSZone(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+#if 0
+ DNSZone *z = Serialize::New<DNSZone *>();
+ z->SetName(data["name"]);
+
+ unsigned int count = 0;
+ while (data["server" + stringify(count)].empty() == false)
+ {
+ DNSZoneMembership *mem = Serialize::New<DNSZoneMembership *>();
+ mem->SetZone(z);
+ mem->SetServer(s);
+
+ ++count;
+ }
+// data["name"] << name;
+// unsigned count = 0;
+// for (std::set<Anope::string, ci::less>::iterator it = servers.begin(), it_end = servers.end(); it != it_end; ++it)
+// data["server" + stringify(count++)] << *it;
+#endif
+ }
+
+ void LoadDNSServer(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+#if 0
+ s = Serialize::New<DNSServer *>();
+ s->SetName(data["server_name"]);
+
+ data["server_name"] << server_name;
+ for (unsigned i = 0; i < ips.size(); ++i)
+ data["ip" + stringify(i)] << ips[i];
+ try
+ {
+ s->SetLimit(convertTo<unsigned>(data["limit"]));
+ }
+ catch (const ConvertException &) { }
+ try
+ {
+ s->SetPooled(data["pooled"] == "1");
+ }
+ catch (const ConvertException &) { }
+
+ unsigned int count = 0;
+ while (data["zone" + stringify(count)].empty() == false)
+ {
+ }
+// for (std::set<Anope::string, ci::less>::iterator it = zones.begin(), it_end = zones.end(); it != it_end; ++it)
+// data["zone" + stringify(count++)] << *it;
+#endif
+ }
+
+ void LoadMemo(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ MemoServ::MemoInfo *mi = nullptr;
+
+ Anope::string owner = data["owner"];
+
+ NickServ::Nick *nick = NickServ::FindNick(owner);
+ ChanServ::Channel *chan = ChanServ::Find(owner);
+ if (nick != nullptr)
+ mi = nick->GetAccount()->GetMemos();
+ else if (chan != nullptr)
+ mi = chan->GetMemos();
+
+ if (mi == nullptr)
+ return;
+
+ MemoServ::Memo *m = Serialize::New<MemoServ::Memo *>();
+ if (m == nullptr)
+ return;
+
+ m->SetMemoInfo(mi);
+ m->SetSender(data["sender"]);
+ try
+ {
+ m->SetTime(convertTo<time_t>(data["time"]));
+ }
+ catch (const ConvertException &) { }
+ m->SetText(data["text"]);
+ m->SetUnread(data["unread"] == "1");
+ // receipt
+ }
+
+ void LoadType(const Anope::string &type, std::map<Anope::string, Anope::string> &data)
+ {
+ if (type == "NickCore")
+ LoadAccount(type, data);
+ else if (type == "NickAlias")
+ LoadNick(type, data);
+ else if (type == "NSSuspend")
+ LoadNSSuspend(type, data);
+ else if (type == "AJoinEntry")
+ LoadAJoin(type, data);
+ else if (type == "NSMiscData")
+ LoadNSMiscData(type, data);
+
+ else if (type == "BotInfo")
+ LoadBot(type, data);
+ else if (type == "BadWord")
+ LoadBadWord(type, data);
+
+ else if (type == "ChannelInfo")
+ LoadChannel(type, data);
+ else if (type == "ChanAccess")
+ LoadChanAccess(type, data);
+ else if (type == "ModeLock")
+ LoadModeLock(type, data);
+ else if (type == "AutoKick")
+ LoadAutoKick(type, data);
+ else if (type == "CSSuspendInfo")
+ LoadCSSuspend(type, data);
+ else if (type == "EntryMsg")
+ LoadEntrymsg(type, data);
+ else if (type == "LogSetting")
+ LoadLogSetting(type, data);
+ else if (type == "CSMiscData")
+ LoadCSMiscData(type, data);
+
+ else if (type == "ForbidData")
+ LoadForbid(type, data);
+ else if (type == "NewsItem")
+ LoadNews(type, data);
+ else if (type == "OperInfo")
+ LoadOperInfo(type, data);
+ else if (type == "XLine")
+ LoadXLine(type, data);
+ else if (type == "Oper")
+ LoadOper(type, data);
+ else if (type == "DNSZone")
+ LoadDNSZone(type, data);
+ else if (type == "DNSServer")
+ LoadDNSServer(type, data);
+
+ else if (type == "Memo")
+ LoadMemo(type, data);
+ }
+
+ public:
+ DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
+ , EventHook<Event::LoadDatabase>(this)
+ {
+
+ }
+
+ EventReturn OnLoadDatabase() override
+ {
+ const Anope::string &db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<Anope::string>("database", "anope.db");
+
+ std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
+ if (!fd.is_open())
+ {
+ logger.Log("Unable to open {0} for reading!", db_name);
+ return EVENT_STOP;
+ }
+
+ Anope::string type;
+ std::map<Anope::string, Anope::string> data;
+ for (Anope::string buf; std::getline(fd, buf.str());)
+ {
+ if (buf.find("OBJECT ") == 0)
+ {
+ type = buf.substr(7);
+ }
+ else if (buf.find("DATA ") == 0)
+ {
+ size_t sp = buf.find(' ', 5); // Skip DATA
+ if (sp == Anope::string::npos)
+ continue;
+
+ Anope::string key = buf.substr(5, sp - 5), value = buf.substr(sp + 1);
+
+ data[key] = value;
+ }
+ else if (buf.find("END") == 0)
+ {
+ LoadType(type, data);
+
+ type.empty();
+ data.empty();
+ }
+ }
+
+ fd.close();
+
+ return EVENT_STOP;
+ }
+};
+
+MODULE_INIT(DBFlatFile)
+
+
diff --git a/modules/database/db_old.cpp b/modules/database/old.cpp
index 0c65fb95b..3a2b6ccb6 100644
--- a/modules/database/db_old.cpp
+++ b/modules/database/old.cpp
@@ -1,23 +1,36 @@
/*
+ * Anope IRC Services
*
- * (C) 2003-2016 Anope Team
- * Contact us at team@anope.org
+ * Copyright (C) 2003-2016 Anope Team <team@anope.org>
*
- * Please read COPYING and README for further details.
+ * This file is part of Anope. Anope 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.
*
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
+ * 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 see <http://www.gnu.org/licenses/>.
*/
+/* Dependencies: anope_chanserv.access */
+
#include "module.h"
-#include "modules/os_session.h"
-#include "modules/bs_kick.h"
-#include "modules/cs_mode.h"
-#include "modules/bs_badwords.h"
-#include "modules/os_news.h"
-#include "modules/suspend.h"
-#include "modules/os_forbid.h"
-#include "modules/cs_entrymsg.h"
+#include "modules/operserv/session.h"
+#include "modules/botserv/kick.h"
+#include "modules/chanserv/mode.h"
+#include "modules/botserv/badwords.h"
+#include "modules/operserv/news.h"
+#include "modules/operserv/forbid.h"
+#include "modules/chanserv/entrymsg.h"
+#include "modules/nickserv/suspend.h"
+#include "modules/chanserv/suspend.h"
+#include "modules/chanserv/access.h"
+#include "modules/nickserv/access.h"
#define READ(x) \
if (true) \
@@ -94,6 +107,18 @@ else \
#define OLD_NEWS_OPER 1
#define OLD_NEWS_RANDOM 2
+enum
+{
+ TTB_BOLDS,
+ TTB_COLORS,
+ TTB_REVERSES,
+ TTB_UNDERLINES,
+ TTB_BADWORDS,
+ TTB_CAPS,
+ TTB_FLOOD,
+ TTB_REPEAT,
+};
+
static struct mlock_info
{
char c;
@@ -143,21 +168,25 @@ enum
LANG_PL /* Polish */
};
-static void process_mlock(ChannelInfo *ci, uint32_t lock, bool status, uint32_t *limit, Anope::string *key)
+static void process_mlock(ChanServ::Channel *ci, uint32_t lock, bool status, uint32_t *limit, Anope::string *key)
{
- ModeLocks *ml = ci->Require<ModeLocks>("modelocks");
+ ServiceReference<ModeLocks> mlocks;
+
+ if (!mlocks)
+ return;
+
for (unsigned i = 0; i < (sizeof(mlock_infos) / sizeof(mlock_info)); ++i)
if (lock & mlock_infos[i].m)
{
ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock_infos[i].c);
- if (cm && ml)
+ if (cm)
{
if (limit && mlock_infos[i].c == 'l')
- ml->SetMLock(cm, status, stringify(*limit));
+ mlocks->SetMLock(ci, cm, status, stringify(*limit));
else if (key && mlock_infos[i].c == 'k')
- ml->SetMLock(cm, status, *key);
+ mlocks->SetMLock(ci, cm, status, *key);
else
- ml->SetMLock(cm, status);
+ mlocks->SetMLock(ci, cm, status);
}
}
}
@@ -326,7 +355,7 @@ static dbFILE *open_db_read(const char *service, const char *filename, int versi
fp = fopen(f->filename, "rb");
if (!fp)
{
- Log() << "Can't read " << service << " database " << f->filename;
+ Anope::Logger.Log("Can't read {0} database {1}", service, f->filename);
delete f;
return NULL;
}
@@ -334,13 +363,13 @@ static dbFILE *open_db_read(const char *service, const char *filename, int versi
myversion = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
if (feof(fp))
{
- Log() << "Error reading version number on " << f->filename << ": End of file detected.";
+ Anope::Logger.Log("Error reading version number on {0}: End of file detected.", f->filename);
delete f;
return NULL;
}
else if (myversion < version)
{
- Log() << "Unsuported database version (" << myversion << ") on " << f->filename << ".";
+ Anope::Logger.Log("Unsuported database version ({0}) on {1}.", myversion, f->filename);
delete f;
return NULL;
}
@@ -435,7 +464,8 @@ int read_int32(int32_t *ret, dbFILE *f)
static void LoadNicks()
{
- ServiceReference<ForbidService> forbid("ForbidService", "forbid");
+ if (!NickServ::service)
+ return;
dbFILE *f = open_db_read("NickServ", "nick.db", 14);
if (f == NULL)
return;
@@ -445,31 +475,37 @@ static void LoadNicks()
Anope::string buffer;
READ(read_string(buffer, f));
- NickCore *nc = new NickCore(buffer);
- const Anope::string settings[] = { "killprotect", "kill_quick", "ns_secure", "ns_private", "hide_email",
- "hide_mask", "hide_quit", "memo_signon", "memo_receive", "autoop", "msg", "ns_keepmodes" };
+ NickServ::Account *nc = Serialize::New<NickServ::Account *>();
+ nc->SetDisplay(buffer);
+
+ const Anope::string settings[] = { "killprotect", "kill_quick", "secure", "private", "hide_email",
+ "hide_mask", "hide_quit", "memo_signon", "memo_receive", "autoop", "msg", "keepmodes" };
for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j)
- nc->Shrink<bool>(settings[j].upper());
+ nc->UnsetS<bool>(settings[j]);
char pwbuf[32];
READ(read_buffer(pwbuf, f));
if (hashm == "plain")
- my_b64_encode(pwbuf, nc->pass);
+ {
+ Anope::string p;
+ my_b64_encode(pwbuf, p);
+ nc->SetPassword(p);
+ }
else if (hashm == "md5" || hashm == "oldmd5")
- nc->pass = Hex(pwbuf, 16);
+ nc->SetPassword(Hex(pwbuf, 16));
else if (hashm == "sha1")
- nc->pass = Hex(pwbuf, 20);
+ nc->SetPassword(Hex(pwbuf, 20));
else
- nc->pass = Hex(pwbuf, strlen(pwbuf));
- nc->pass = hashm + ":" + nc->pass;
+ nc->SetPassword(Hex(pwbuf, strlen(pwbuf)));
+ nc->SetPassword(hashm + ":" + nc->GetPassword());
READ(read_string(buffer, f));
- nc->email = buffer;
+ nc->SetEmail(buffer);
READ(read_string(buffer, f));
if (!buffer.empty())
- nc->Extend<Anope::string>("greet", buffer);
+ nc->SetGreet(buffer);
uint32_t u32;
READ(read_uint32(&u32, f));
@@ -480,122 +516,135 @@ static void LoadNicks()
READ(read_uint32(&u32, f));
if (u32 & OLD_NI_KILLPROTECT)
- nc->Extend<bool>("KILLPROTECT");
+ nc->SetKillProtect(true);
if (u32 & OLD_NI_SECURE)
- nc->Extend<bool>("NS_SECURE");
+ nc->SetSecure(true);
if (u32 & OLD_NI_MSG)
- nc->Extend<bool>("MSG");
+ nc->SetMsg(true);
if (u32 & OLD_NI_MEMO_HARDMAX)
- nc->Extend<bool>("MEMO_HARDMAX");
+ if (MemoServ::MemoInfo *mi = nc->GetMemos())
+ mi->SetHardMax(true);
if (u32 & OLD_NI_MEMO_SIGNON)
- nc->Extend<bool>("MEMO_SIGNON");
+ nc->SetMemoSignon(true);
if (u32 & OLD_NI_MEMO_RECEIVE)
- nc->Extend<bool>("MEMO_RECEIVE");
+ nc->SetMemoReceive(true);
if (u32 & OLD_NI_PRIVATE)
- nc->Extend<bool>("NS_PRIVATE");
+ nc->SetPrivate(true);
if (u32 & OLD_NI_HIDE_EMAIL)
- nc->Extend<bool>("HIDE_EMAIL");
+ nc->SetHideEmail(true);
if (u32 & OLD_NI_HIDE_MASK)
- nc->Extend<bool>("HIDE_MASK");
+ nc->SetHideMask(true);
if (u32 & OLD_NI_HIDE_QUIT)
- nc->Extend<bool>("HIDE_QUIT");
+ nc->SetHideQuit(true);
if (u32 & OLD_NI_KILL_QUICK)
- nc->Extend<bool>("KILL_QUICK");
+ nc->SetKillQuick(true);
if (u32 & OLD_NI_KILL_IMMED)
- nc->Extend<bool>("KILL_IMMED");
+ nc->SetKillImmed(true);
if (u32 & OLD_NI_MEMO_MAIL)
- nc->Extend<bool>("MEMO_MAIL");
+ nc->SetMemoMail(true);
if (u32 & OLD_NI_HIDE_STATUS)
- nc->Extend<bool>("HIDE_STATUS");
+ nc->SetHideStatus(true);
if (u32 & OLD_NI_SUSPENDED)
{
- SuspendInfo si;
- si.what = nc->display;
- si.when = si.expires = 0;
- nc->Extend("NS_SUSPENDED", si);
+ NSSuspendInfo *si = Serialize::New<NSSuspendInfo *>();
+ if (si)
+ {
+ si->SetAccount(nc);
+ }
}
if (!(u32 & OLD_NI_AUTOOP))
- nc->Extend<bool>("AUTOOP");
+ nc->SetAutoOp(true);
uint16_t u16;
READ(read_uint16(&u16, f));
switch (u16)
{
case LANG_ES:
- nc->language = "es_ES";
+ nc->SetLanguage("es_ES");
break;
case LANG_PT:
- nc->language = "pt_PT";
+ nc->SetLanguage("pt_PT");
break;
case LANG_FR:
- nc->language = "fr_FR";
+ nc->SetLanguage("fr_FR");
break;
case LANG_TR:
- nc->language = "tr_TR";
+ nc->SetLanguage("tr_TR");
break;
case LANG_IT:
- nc->language = "it_IT";
+ nc->SetLanguage("it_IT");
break;
case LANG_DE:
- nc->language = "de_DE";
+ nc->SetLanguage("de_DE");
break;
case LANG_CAT:
- nc->language = "ca_ES"; // yes, iso639 defines catalan as CA
+ nc->SetLanguage("ca_ES"); // yes, iso639 defines catalan as CA
break;
case LANG_GR:
- nc->language = "el_GR";
+ nc->SetLanguage("el_GR");
break;
case LANG_NL:
- nc->language = "nl_NL";
+ nc->SetLanguage("nl_NL");
break;
case LANG_RU:
- nc->language = "ru_RU";
+ nc->SetLanguage("ru_RU");
break;
case LANG_HUN:
- nc->language = "hu_HU";
+ nc->SetLanguage("hu_HU");
break;
case LANG_PL:
- nc->language = "pl_PL";
+ nc->SetLanguage("pl_PL");
break;
case LANG_EN_US:
case LANG_JA_JIS:
case LANG_JA_EUC:
case LANG_JA_SJIS: // these seem to be unused
default:
- nc->language = "en";
+ nc->SetLanguage("en");
}
READ(read_uint16(&u16, f));
for (uint16_t j = 0; j < u16; ++j)
{
READ(read_string(buffer, f));
- nc->access.push_back(buffer);
+
+ NickAccess *a = Serialize::New<NickAccess *>();
+ if (a)
+ {
+ a->SetAccount(nc);
+ a->SetMask(buffer);
+ }
}
int16_t i16;
READ(read_int16(&i16, f));
- READ(read_int16(&nc->memos.memomax, f));
+ READ(read_int16(&i16, f));
+ MemoServ::MemoInfo *mi = nc->GetMemos();
+ if (mi)
+ mi->SetMemoMax(i16);
for (int16_t j = 0; j < i16; ++j)
{
- Memo *m = new Memo;
+ MemoServ::Memo *m = Serialize::New<MemoServ::Memo *>();
READ(read_uint32(&u32, f));
uint16_t flags;
READ(read_uint16(&flags, f));
int32_t tmp32;
READ(read_int32(&tmp32, f));
- m->time = tmp32;
+ if (m)
+ m->SetTime(tmp32);
char sbuf[32];
READ(read_buffer(sbuf, f));
- m->sender = sbuf;
- READ(read_string(m->text, f));
- m->owner = nc->display;
- nc->memos.memos->push_back(m);
- m->mi = &nc->memos;
+ if (m)
+ m->SetSender(sbuf);
+ Anope::string text;
+ READ(read_string(text, f));
+ if (m)
+ m->SetText(text);
}
READ(read_uint16(&u16, f));
READ(read_int16(&i16, f));
- Log(LOG_DEBUG) << "Loaded NickCore " << nc->display;
+ Anope::Logger.Debug("Loaded nickserv account {0}", nc->GetDisplay());
}
for (int i = 0; i < 1024; ++i)
@@ -620,50 +669,47 @@ static void LoadNicks()
Anope::string core;
READ(read_string(core, f));
- NickCore *nc = NickCore::Find(core);
+ NickServ::Account *nc = NickServ::FindAccount(core);
if (nc == NULL)
{
- Log() << "Skipping coreless nick " << nick << " with core " << core;
+ Anope::Logger.Debug("Skipping coreless nick {0} with core {1}", nick, core);
continue;
}
if (tmpu16 & OLD_NS_VERBOTEN)
{
- if (!forbid)
+ if (nc->GetDisplay().find_first_of("?*") != Anope::string::npos)
{
delete nc;
continue;
}
- if (nc->display.find_first_of("?*") != Anope::string::npos)
+ ForbidData *d = Serialize::New<ForbidData *>();
+ if (d)
{
- delete nc;
- continue;
+ d->SetMask(nc->GetDisplay());
+ d->SetCreator(last_usermask);
+ d->SetReason(last_realname);
+ d->SetType(FT_NICK);
}
-
- ForbidData *d = forbid->CreateForbid();
- d->mask = nc->display;
- d->creator = last_usermask;
- d->reason = last_realname;
- d->expires = 0;
- d->created = 0;
- d->type = FT_NICK;
+
delete nc;
- forbid->AddForbid(d);
continue;
}
- NickAlias *na = new NickAlias(nick, nc);
- na->last_usermask = last_usermask;
- na->last_realname = last_realname;
- na->last_quit = last_quit;
- na->time_registered = time_registered;
- na->last_seen = last_seen;
+ NickServ::Nick *na = Serialize::New<NickServ::Nick *>();
+ na->SetNick(nick);
+ na->SetAccount(nc);
+ na->SetLastUsermask(last_usermask);
+ na->SetLastRealname(last_realname);
+ na->SetLastQuit(last_quit);
+ na->SetTimeRegistered(time_registered);
+ na->SetLastSeen(last_seen);
if (tmpu16 & OLD_NS_NO_EXPIRE)
- na->Extend<bool>("NS_NO_EXPIRE");
+ na->SetNoExpire(true);
- Log(LOG_DEBUG) << "Loaded NickAlias " << na->nick;
+ Anope::Logger.Debug("Loaded nick {0}", na->GetNick());
}
close_db(f); /* End of section Ia */
@@ -686,16 +732,24 @@ static void LoadVHosts()
READ(read_string(creator, f));
READ(read_int32(&vtime, f));
- NickAlias *na = NickAlias::Find(nick);
+ NickServ::Nick *na = NickServ::FindNick(nick);
if (na == NULL)
{
- Log() << "Removing vhost for non-existent nick " << nick;
+ Anope::Logger.Log("Removing vhost for non-existent nick {0}", nick);
continue;
}
- na->SetVhost(ident, host, creator, vtime);
+ HostServ::VHost *vhost = Serialize::New<HostServ::VHost *>();
+ if (vhost == nullptr)
+ continue;
+
+ vhost->SetAccount(na->GetAccount());
+ vhost->SetIdent(ident);
+ vhost->SetHost(host);
+ vhost->SetCreator(creator);
+ vhost->SetCreated(vtime);
- Log() << "Loaded vhost for " << na->nick;
+ Anope::Logger.Debug("Loaded vhost for {0}", na->GetNick());
}
close_db(f);
@@ -721,15 +775,19 @@ static void LoadBots()
READ(read_int32(&created, f));
READ(read_int16(&chancount, f));
- BotInfo *bi = BotInfo::Find(nick, true);
+ ServiceBot *bi = ServiceBot::Find(nick, true);
if (!bi)
- bi = new BotInfo(nick, user, host, real);
- bi->created = created;
+ bi = new ServiceBot(nick, user, host, real);
+
+ if (bi->bi == nullptr)
+ bi->bi = Serialize::New<BotInfo *>();
+
+ bi->bi->SetCreated(created);
if (flags & OLD_BI_PRIVATE)
- bi->oper_only = true;
+ bi->bi->SetOperOnly(true);
- Log(LOG_DEBUG) << "Loaded bot " << bi->nick;
+ Anope::Logger.Debug("Loaded bot {0}", bi->nick);
}
close_db(f);
@@ -737,7 +795,13 @@ static void LoadBots()
static void LoadChannels()
{
- ServiceReference<ForbidService> forbid("ForbidService", "forbid");
+ ServiceReference<BadWords> badwords;
+ ServiceReference<ChanServ::ChanServService> chanserv;
+
+ if (!chanserv)
+ return;
+
+ ServiceReference<ForbidService> forbid;
dbFILE *f = open_db_read("ChanServ", "chan.db", 16);
if (f == NULL)
return;
@@ -748,87 +812,93 @@ static void LoadChannels()
Anope::string buffer;
char namebuf[64];
READ(read_buffer(namebuf, f));
- ChannelInfo *ci = new ChannelInfo(namebuf);
+ ChanServ::Channel *ci = Serialize::New<ChanServ::Channel *>();
+ ci->SetName(namebuf);
- const Anope::string settings[] = { "keeptopic", "peace", "cs_private", "restricted", "cs_secure", "secureops", "securefounder",
- "signkick", "signkick_level", "topiclock", "persist", "noautoop", "cs_keepmodes" };
+ const Anope::string settings[] = { "keeptopic", "peace", "private", "restricted", "secure", "secureops", "securefounder",
+ "signkick", "signkick_level", "topiclock", "persist", "noautoop", "keepmodes" };
for (unsigned j = 0; j < sizeof(settings) / sizeof(Anope::string); ++j)
- ci->Shrink<bool>(settings[j].upper());
+ ci->UnsetS<bool>(settings[j]);
READ(read_string(buffer, f));
- ci->SetFounder(NickCore::Find(buffer));
+ ci->SetFounder(NickServ::FindAccount(buffer));
READ(read_string(buffer, f));
- ci->SetSuccessor(NickCore::Find(buffer));
+ ci->SetSuccessor(NickServ::FindAccount(buffer));
char pwbuf[32];
READ(read_buffer(pwbuf, f));
- READ(read_string(ci->desc, f));
+ Anope::string desc;
+ READ(read_string(desc, f));
+ ci->SetDesc(desc);
READ(read_string(buffer, f));
READ(read_string(buffer, f));
int32_t tmp32;
READ(read_int32(&tmp32, f));
- ci->time_registered = tmp32;
+ ci->SetTimeRegistered(tmp32);
READ(read_int32(&tmp32, f));
- ci->last_used = tmp32;
+ ci->SetLastUsed(tmp32);
- READ(read_string(ci->last_topic, f));
+ Anope::string last_topic;
+ READ(read_string(last_topic, f));
+ ci->SetLastTopic(last_topic);
READ(read_buffer(pwbuf, f));
- ci->last_topic_setter = pwbuf;
+ ci->SetLastTopicSetter(pwbuf);
READ(read_int32(&tmp32, f));
- ci->last_topic_time = tmp32;
+ ci->SetLastTopicTime(tmp32);
uint32_t tmpu32;
READ(read_uint32(&tmpu32, f));
// Temporary flags cleanup
tmpu32 &= ~0x80000000;
if (tmpu32 & OLD_CI_KEEPTOPIC)
- ci->Extend<bool>("KEEPTOPIC");
+ ci->SetKeepTopic(true);
if (tmpu32 & OLD_CI_SECUREOPS)
- ci->Extend<bool>("SECUREOPS");
+ ci->SetSecureOps(true);
if (tmpu32 & OLD_CI_PRIVATE)
- ci->Extend<bool>("CS_PRIVATE");
+ ci->SetPrivate(true);
if (tmpu32 & OLD_CI_TOPICLOCK)
- ci->Extend<bool>("TOPICLOCK");
+ ci->SetTopicLock(true);
if (tmpu32 & OLD_CI_RESTRICTED)
- ci->Extend<bool>("RESTRICTED");
+ ci->SetRestricted(true);
if (tmpu32 & OLD_CI_PEACE)
- ci->Extend<bool>("PEACE");
+ ci->SetPeace(true);
if (tmpu32 & OLD_CI_SECURE)
- ci->Extend<bool>("CS_SECURE");
+ ci->SetSecure(true);
if (tmpu32 & OLD_CI_NO_EXPIRE)
- ci->Extend<bool>("CS_NO_EXPIRE");
+ ci->SetNoExpire(true);
if (tmpu32 & OLD_CI_MEMO_HARDMAX)
- ci->Extend<bool>("MEMO_HARDMAX");
+ if (MemoServ::MemoInfo *mi = ci->GetMemos())
+ mi->SetHardMax(true);
if (tmpu32 & OLD_CI_SECUREFOUNDER)
- ci->Extend<bool>("SECUREFOUNDER");
+ ci->SetSecureFounder(true);
if (tmpu32 & OLD_CI_SIGNKICK)
- ci->Extend<bool>("SIGNKICK");
+ ci->SetSignKick(true);
if (tmpu32 & OLD_CI_SIGNKICK_LEVEL)
- ci->Extend<bool>("SIGNKICK_LEVEL");
+ ci->SetSignKickLevel(true);
Anope::string forbidby, forbidreason;
READ(read_string(forbidby, f));
READ(read_string(forbidreason, f));
if (tmpu32 & OLD_CI_SUSPENDED)
{
- SuspendInfo si;
- si.what = ci->name;
- si.by = forbidby;
- si.reason = forbidreason;
- si.when = si.expires = 0;
- ci->Extend("CS_SUSPENDED", si);
+ CSSuspendInfo *si = Serialize::New<CSSuspendInfo *>();
+ if (si)
+ {
+ si->SetChannel(ci);
+ si->SetBy(forbidby);
+ }
}
bool forbid_chan = tmpu32 & OLD_CI_VERBOTEN;
int16_t tmp16;
READ(read_int16(&tmp16, f));
- ci->bantype = tmp16;
+ ci->SetBanType(tmp16);
READ(read_int16(&tmp16, f));
if (tmp16 > 36)
@@ -838,17 +908,16 @@ static void LoadChannels()
int16_t level;
READ(read_int16(&level, f));
- if (level == ACCESS_INVALID)
- level = ACCESS_FOUNDER;
+ if (level == ChanServ::ACCESS_INVALID)
+ level = ChanServ::ACCESS_FOUNDER;
if (j == 10 && level < 0) // NOJOIN
- ci->Shrink<bool>("RESTRICTED"); // If CSDefRestricted was enabled this can happen
+ ci->SetRestricted(false);
ci->SetLevel(GetLevelName(j), level);
}
bool xop = tmpu32 & OLD_CI_XOP;
- ServiceReference<AccessProvider> provider_access("AccessProvider", "access/access"), provider_xop("AccessProvider", "access/xop");
uint16_t tmpu16;
READ(read_uint16(&tmpu16, f));
for (uint16_t j = 0; j < tmpu16; ++j)
@@ -857,19 +926,19 @@ static void LoadChannels()
READ(read_uint16(&in_use, f));
if (in_use)
{
- ChanAccess *access = NULL;
-
+ ChanServ::ChanAccess *access = NULL;
+
if (xop)
{
- if (provider_xop)
- access = provider_xop->Create();
+ access = Serialize::New<XOPChanAccess *>();
}
else
- if (provider_access)
- access = provider_access->Create();
+ {
+ access = Serialize::New<AccessChanAccess *>();
+ }
if (access)
- access->ci = ci;
+ access->SetChannel(ci);
int16_t level;
READ(read_int16(&level, f));
@@ -900,16 +969,19 @@ static void LoadChannels()
Anope::string mask;
READ(read_string(mask, f));
if (access)
- access->SetMask(mask, ci);
+ {
+ access->SetMask(mask);
+ NickServ::Nick *na = NickServ::FindNick(mask);
+ if (na)
+ na->SetAccount(na->GetAccount());
+ }
READ(read_int32(&tmp32, f));
if (access)
{
- access->last_seen = tmp32;
- access->creator = "Unknown";
- access->created = Anope::CurTime;
-
- ci->AddAccess(access);
+ access->SetLastSeen(tmp32);
+ access->SetCreator("Unknown");
+ access->SetCreated(Anope::CurTime);
}
}
}
@@ -943,74 +1015,67 @@ static void LoadChannels()
READ(read_string(buffer, f)); // +L
READ(read_int16(&tmp16, f));
- READ(read_int16(&ci->memos.memomax, f));
+ READ(read_int16(&tmp16, f));
+ MemoServ::MemoInfo *mi = ci->GetMemos();
+ if (mi)
+ mi->SetMemoMax(tmp16);
for (int16_t j = 0; j < tmp16; ++j)
{
READ(read_uint32(&tmpu32, f));
READ(read_uint16(&tmpu16, f));
- Memo *m = new Memo;
+ MemoServ::Memo *m = Serialize::New<MemoServ::Memo *>();
READ(read_int32(&tmp32, f));
- m->time = tmp32;
+ if (m)
+ m->SetTime(tmp32);
char sbuf[32];
READ(read_buffer(sbuf, f));
- m->sender = sbuf;
- READ(read_string(m->text, f));
- m->owner = ci->name;
- ci->memos.memos->push_back(m);
- m->mi = &ci->memos;
+ if (m)
+ m->SetSender(sbuf);
+ Anope::string text;
+ READ(read_string(text, f));
+ if (m)
+ m->SetText(text);
}
READ(read_string(buffer, f));
if (!buffer.empty())
{
- EntryMessageList *eml = ci->Require<EntryMessageList>("entrymsg");
- if (eml)
+ EntryMsg *e = Serialize::New<EntryMsg *>();
+ if (e)
{
- EntryMsg *e = eml->Create();
-
- e->chan = ci->name;
- e->creator = "Unknown";
- e->message = buffer;
- e->when = Anope::CurTime;
-
- (*eml)->push_back(e);
+ e->SetChannel(ci);
+ e->SetCreator("Unknown");
+ e->SetMessage(buffer);
+ e->SetWhen(Anope::CurTime);
}
}
READ(read_string(buffer, f));
- ci->bi = BotInfo::Find(buffer, true);
+ ci->SetBot(ServiceBot::Find(buffer, true));
READ(read_int32(&tmp32, f));
if (tmp32 & OLD_BS_DONTKICKOPS)
- ci->Extend<bool>("BS_DONTKICKOPS");
+ ci->SetS<bool>("BS_DONTKICKOPS", true);
if (tmp32 & OLD_BS_DONTKICKVOICES)
- ci->Extend<bool>("BS_DONTKICKVOICES");
+ ci->SetS<bool>("BS_DONTKICKVOICES", true);
if (tmp32 & OLD_BS_FANTASY)
- ci->Extend<bool>("BS_FANTASY");
+ ci->SetFantasy(true);
if (tmp32 & OLD_BS_GREET)
- ci->Extend<bool>("BS_GREET");
+ ci->SetGreet(true);
if (tmp32 & OLD_BS_NOBOT)
- ci->Extend<bool>("BS_NOBOT");
+ ci->SetS<bool>("BS_NOBOT", true);
- KickerData *kd = ci->Require<KickerData>("kickerdata");
+ KickerData *kd = GetKickerData(ci);
if (kd)
{
- if (tmp32 & OLD_BS_KICK_BOLDS)
- kd->bolds = true;
- if (tmp32 & OLD_BS_KICK_COLORS)
- kd->colors = true;
- if (tmp32 & OLD_BS_KICK_REVERSES)
- kd->reverses = true;
- if (tmp32 & OLD_BS_KICK_UNDERLINES)
- kd->underlines = true;
- if (tmp32 & OLD_BS_KICK_BADWORDS)
- kd->badwords = true;
- if (tmp32 & OLD_BS_KICK_CAPS)
- kd->caps = true;
- if (tmp32 & OLD_BS_KICK_FLOOD)
- kd->flood = true;
- if (tmp32 & OLD_BS_KICK_REPEAT)
- kd->repeat = true;
+ kd->SetBolds(tmp32 & OLD_BS_KICK_BOLDS);
+ kd->SetColors(tmp32 & OLD_BS_KICK_COLORS);
+ kd->SetReverses(tmp32 & OLD_BS_KICK_REVERSES);
+ kd->SetUnderlines(tmp32 & OLD_BS_KICK_UNDERLINES);
+ kd->SetBadwords(tmp32 & OLD_BS_KICK_BADWORDS);
+ kd->SetCaps(tmp32 & OLD_BS_KICK_CAPS);
+ kd->SetFlood(tmp32 & OLD_BS_KICK_FLOOD);
+ kd->SetRepeat(tmp32 & OLD_BS_KICK_REPEAT);
}
READ(read_int16(&tmp16, f));
@@ -1018,27 +1083,51 @@ static void LoadChannels()
{
int16_t ttb;
READ(read_int16(&ttb, f));
- if (j < TTB_SIZE && kd)
- kd->ttb[j] = ttb;
+ switch (j)
+ {
+ case TTB_BOLDS:
+ kd->SetTTBBolds(ttb);
+ break;
+ case TTB_COLORS:
+ kd->SetTTBColors(ttb);
+ break;
+ case TTB_REVERSES:
+ kd->SetTTBReverses(ttb);
+ break;
+ case TTB_UNDERLINES:
+ kd->SetTTBUnderlines(ttb);
+ break;
+ case TTB_BADWORDS:
+ kd->SetTTBBadwords(ttb);
+ break;
+ case TTB_CAPS:
+ kd->SetTTBCaps(ttb);
+ break;
+ case TTB_FLOOD:
+ kd->SetTTBFlood(ttb);
+ break;
+ case TTB_REPEAT:
+ kd->SetTTBRepeat(ttb);
+ break;
+ }
}
READ(read_int16(&tmp16, f));
if (kd)
- kd->capsmin = tmp16;
+ kd->SetCapsMin(tmp16);
READ(read_int16(&tmp16, f));
if (kd)
- kd->capspercent = tmp16;
+ kd->SetCapsPercent(tmp16);
READ(read_int16(&tmp16, f));
if (kd)
- kd->floodlines = tmp16;
+ kd->SetFloodLines(tmp16);
READ(read_int16(&tmp16, f));
if (kd)
- kd->floodsecs = tmp16;
+ kd->SetFloodSecs(tmp16);
READ(read_int16(&tmp16, f));
if (kd)
- kd->repeattimes = tmp16;
+ kd->SetRepeatTimes(tmp16);
- BadWords *bw = ci->Require<BadWords>("badwords");
READ(read_uint16(&tmpu16, f));
for (uint16_t j = 0; j < tmpu16; ++j)
{
@@ -1058,38 +1147,33 @@ static void LoadChannels()
else if (type == 3)
bwtype = BW_END;
- if (bw)
- bw->AddBadWord(buffer, bwtype);
+ if (badwords)
+ badwords->AddBadWord(ci, buffer, bwtype);
}
}
if (forbid_chan)
{
- if (!forbid)
+ if (ci->GetName().find_first_of("?*") != Anope::string::npos)
{
delete ci;
continue;
}
- if (ci->name.find_first_of("?*") != Anope::string::npos)
+ ForbidData *d = Serialize::New<ForbidData *>();
+ if (d)
{
- delete ci;
- continue;
+ d->SetMask(ci->GetName());
+ d->SetCreator(forbidby);
+ d->SetReason(forbidreason);
+ d->SetType(FT_CHAN);
}
-
- ForbidData *d = forbid->CreateForbid();
- d->mask = ci->name;
- d->creator = forbidby;
- d->reason = forbidreason;
- d->expires = 0;
- d->created = 0;
- d->type = FT_CHAN;
+
delete ci;
- forbid->AddForbid(d);
continue;
}
- Log(LOG_DEBUG) << "Loaded channel " << ci->name;
+ Anope::Logger.Debug("Loaded channel {0}", ci->GetName());
}
close_db(f);
@@ -1104,9 +1188,8 @@ static void LoadOper()
XLineManager *akill, *sqline, *snline, *szline;
akill = sqline = snline = szline = NULL;
- for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it)
+ for (XLineManager *xl : XLineManager::XLineManagers)
{
- XLineManager *xl = *it;
if (xl->Type() == 'G')
akill = xl;
else if (xl->Type() == 'Q')
@@ -1138,8 +1221,14 @@ static void LoadOper()
if (!akill)
continue;
- XLine *x = new XLine(user + "@" + host, by, expires, reason, XLineManager::GenerateUID());
- x->created = seton;
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(user + "@" + host);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
akill->AddXLine(x);
}
@@ -1158,8 +1247,14 @@ static void LoadOper()
if (!snline)
continue;
- XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
- x->created = seton;
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(mask);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
snline->AddXLine(x);
}
@@ -1178,8 +1273,14 @@ static void LoadOper()
if (!sqline)
continue;
- XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
- x->created = seton;
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(mask);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
sqline->AddXLine(x);
}
@@ -1198,8 +1299,14 @@ static void LoadOper()
if (!szline)
continue;
- XLine *x = new XLine(mask, by, expires, reason, XLineManager::GenerateUID());
- x->created = seton;
+ XLine *x = Serialize::New<XLine *>();
+ x->SetMask(mask);
+ x->SetBy(by);
+ x->SetExpires(expires);
+ x->SetReason(reason);
+ x->SetID(XLineManager::GenerateUID());
+ x->SetCreated(seton);
+
szline->AddXLine(x);
}
@@ -1208,13 +1315,10 @@ static void LoadOper()
static void LoadExceptions()
{
- if (!session_service)
- return;
-
dbFILE *f = open_db_read("OperServ", "exception.db", 9);
if (f == NULL)
return;
-
+
int16_t num;
READ(read_int16(&num, f));
for (int i = 0; i < num; ++i)
@@ -1231,14 +1335,16 @@ static void LoadExceptions()
READ(read_int32(&time, f));
READ(read_int32(&expires, f));
- Exception *exception = session_service->CreateException();
- exception->mask = mask;
- exception->limit = limit;
- exception->who = who;
- exception->time = time;
- exception->expires = expires;
- exception->reason = reason;
- session_service->AddException(exception);
+ Exception *e = Serialize::New<Exception *>();
+ if (e)
+ {
+ e->SetMask(mask);
+ e->SetLimit(limit);
+ e->SetWho(who);
+ e->SetTime(time);
+ e->SetExpires(expires);
+ e->SetReason(reason);
+ }
}
close_db(f);
@@ -1246,9 +1352,6 @@ static void LoadExceptions()
static void LoadNews()
{
- if (!news_service)
- return;
-
dbFILE *f = open_db_read("OperServ", "news.db", 9);
if (f == NULL)
@@ -1260,60 +1363,68 @@ static void LoadNews()
for (int16_t i = 0; i < n; i++)
{
int16_t type;
- NewsItem *ni = news_service->CreateNewsItem();
+ NewsItem *ni = Serialize::New<NewsItem *>();
+
+ if (!ni)
+ break;
READ(read_int16(&type, f));
switch (type)
{
case OLD_NEWS_LOGON:
- ni->type = NEWS_LOGON;
+ ni->SetNewsType(NEWS_LOGON);
break;
case OLD_NEWS_OPER:
- ni->type = NEWS_OPER;
+ ni->SetNewsType(NEWS_OPER);
break;
case OLD_NEWS_RANDOM:
- ni->type = NEWS_RANDOM;
+ ni->SetNewsType(NEWS_RANDOM);
break;
}
int32_t unused;
READ(read_int32(&unused, f));
- READ(read_string(ni->text, f));
+ Anope::string text;
+ READ(read_string(text, f));
+ ni->SetText(text);
char who[32];
READ(read_buffer(who, f));
- ni->who = who;
+ ni->SetWho(who);
int32_t tmp;
READ(read_int32(&tmp, f));
- ni->time = tmp;
-
- news_service->AddNewsItem(ni);
+ ni->SetTime(tmp);
}
close_db(f);
}
class DBOld : public Module
+ , public EventHook<Event::LoadDatabase>
+ , public EventHook<Event::UplinkSync>
{
- PrimitiveExtensibleItem<uint32_t> mlock_on, mlock_off, mlock_limit;
- PrimitiveExtensibleItem<Anope::string> mlock_key;
+ ExtensibleItem<uint32_t> mlock_on, mlock_off, mlock_limit; // XXX these are no longer required because of confmodes
+ ExtensibleItem<Anope::string> mlock_key;
public:
- DBOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR),
- mlock_on(this, "mlock_on"), mlock_off(this, "mlock_off"), mlock_limit(this, "mlock_limit"), mlock_key(this, "mlock_key")
+ DBOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
+ , EventHook<Event::LoadDatabase>(this)
+ , EventHook<Event::UplinkSync>(this)
+ , mlock_on(this, "mlock_on")
+ , mlock_off(this, "mlock_off")
+ , mlock_limit(this, "mlock_limit")
+ , mlock_key(this, "mlock_key")
{
-
-
- hashm = Config->GetModule(this)->Get<const Anope::string>("hash");
+ hashm = Config->GetModule(this)->Get<Anope::string>("hash");
if (hashm != "md5" && hashm != "oldmd5" && hashm != "sha1" && hashm != "plain" && hashm != "sha256")
throw ModuleException("Invalid hash method");
}
- EventReturn OnLoadDatabase() anope_override
+ EventReturn OnLoadDatabase() override
{
LoadNicks();
LoadVHosts();
@@ -1326,11 +1437,13 @@ class DBOld : public Module
return EVENT_STOP;
}
- void OnUplinkSync(Server *s) anope_override
+ void OnUplinkSync(Server *s) override
{
- for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
+ if (!ChanServ::service)
+ return;
+ for (auto& it : ChanServ::service->GetChannels())
{
- ChannelInfo *ci = it->second;
+ ChanServ::Channel *ci = it.second;
uint32_t *limit = mlock_limit.Get(ci);
Anope::string *key = mlock_key.Get(ci);
@@ -1357,5 +1470,10 @@ class DBOld : public Module
}
};
+template<> void ModuleInfo<DBOld>(ModuleDef *def)
+{
+ def->Depends("chanserv.access");
+}
+
MODULE_INIT(DBOld)
diff --git a/modules/database/sql.cpp b/modules/database/sql.cpp
new file mode 100644
index 000000000..bd5a96b90
--- /dev/null
+++ b/modules/database/sql.cpp
@@ -0,0 +1,380 @@
+/*
+ * Anope IRC Services
+ *
+ * Copyright (C) 2011-2016 Anope Team <team@anope.org>
+ *
+ * This file is part of Anope. Anope 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 see <http://www.gnu.org/licenses/>.
+ */
+
+#include "module.h"
+#include "modules/sql.h"
+
+using namespace SQL;
+
+class DBSQL : public Module, public Pipe
+ , public EventHook<Event::SerializeEvents>
+{
+ private:
+ bool transaction = false;
+ bool inited = false;
+ Anope::string prefix;
+ ServiceReference<Provider> SQL;
+
+ Result Run(const Query &query)
+ {
+ if (!SQL)
+ return Result();
+
+ if (!inited)
+ {
+ inited = true;
+ for (const Query &q : SQL->InitSchema(prefix))
+ SQL->RunQuery(q);
+ }
+
+ return SQL->RunQuery(query);
+ }
+
+ void StartTransaction()
+ {
+ if (!SQL || transaction)
+ return;
+
+ Run(SQL->BeginTransaction());
+
+ transaction = true;
+ Notify();
+ }
+
+ void Commit()
+ {
+ if (!SQL || !transaction)
+ return;
+
+ Run(SQL->Commit());
+
+ transaction = false;
+ }
+
+ public:
+ DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
+ , EventHook<Event::SerializeEvents>(this)
+ {
+ }
+
+ void OnNotify() override
+ {
+ Commit();
+ Serialize::GC();
+ }
+
+ void OnReload(Configuration::Conf *conf) override
+ {
+ Configuration::Block *block = conf->GetModule(this);
+ this->SQL = ServiceReference<Provider>(block->Get<Anope::string>("engine"));
+ this->prefix = block->Get<Anope::string>("prefix", "anope_");
+ inited = false;
+ }
+
+ EventReturn OnSerializeList(Serialize::TypeBase *type, std::vector<Serialize::ID> &ids) override
+ {
+ StartTransaction();
+
+ ids.clear();
+
+ Query query = "SELECT `id` FROM `" + prefix + type->GetName() + "`";
+ Result res = Run(query);
+ for (int i = 0; i < res.Rows(); ++i)
+ {
+ Serialize::ID id = convertTo<Serialize::ID>(res.Get(i, "id"));
+ ids.push_back(id);
+ }
+
+ return EVENT_ALLOW;
+ }
+
+ EventReturn OnSerializeFind(Serialize::TypeBase *type, Serialize::FieldBase *field, const Anope::string &value, Serialize::ID &id) override
+ {
+ if (!SQL)
+ return EVENT_CONTINUE;
+
+ StartTransaction();
+
+ for (Query &q : SQL->CreateTable(prefix, type))
+ Run(q);
+
+ for (Query &q : SQL->AlterTable(prefix, type, field))
+ Run(q);
+
+ for (const Query &q : SQL->CreateIndex(prefix + type->GetName(), field->serialize_name))
+ Run(q);
+
+ Query query = SQL->SelectFind(prefix + type->GetName(), field->serialize_name);
+
+ query.SetValue("value", value);
+ Result res = Run(query);
+ if (res.Rows())
+ try
+ {
+ id = convertTo<Serialize::ID>(res.Get(0, "id"));
+ return EVENT_ALLOW;
+ }
+ catch (const ConvertException &)
+ {
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ private:
+ bool GetValue(Serialize::Object *object, Serialize::FieldBase *field, SQL::Result::Value &v)
+ {
+ StartTransaction();
+
+ Query query = "SELECT `" + field->serialize_name + "` FROM `" + prefix + object->GetSerializableType()->GetName() + "` WHERE `id` = @id@";
+ query.SetValue("id", object->id, false);
+ Result res = Run(query);
+
+ if (res.Rows() == 0)
+ return false;
+
+ v = res.GetValue(0, field->serialize_name);
+ return true;
+ }
+
+ void GetRefs(Serialize::Object *object, Serialize::TypeBase *type, std::vector<Serialize::Edge> &edges)
+ {
+ for (Serialize::FieldBase *field : type->GetFields())
+ {
+ if (field->is_object && object->GetSerializableType()->GetName() == field->GetTypeName())
+ {
+ Anope::string table = prefix + type->GetName();
+
+ Query query = "SELECT id FROM " + table +
+ " WHERE " + field->serialize_name + " = @id@";
+
+ query.SetValue("id", object->id, false);
+
+ Result res = Run(query);
+ for (int i = 0; i < res.Rows(); ++i)
+ {
+ Serialize::ID id = convertTo<Serialize::ID>(res.Get(i, "id"));
+
+ Serialize::Object *other = type->Require(id);
+ if (other == nullptr)
+ {
+ Anope::Logger.Debug("Unable to require id {0} type {1}", id, type->GetName());
+ continue;
+ }
+
+ // other type, other field, direction
+ edges.emplace_back(other, field, false);
+ }
+ }
+ }
+ }
+
+ public:
+ EventReturn OnSerializeGet(Serialize::Object *object, Serialize::FieldBase *field, Anope::string &value) override
+ {
+ SQL::Result::Value v;
+
+ if (!GetValue(object, field, v))
+ return EVENT_CONTINUE;
+
+ value = v.value;
+ return EVENT_ALLOW;
+ }
+
+ EventReturn OnSerializeGetRefs(Serialize::Object *object, Serialize::TypeBase *type, std::vector<Serialize::Edge> &edges) override
+ {
+ StartTransaction();
+
+ edges.clear();
+
+ if (type == nullptr)
+ {
+ for (Serialize::TypeBase *type : Serialize::TypeBase::GetTypes())
+ GetRefs(object, type, edges);
+ }
+ else
+ {
+ GetRefs(object, type, edges);
+ }
+
+ return EVENT_ALLOW;
+ }
+
+ EventReturn OnSerializeDeref(Serialize::ID id, Serialize::TypeBase *type) override
+ {
+ StartTransaction();
+
+ Query query = "SELECT `id` FROM `" + prefix + type->GetName() + "` WHERE `id` = @id@";
+ query.SetValue("id", id, false);
+ Result res = Run(query);
+ if (res.Rows() == 0)
+ return EVENT_CONTINUE;
+ return EVENT_ALLOW;
+ }
+
+ EventReturn OnSerializeGetSerializable(Serialize::Object *object, Serialize::FieldBase *field, Anope::string &type, Serialize::ID &value) override
+ {
+ StartTransaction();
+
+ Query query = "SELECT `" + field->serialize_name + "` FROM `" + prefix + object->GetSerializableType()->GetName() + "` "
+ "WHERE id = @id@";
+ query.SetValue("id", object->id, false);
+ Result res = Run(query);
+
+ if (res.Rows() == 0)
+ return EVENT_CONTINUE;
+
+ type = field->GetTypeName();
+ try
+ {
+ value = convertTo<Serialize::ID>(res.Get(0, field->serialize_name));
+ }
+ catch (const ConvertException &ex)
+ {
+ return EVENT_STOP;
+ }
+
+ return EVENT_ALLOW;
+ }
+
+ private:
+ void DoSet(Serialize::Object *object, Serialize::FieldBase *field, bool is_object, const Anope::string *value)
+ {
+ if (!SQL)
+ return;
+
+ StartTransaction();
+
+ for (Query &q : SQL->CreateTable(prefix, object->GetSerializableType()))
+ Run(q);
+
+ for (Query &q : SQL->AlterTable(prefix, object->GetSerializableType(), field))
+ Run(q);
+
+ Query q;
+ q.SetValue("id", object->id, false);
+ if (value)
+ q.SetValue(field->serialize_name, *value, !is_object);
+ else
+ q.SetNull(field->serialize_name);
+
+ for (Query &q2 : SQL->Replace(prefix + object->GetSerializableType()->GetName(), q, { "id" }))
+ Run(q2);
+ }
+
+ public:
+ EventReturn OnSerializeSet(Serialize::Object *object, Serialize::FieldBase *field, const Anope::string &value) override
+ {
+ DoSet(object, field, false, &value);
+ return EVENT_STOP;
+ }
+
+ EventReturn OnSerializeSetSerializable(Serialize::Object *object, Serialize::FieldBase *field, Serialize::Object *value) override
+ {
+ if (!SQL)
+ return EVENT_CONTINUE;
+
+ StartTransaction();
+
+ if (value)
+ {
+ Anope::string v = stringify(value->id);
+ DoSet(object, field, true, &v);
+ }
+ else
+ {
+ DoSet(object, field, true, nullptr);
+ }
+
+ return EVENT_STOP;
+ }
+
+ EventReturn OnSerializeUnset(Serialize::Object *object, Serialize::FieldBase *field) override
+ {
+ DoSet(object, field, false, nullptr);
+ return EVENT_STOP;
+ }
+
+ EventReturn OnSerializeUnsetSerializable(Serialize::Object *object, Serialize::FieldBase *field) override
+ {
+ DoSet(object, field, true, nullptr);
+ return EVENT_STOP;
+ }
+
+ EventReturn OnSerializeHasField(Serialize::Object *object, Serialize::FieldBase *field) override
+ {
+ if (field->is_object)
+ {
+ Anope::string type;
+ Serialize::ID id;
+
+ EventReturn er = OnSerializeGetSerializable(object, field, type, id);
+
+ if (er != EVENT_ALLOW)
+ return EVENT_CONTINUE;
+
+ field->UnserializeFromString(object, type + ":" + stringify(id));
+ return EVENT_STOP;
+ }
+ else
+ {
+ SQL::Result::Value v;
+
+ if (!GetValue(object, field, v))
+ return EVENT_CONTINUE;
+
+ if (v.null)
+ return EVENT_CONTINUE;
+
+ field->UnserializeFromString(object, v.value);
+ return EVENT_STOP;
+ }
+ }
+
+ EventReturn OnSerializableGetId(Serialize::TypeBase *type, Serialize::ID &id) override
+ {
+ if (!SQL)
+ return EVENT_CONTINUE;
+
+ StartTransaction();
+
+ for (Query &q : SQL->CreateTable(prefix, type))
+ Run(q);
+
+ id = SQL->GetID(prefix, type->GetName());
+ return EVENT_ALLOW;
+ }
+
+ void OnSerializableCreate(Serialize::Object *object) override
+ {
+ }
+
+ void OnSerializableDelete(Serialize::Object *object) override
+ {
+ StartTransaction();
+
+ Serialize::TypeBase *type = object->GetSerializableType();
+
+ Query query("DELETE FROM `" + prefix + type->GetName() + "` WHERE `id` = " + stringify(object->id));
+ Run(query);
+ }
+};
+
+MODULE_INIT(DBSQL)
+