From 1f2399de364c09adcce4193895cd362d80ffdfc5 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 25 Sep 2011 04:19:15 -0400 Subject: Added a new database format and sqlite support. Also moved db-convert to a module. --- modules/commands/bs_kick.cpp | 123 +++++++++++++++++----------- modules/commands/cs_access.cpp | 42 +++++++++- modules/commands/cs_entrymsg.cpp | 128 +++++++++++++++-------------- modules/commands/cs_flags.cpp | 39 ++++++++- modules/commands/cs_info.cpp | 7 +- modules/commands/cs_seen.cpp | 151 +++++++++++++--------------------- modules/commands/cs_set_misc.cpp | 69 +++++++++------- modules/commands/cs_suspend.cpp | 11 ++- modules/commands/cs_xop.cpp | 38 ++++++++- modules/commands/hs_request.cpp | 165 +++++++++++++++----------------------- modules/commands/ns_ajoin.cpp | 164 +++++++++++++++++++------------------ modules/commands/ns_register.cpp | 19 +++-- modules/commands/ns_resetpass.cpp | 29 ++++--- modules/commands/ns_set_email.cpp | 12 +-- modules/commands/ns_set_misc.cpp | 70 +++++++++------- modules/commands/os_forbid.cpp | 45 +---------- modules/commands/os_forbid.h | 40 ++++++++- modules/commands/os_ignore.cpp | 52 ++---------- modules/commands/os_ignore.h | 32 +++++++- modules/commands/os_login.cpp | 6 +- modules/commands/os_module.cpp | 14 ---- modules/commands/os_news.cpp | 48 +---------- modules/commands/os_news.h | 36 ++++++++- modules/commands/os_oper.cpp | 64 ++++++++------- modules/commands/os_session.cpp | 70 ++++++++-------- modules/commands/os_session.h | 46 +++++++++++ modules/commands/os_shutdown.cpp | 4 +- 27 files changed, 817 insertions(+), 707 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp index 74ccaf05c..2c41b4b90 100644 --- a/modules/commands/bs_kick.cpp +++ b/modules/commands/bs_kick.cpp @@ -577,26 +577,60 @@ class CommandBSKick : public Command } }; -struct BanData +struct BanData : public ExtensibleItem { - Anope::string mask; - time_t last_use; - int16 ttb[TTB_SIZE]; + struct Data + { + Anope::string mask; + time_t last_use; + int16 ttb[TTB_SIZE]; + + Data() + { + this->Clear(); + } + + void Clear() + { + last_use = 0; + for (int i = 0; i < TTB_SIZE; ++i) + this->ttb[i] = 0; + } + }; + + private: + typedef std::map > data_type; + data_type data_map; - BanData() + public: + Data &get(const Anope::string &key) { - this->Clear(); + return this->data_map[key]; } - void Clear() + bool empty() const + { + return this->data_map.empty(); + } + + void purge() { - last_use = 0; - for (int i = 0; i < TTB_SIZE; ++i) - this->ttb[i] = 0; + for (data_type::iterator it = data_map.begin(), it_end = data_map.end(); it != it_end;) + { + const Anope::string &user = it->first; + Data &bd = it->second; + ++it; + + if (Anope::CurTime - bd.last_use > Config->BSKeepData) + { + data_map.erase(user); + continue; + } + } } }; -struct UserData +struct UserData : public ExtensibleItem { UserData() { @@ -621,6 +655,11 @@ struct UserData Anope::string lastline; Anope::string lasttarget; int16 times; + + void OnDelete() + { + delete this; + } }; @@ -637,23 +676,11 @@ class BanDataPurger : public CallBack { Channel *c = it->second; - std::map bandata; - if (c->GetExtRegular("bs_main_bandata", bandata)) + BanData *bd = c->GetExt("bs_main_bandata"); + if (bd != NULL) { - for (std::map::iterator it2 = bandata.begin(), it2_end = bandata.end(); it2 != it2_end;) - { - const Anope::string &user = it2->first; - BanData *bd = &it2->second; - ++it2; - - if (Anope::CurTime - bd->last_use > Config->BSKeepData) - { - bandata.erase(user); - continue; - } - } - - if (bandata.empty()) + bd->purge(); + if (bd->empty()) c->Shrink("bs_main_bandata"); } } @@ -665,30 +692,32 @@ class BSKick : public Module CommandBSKick commandbskick; BanDataPurger purger; - BanData *GetBanData(User *u, Channel *c) + BanData::Data &GetBanData(User *u, Channel *c) { - std::map bandatamap; - if (!c->GetExtRegular("bs_main_bandata", bandatamap)); - c->Extend("bs_main_bandata", new ExtensibleItemRegular >(bandatamap)); - c->GetExtRegular("bs_main_bandata", bandatamap); - - BanData *bd = &bandatamap[u->GetMask()]; - if (bd->last_use && Anope::CurTime - bd->last_use > Config->BSKeepData) - bd->Clear(); - bd->last_use = Anope::CurTime; - return bd; + BanData *bd = c->GetExt("bs_main_bandata"); + if (bd == NULL) + { + bd = new BanData(); + c->Extend("bs_main_bandata", bd); + } + + return bd->get(u->GetMask()); } UserData *GetUserData(User *u, Channel *c) { - UserData *ud = NULL; UserContainer *uc = c->FindUser(u); - if (uc != NULL && !uc->GetExtPointer("bs_main_userdata", ud)) + if (uc == NULL) + return NULL; + + UserData *ud = uc->GetExt("bs_main_userdata"); + if (ud == NULL) { ud = new UserData(); - uc->Extend("bs_main_userdata", new ExtensibleItemPointer(ud)); + uc->Extend("bs_main_userdata", ud); } - return ud; + + return ud; } void check_ban(ChannelInfo *ci, User *u, int ttbtype) @@ -697,17 +726,17 @@ class BSKick : public Module if (u->server->IsULined()) return; - BanData *bd = this->GetBanData(u, ci->c); + BanData::Data &bd = this->GetBanData(u, ci->c); - ++bd->ttb[ttbtype]; - if (ci->ttb[ttbtype] && bd->ttb[ttbtype] >= ci->ttb[ttbtype]) + ++bd.ttb[ttbtype]; + if (ci->ttb[ttbtype] && bd.ttb[ttbtype] >= ci->ttb[ttbtype]) { - /* Should not use == here because bd->ttb[ttbtype] could possibly be > ci->ttb[ttbtype] + /* Should not use == here because bd.ttb[ttbtype] could possibly be > ci->ttb[ttbtype] * if the TTB was changed after it was not set (0) before and the user had already been * kicked a few times. Bug #1056 - Adam */ Anope::string mask; - bd->ttb[ttbtype] = 0; + bd.ttb[ttbtype] = 0; get_idealban(ci, u, mask); diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 2821ba5c3..3e737b709 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -28,7 +28,7 @@ static void reset_levels(ChannelInfo *ci) ci->SetLevel(it->first, it->second); } -class AccessChanAccess : public ChanAccess +class AccessChanAccess : public ChanAccess, public Serializable { public: int level; @@ -86,6 +86,41 @@ class AccessChanAccess : public ChanAccess return highest; } } + + Anope::string serialize_name() { return "AccessChanAccess"; } + serialized_data serialize() + { + serialized_data data; + + data["provider"] << this->provider->name; + data["ci"] << this->ci->name; + data["mask"] << this->mask; + data["creator"] << this->creator; + data["last_seen"].setType(Serialize::DT_INT) << this->last_seen; + data["created"].setType(Serialize::DT_INT) << this->created; + data["level"].setType(Serialize::DT_INT) << this->level; + + return data; + } + + static void unserialize(SerializableBase::serialized_data &data) + { + service_reference aprovider(data["provider"].astr()); + ChannelInfo *ci = cs_findchan(data["ci"].astr()); + if (!aprovider || !ci) + return; + + AccessChanAccess *access = new AccessChanAccess(aprovider); + access->provider = aprovider; + access->ci = ci; + data["mask"] >> access->mask; + data["creator"] >> access->creator; + data["last_seen"] >> access->last_seen; + data["created"] >> access->created; + data["level"] >> access->level; + + ci->AddAccess(access); + } }; class AccessAccessProvider : public AccessProvider @@ -459,10 +494,10 @@ class CommandCSAccess : public Command source.Reply(ACCESS_DENIED); else { - ci->ClearAccess(); - FOREACH_MOD(I_OnAccessClear, OnAccessClear(ci, u)); + ci->ClearAccess(); + source.Reply(_("Channel %s access list has been cleared."), ci->name.c_str()); bool override = !IsFounder(u, ci); @@ -833,6 +868,7 @@ class CSAccess : public Module { this->SetAuthor("Anope"); + Serializable::Alloc.Register("AccessChanAccess"); Implementation i[] = { I_OnReload, I_OnCreateChan, I_OnGroupCheckPriv }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); diff --git a/modules/commands/cs_entrymsg.cpp b/modules/commands/cs_entrymsg.cpp index 05b97e027..6fa8d5dd3 100644 --- a/modules/commands/cs_entrymsg.cpp +++ b/modules/commands/cs_entrymsg.cpp @@ -13,34 +13,70 @@ #include "module.h" -struct EntryMsg +struct EntryMsg : Serializable { - static unsigned MaxEntries; + ChannelInfo *ci; + Anope::string creator; + Anope::string message; + time_t when; - EntryMsg(const Anope::string &cname, const Anope::string &cmessage, time_t ct = Anope::CurTime) + EntryMsg(ChannelInfo *c, const Anope::string &cname, const Anope::string &cmessage, time_t ct = Anope::CurTime) { + + this->ci = c; this->creator = cname; this->message = cmessage; this->when = ct; } - Anope::string creator; - Anope::string message; - time_t when; + serialized_data serialize() + { + serialized_data data; + + data["ci"] << this->ci->name; + data["creator"] << this->creator; + data["message"] << this->message; + data["when"].setType(Serialize::DT_INT) << this->when; + + return data; + } + + static void unserialize(serialized_data &data); }; -unsigned EntryMsg::MaxEntries = 0; + +static unsigned MaxEntries = 0; + +struct EntryMessageList : std::vector, ExtensibleItem +{ +}; + +void EntryMsg::unserialize(serialized_data &data) +{ + ChannelInfo *ci = cs_findchan(data["ci"].astr()); + if (!ci) + return; + + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); + if (messages == NULL) + { + messages = new EntryMessageList(); + ci->Extend("cs_entrymsg", messages); + } + + messages->push_back(EntryMsg(ci, data["creator"].astr(), data["message"].astr())); +} class CommandEntryMessage : public Command { private: void DoList(CommandSource &source, ChannelInfo *ci) { - std::vector messages; - if (ci->GetExtRegular("cs_entrymsg", messages)) + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); + if (messages == NULL) { source.Reply(_("Entry message list for \2%s\2:"), ci->name.c_str()); - for (unsigned i = 0; i < messages.size(); ++i) - source.Reply(CHAN_LIST_ENTRY, i + 1, messages[i].message.c_str(), messages[i].creator.c_str(), do_strftime(messages[i].when).c_str()); + for (unsigned i = 0; i < messages->size(); ++i) + source.Reply(CHAN_LIST_ENTRY, i + 1, (*messages)[i].message.c_str(), (*messages)[i].creator.c_str(), do_strftime((*messages)[i].when).c_str()); source.Reply(_("End of entry message list.")); } else @@ -49,35 +85,36 @@ class CommandEntryMessage : public Command void DoAdd(CommandSource &source, ChannelInfo *ci, const Anope::string &message) { - std::vector messages; - ci->GetExtRegular("cs_entrymsg", messages); + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); + if (messages == NULL) + { + messages = new EntryMessageList(); + ci->Extend("cs_entrymsg", messages); + } - if (EntryMsg::MaxEntries && messages.size() >= EntryMsg::MaxEntries) + if (MaxEntries && messages->size() >= MaxEntries) source.Reply(_("The entry message list for \2%s\2 is full."), ci->name.c_str()); else { - messages.push_back(EntryMsg(source.u->nick, message)); - ci->Extend("cs_entrymsg", new ExtensibleItemRegular >(messages)); + messages->push_back(EntryMsg(ci, source.u->nick, message)); source.Reply(_("Entry message added to \2%s\2"), ci->name.c_str()); } } void DoDel(CommandSource &source, ChannelInfo *ci, const Anope::string &message) { - std::vector messages; + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); if (!message.is_pos_number_only()) source.Reply(("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str()); - else if (ci->GetExtRegular("cs_entrymsg", messages)) + else if (messages != NULL) { try { unsigned i = convertTo(message); - if (i > 0 && i <= messages.size()) + if (i > 0 && i <= messages->size()) { - messages.erase(messages.begin() + i - 1); - if (!messages.empty()) - ci->Extend("cs_entrymsg", new ExtensibleItemRegular >(messages)); - else + messages->erase(messages->begin() + i - 1); + if (messages->empty()) ci->Shrink("cs_entrymsg"); source.Reply(_("Entry message \2%i\2 for \2%s\2 deleted."), i, ci->name.c_str()); } @@ -165,58 +202,27 @@ class CSEntryMessage : public Module { this->SetAuthor("Anope"); - Implementation i[] = { I_OnJoinChannel, I_OnReload, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - - this->OnReload(); + + Serializable::Alloc.Register("EntryMsg"); } void OnJoinChannel(User *u, Channel *c) { if (u && c && c->ci && u->server->IsSynced()) { - std::vector messages; + EntryMessageList *messages = c->ci->GetExt("cs_entrymsg"); - if (c->ci->GetExtRegular("cs_entrymsg", messages)) - for (unsigned i = 0; i < messages.size(); ++i) - u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); + if (messages != NULL) + for (unsigned i = 0; i < messages->size(); ++i) + u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), (*messages)[i].message.c_str()); } } void OnReload() { ConfigReader config; - EntryMsg::MaxEntries = config.ReadInteger("cs_entrymsg", "maxentries", "5", 0, true); - } - - EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector ¶ms) - { - if (key.find("CS_ENTRYMSG_") == 0 && params.size() > 2) - { - Anope::string creator = params[0]; - time_t t = params[1].is_pos_number_only() ? convertTo(params[1]) : Anope::CurTime; - Anope::string message = params[2]; - for (unsigned j = 3; j < params.size(); ++j) - message += " " + params[j]; - - std::vector messages; - ci->GetExtRegular("cs_entrymsg", messages); - messages.push_back(EntryMsg(creator, message, t)); - ci->Extend("cs_entrymsg", new ExtensibleItemRegular >(messages)); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), ChannelInfo *ci) - { - std::vector messages; - if (ci->GetExtRegular("cs_entrymsg", messages)) - for (unsigned i = 0; i < messages.size(); ++i) - WriteMetadata("CS_ENTRYMSG_" + stringify(i), messages[i].creator + " " + stringify(messages[i].when) + " " + messages[i].message); + MaxEntries = config.ReadInteger("cs_entrymsg", "maxentries", "5", 0, true); } }; diff --git a/modules/commands/cs_flags.cpp b/modules/commands/cs_flags.cpp index 5ead6f2d9..1b790b5f1 100644 --- a/modules/commands/cs_flags.cpp +++ b/modules/commands/cs_flags.cpp @@ -15,7 +15,7 @@ static std::map defaultFlags; -class FlagsChanAccess : public ChanAccess +class FlagsChanAccess : public ChanAccess, public Serializable { public: std::set flags; @@ -65,6 +65,41 @@ class FlagsChanAccess : public ChanAccess return Anope::string(buffer.begin(), buffer.end()); } + + Anope::string serialize_name() { return "FlagsChanAccess"; } + serialized_data serialize() + { + serialized_data data; + + data["provider"] << this->provider->name; + data["ci"] << this->ci->name; + data["mask"] << this->mask; + data["creator"] << this->creator; + data["last_seen"].setType(Serialize::DT_INT) << this->last_seen; + data["created"].setType(Serialize::DT_INT) << this->created; + data["flags"] << this->Serialize(); + + return data; + } + + static void unserialize(SerializableBase::serialized_data &data) + { + service_reference aprovider(data["provider"].astr()); + ChannelInfo *ci = cs_findchan(data["ci"].astr()); + if (!aprovider || !ci) + return; + + FlagsChanAccess *access = new FlagsChanAccess(aprovider); + access->provider = aprovider; + access->ci = ci; + data["mask"] >> access->mask; + data["creator"] >> access->creator; + data["last_seen"] >> access->last_seen; + data["created"] >> access->created; + access->Unserialize(data["flags"].astr()); + + ci->AddAccess(access); + } }; class FlagsAccessProvider : public AccessProvider @@ -385,6 +420,8 @@ class CSFlags : public Module ModuleManager::Attach(i, this, 1); this->OnReload(); + + Serializable::Alloc.Register("FlagsChanAccess"); } void OnReload() diff --git a/modules/commands/cs_info.cpp b/modules/commands/cs_info.cpp index 5fc85666a..e7c8e039e 100644 --- a/modules/commands/cs_info.cpp +++ b/modules/commands/cs_info.cpp @@ -100,10 +100,9 @@ class CommandCSInfo : public Command } if (ci->HasFlag(CI_SUSPENDED)) { - Anope::string by, reason; - ci->GetExtRegular("suspend_by", by); - ci->GetExtRegular("suspend_reason", reason); - source.Reply(_(" Suspended: [%s] %s"), by.c_str(), !reason.empty() ? reason.c_str() : NO_REASON); + Anope::string *by = ci->GetExt("suspend_by"), *reason = ci->GetExt("suspend_reason"); + if (by != NULL) + source.Reply(_(" Suspended: [%s] %s"), by->c_str(), (reason && !reason->empty() ? reason->c_str() : NO_REASON)); } FOREACH_MOD(I_OnChanInfo, OnChanInfo(source, ci, show_all)); diff --git a/modules/commands/cs_seen.cpp b/modules/commands/cs_seen.cpp index d466acca4..f828e181d 100644 --- a/modules/commands/cs_seen.cpp +++ b/modules/commands/cs_seen.cpp @@ -19,26 +19,55 @@ enum TypeInfo NEW, NICK_TO, NICK_FROM, JOIN, PART, QUIT, KICK }; -struct SeenInfo +struct SeenInfo; +typedef Anope::insensitive_map database_map; +database_map database; + +struct SeenInfo : Serializable { + Anope::string nick; Anope::string vhost; TypeInfo type; Anope::string nick2; // for nickchanges and kicks Anope::string channel; // for join/part/kick Anope::string message; // for part/kick/quit time_t last; // the time when the user was last seen -}; -class ModuleConfigClass -{ - public: - time_t purgetime; - time_t expiretimeout; + serialized_data serialize() + { + serialized_data data; + + data["nick"] << nick; + data["vhost"] << vhost; + data["type"] << type; + data["nick2"] << nick2; + data["channel"] << channel; + data["message"] << message; + data["last"].setType(Serialize::DT_INT) << last; + + return data; + } + + static void unserialize(serialized_data &data) + { + SeenInfo *s = new SeenInfo(); + + data["nick"] >> s->nick; + data["vhost"] >> s->vhost; + unsigned int n; + data["type"] >> n; + s->type = static_cast(n); + data["nick2"] >> s->nick2; + data["channel"] >> s->channel; + data["message"] >> s->message; + data["last"] >> s->last; + + database[s->nick] = s; + } }; -ModuleConfigClass ModuleConfig; -typedef Anope::insensitive_map database_map; -database_map database; +static time_t purgetime; +static time_t expiretimeout; static SeenInfo *FindInfo(const Anope::string &nick) { @@ -262,7 +291,7 @@ class DataBasePurger : public CallBack database_map::iterator cur = it; ++it; - if ((Anope::CurTime - cur->second->last) > ModuleConfig.purgetime) + if ((Anope::CurTime - cur->second->last) > purgetime) { Log(LOG_DEBUG) << cur->first << " was last seen " << do_strftime(cur->second->last) << ", purging entry"; delete cur->second; @@ -289,48 +318,55 @@ class CSSeen : public Module I_OnUserQuit, I_OnJoinChannel, I_OnPartChannel, - I_OnUserKicked, - I_OnDatabaseRead, - I_OnDatabaseWrite }; + I_OnUserKicked }; ModuleManager::Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation)); - OnReload(); + + Serializable::Alloc.Register("SeenInfo"); } + void OnReload() { ConfigReader config; - ModuleConfig.purgetime = dotime(config.ReadValue("cs_seen", "purgetime", "30d", 0)); - ModuleConfig.expiretimeout = dotime(config.ReadValue("cs_seen", "expiretimeout", "1d", 0)); + purgetime = dotime(config.ReadValue("cs_seen", "purgetime", "30d", 0)); + expiretimeout = dotime(config.ReadValue("cs_seen", "expiretimeout", "1d", 0)); - if (purger.GetSecs() != ModuleConfig.expiretimeout) - purger.SetSecs(ModuleConfig.expiretimeout); + if (purger.GetSecs() != expiretimeout) + purger.SetSecs(expiretimeout); } + void OnUserConnect(User *u) { UpdateUser(u, NEW, u->nick, "", "", ""); } + void OnUserNickChange(User *u, const Anope::string &oldnick) { UpdateUser(u, NICK_TO, oldnick, u->nick, "", ""); UpdateUser(u, NICK_FROM, u->nick, oldnick, "", ""); } + void OnUserQuit(User *u, const Anope::string &msg) { UpdateUser(u, QUIT, u->nick, "", "", msg); } + void OnJoinChannel(User *u, Channel *c) { UpdateUser(u, JOIN, u->nick, "", c->name, ""); } + void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) { UpdateUser(u, PART, u->nick, "", channel, msg); } + void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &msg) { UpdateUser(target, KICK, target->nick, source, c->name, msg); } + void UpdateUser(const User *u, const TypeInfo Type, const Anope::string &nick, const Anope::string &nick2, const Anope::string &channel, const Anope::string &message) { SeenInfo *info = FindInfo(nick); @@ -339,6 +375,7 @@ class CSSeen : public Module info = new SeenInfo; database.insert(std::pair(nick, info)); } + info->nick = nick; info->vhost = u->GetVIdent() + "@" + u->GetDisplayedHost(); info->type = Type; info->last = Anope::CurTime; @@ -346,82 +383,6 @@ class CSSeen : public Module info->channel = channel; info->message = message; } - - EventReturn OnDatabaseRead(const std::vector ¶ms) - { - if (params[0].equals_ci("SEEN") && (params.size() >= 5)) - { - SeenInfo *info = new SeenInfo; - database.insert(std::pair(params[1], info)); - info->vhost = params[2]; - info->last = params[3].is_pos_number_only() ? convertTo(params[3]) : 0 ; - if (params[4].equals_ci("NEW")) - { - info->type = NEW; - } - else if (params[4].equals_ci("NICK_TO") && params.size() == 6) - { - info->type = NICK_TO; - info->nick2 = params[5]; - } - else if (params[4].equals_ci("NICK_FROM") && params.size() == 6) - { - info->type = NICK_FROM; - info->nick2 = params[5]; - } - else if (params[4].equals_ci("JOIN") && params.size() == 6) - { - info->type = JOIN; - info->channel = params[5]; - } - else if (params[4].equals_ci("PART") && params.size() == 7) - { - info->type = PART; - info->channel = params[5]; - info->message = params[6]; - } - else if (params[4].equals_ci("QUIT") && params.size() == 6) - { - info->type = QUIT; - info->message = params[5]; - } - else if (params[4].equals_ci("KICK") && params.size() == 8) - { - info->type = KICK; - info->nick2 = params[5]; - info->channel = params[6]; - info->message = params[7]; - } - return EVENT_STOP; - } - return EVENT_CONTINUE; - } - void OnDatabaseWrite(void (*Write)(const Anope::string &)) - { - for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end; ++it) - { - std::stringstream buf; - buf << "SEEN " << it->first.c_str() << " " << it->second->vhost << " " << it->second->last << " "; - switch (it->second->type) - { - case NEW: - buf << "NEW"; break; - case NICK_TO: - buf << "NICK_TO " << it->second->nick2; break; - case NICK_FROM: - buf << "NICK_FROM " << it->second->nick2; break; - case JOIN: - buf << "JOIN " << it->second->channel; break; - case PART: - buf << "PART " << it->second->channel << " :" << it->second->message; break; - case QUIT: - buf << "QUIT :" << it->second->message; break; - case KICK: - buf << "KICK " << it->second->nick2 << " " << it->second->channel << " :" << it->second->message; break; - } - Write(buf.str()); - } - } }; MODULE_INIT(CSSeen) diff --git a/modules/commands/cs_set_misc.cpp b/modules/commands/cs_set_misc.cpp index 61c8c163b..0757e965b 100644 --- a/modules/commands/cs_set_misc.cpp +++ b/modules/commands/cs_set_misc.cpp @@ -12,6 +12,37 @@ #include "module.h" +struct MiscData : Anope::string, ExtensibleItem, Serializable +{ + ChannelInfo *ci; + Anope::string name; + Anope::string data; + + MiscData(ChannelInfo *c, const Anope::string &n, const Anope::string &d) : ci(c), name(n), data(d) + { + } + + serialized_data serialize() + { + serialized_data sdata; + + sdata["ci"] << this->ci->name; + sdata["name"] << this->name; + sdata["data"] << this->data; + + return sdata; + } + + static void unserialize(serialized_data &data) + { + ChannelInfo *ci = cs_findchan(data["ci"].astr()); + if (ci == NULL) + return; + + ci->Extend(data["name"].astr(), new MiscData(ci, data["name"].astr(), data["data"].astr())); + } +}; + class CommandCSSetMisc : public Command { public: @@ -34,10 +65,11 @@ class CommandCSSetMisc : public Command return; } - ci->Shrink("cs_set_misc:" + source.command.replace_all_cs(" ", "_")); + Anope::string key = "cs_set_misc:" + source.command.replace_all_cs(" ", "_"); + ci->Shrink(key); if (params.size() > 1) { - ci->Extend("cs_set_misc:" + source.command.replace_all_cs(" ", "_"), new ExtensibleItemRegular(params[1])); + ci->Extend(key, new MiscData(ci, key, params[1])); source.Reply(CHAN_SETTING_CHANGED, source.command.c_str(), ci->name.c_str(), params[1].c_str()); } else @@ -64,9 +96,10 @@ class CSSetMisc : public Module { this->SetAuthor("Anope"); - Implementation i[] = { I_OnChanInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; + Implementation i[] = { I_OnChanInfo }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + Serializable::Alloc.Register("CSMisc"); } void OnChanInfo(CommandSource &source, ChannelInfo *ci, bool ShowHidden) @@ -79,35 +112,11 @@ class CSSetMisc : public Module if (list[i].find("cs_set_misc:") != 0) continue; - Anope::string value; - if (ci->GetExtRegular(list[i], value)) - source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), value.c_str()); + MiscData *data = ci->GetExt(list[i]); + if (data != NULL) + source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), data->data.c_str()); } } - - void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), ChannelInfo *ci) - { - std::deque list; - ci->GetExtList(list); - - for (unsigned i = 0; i < list.size(); ++i) - { - if (list[i].find("cs_set_misc:") != 0) - continue; - - Anope::string value; - if (ci->GetExtRegular(list[i], value)) - WriteMetadata(list[i], ":" + value); - } - } - - EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector ¶ms) - { - if (key.find("cs_set_misc:") == 0) - ci->Extend(key, new ExtensibleItemRegular(params[0])); - - return EVENT_CONTINUE; - } }; MODULE_INIT(CSSetMisc) diff --git a/modules/commands/cs_suspend.cpp b/modules/commands/cs_suspend.cpp index d9f846d71..d59931b45 100644 --- a/modules/commands/cs_suspend.cpp +++ b/modules/commands/cs_suspend.cpp @@ -45,9 +45,9 @@ class CommandCSSuspend : public Command } ci->SetFlag(CI_SUSPENDED); - ci->Extend("suspend_by", new ExtensibleItemRegular(u->nick)); + ci->Extend("suspend_by", new ExtensibleString(u->nick)); if (!reason.empty()) - ci->Extend("suspend_reason", new ExtensibleItemRegular(reason)); + ci->Extend("suspend_reason", new ExtensibleString(reason)); if (ci->c) { @@ -113,10 +113,9 @@ class CommandCSUnSuspend : public Command return; } - Anope::string by, reason; - ci->GetExtRegular("suspend_by", by); - ci->GetExtRegular("suspend_reason", reason); - Log(LOG_ADMIN, u, this, ci) << " which was suspended by " << by << " for: " << (!reason.empty() ? reason : "No reason"); + Anope::string *by = ci->GetExt("suspend_by"), *reason = ci->GetExt("suspend_reason"); + if (by != NULL) + Log(LOG_ADMIN, u, this, ci) << " which was suspended by " << *by << " for: " << (reason && !reason->empty() ? *reason : "No reason"); ci->UnsetFlag(CI_SUSPENDED); ci->Shrink("suspend_by"); diff --git a/modules/commands/cs_xop.cpp b/modules/commands/cs_xop.cpp index b2aaffde6..e132f19f5 100644 --- a/modules/commands/cs_xop.cpp +++ b/modules/commands/cs_xop.cpp @@ -90,7 +90,7 @@ static struct XOPAccess } }; -class XOPChanAccess : public ChanAccess +class XOPChanAccess : public ChanAccess, public Serializable { public: XOPType type; @@ -188,6 +188,41 @@ class XOPChanAccess : public ChanAccess return max; } } + + Anope::string serialize_name() { return "XOPChanAccess"; } + serialized_data serialize() + { + serialized_data data; + + data["provider"] << this->provider->name; + data["ci"] << this->ci->name; + data["mask"] << this->mask; + data["creator"] << this->creator; + data["last_seen"] << this->last_seen; + data["created"] << this->created; + data["type"] << this->Serialize(); + + return data; + } + + static void unserialize(SerializableBase::serialized_data &data) + { + service_reference aprovider(data["provider"].astr()); + ChannelInfo *ci = cs_findchan(data["ci"].astr()); + if (!aprovider || !ci) + return; + + XOPChanAccess *access = new XOPChanAccess(aprovider); + access->provider = aprovider; + access->ci = ci; + data["mask"] >> access->mask; + data["creator"] >> access->creator; + data["last_seen"] >> access->last_seen; + data["created"] >> access->created; + access->Unserialize(data["type"].astr()); + + ci->AddAccess(access); + } }; class XOPAccessProvider : public AccessProvider @@ -868,6 +903,7 @@ class CSXOP : public Module { this->SetAuthor("Anope"); + Serializable::Alloc.Register("XOPChanAccess"); } }; diff --git a/modules/commands/hs_request.cpp b/modules/commands/hs_request.cpp index 3d330bc2a..82bba1bbc 100644 --- a/modules/commands/hs_request.cpp +++ b/modules/commands/hs_request.cpp @@ -21,18 +21,42 @@ static bool HSRequestMemoUser = false; static bool HSRequestMemoOper = false; -void my_add_host_request(const Anope::string &nick, const Anope::string &vIdent, const Anope::string &vhost, const Anope::string &creator, time_t tmp_time); void req_send_memos(CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost); -struct HostRequest +struct HostRequest : ExtensibleItem, Serializable { + Anope::string nick; Anope::string ident; Anope::string host; time_t time; -}; -typedef std::map > RequestMap; -RequestMap Requests; + serialized_data serialize() + { + serialized_data data; + + data["nick"] << this->nick; + data["ident"] << this->ident; + data["host"] << this->host; + data["time"].setType(Serialize::DT_INT) << this->time; + + return data; + } + + static void unserialize(serialized_data &data) + { + NickAlias *na = findnick(data["nick"].astr()); + if (na == NULL) + return; + + HostRequest *req = new HostRequest; + req->nick = na->nick; + data["ident"] >> req->ident; + data["host"] >> req->host; + data["time"] >> req->time; + + na->Extend("hs_request", req); + } +}; class CommandHSRequest : public Command { @@ -54,6 +78,12 @@ class CommandHSRequest : public Command { User *u = source.u; + NickAlias *na = findnick(u->nick); + if (na == NULL) + na = findnick(u->Account()->display); + if (!na) + return; + Anope::string rawhostmask = params[0]; Anope::string user, host; @@ -111,7 +141,14 @@ class CommandHSRequest : public Command u->lastmemosend = Anope::CurTime; return; } - my_add_host_request(u->nick, user, host, u->nick, Anope::CurTime); + + + HostRequest *req = new HostRequest; + req->nick = u->nick; + req->ident = user; + req->host = host; + req->time = Anope::CurTime; + na->Extend("hs_request", req); source.Reply(_("Your vHost has been requested")); req_send_memos(source, user, host); @@ -147,29 +184,21 @@ class CommandHSActivate : public Command const Anope::string &nick = params[0]; NickAlias *na = findnick(nick); - if (na) + HostRequest *req = na ? na->GetExt("hs_request") : NULL; + if (req) { - RequestMap::iterator it = Requests.find(na->nick); - if (it != Requests.end()) - { - na->hostinfo.SetVhost(it->second->ident, it->second->host, u->nick, it->second->time); - FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); + na->hostinfo.SetVhost(req->ident, req->host, u->nick, req->time); + FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); - if (HSRequestMemoUser && memoserv) - memoserv->Send(Config->HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true); + if (HSRequestMemoUser && memoserv) + memoserv->Send(Config->HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true); - source.Reply(_("vHost for %s has been activated"), na->nick.c_str()); - Log(LOG_COMMAND, u, this, NULL) << "for " << na->nick << " for vhost " << (!it->second->ident.empty() ? it->second->ident + "@" : "") << it->second->host; - delete it->second; - Requests.erase(it); - } - else - source.Reply(_("No request for nick %s found."), nick.c_str()); + source.Reply(_("vHost for %s has been activated"), na->nick.c_str()); + Log(LOG_COMMAND, u, this, NULL) << "for " << na->nick << " for vhost " << (!req->ident.empty() ? req->ident + "@" : "") << req->host; + na->Shrink("hs_request"); } else - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - - return; + source.Reply(_("No request for nick %s found."), nick.c_str()); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -199,11 +228,11 @@ class CommandHSReject : public Command const Anope::string &nick = params[0]; const Anope::string &reason = params.size() > 1 ? params[1] : ""; - RequestMap::iterator it = Requests.find(nick); - if (it != Requests.end()) + NickAlias *na = findnick(nick); + HostRequest *req = na ? na->GetExt("hs_request") : NULL; + if (req) { - delete it->second; - Requests.erase(it); + na->Shrink("hs_request"); if (HSRequestMemoUser && memoserv) { @@ -246,9 +275,13 @@ class HSListBase : public Command int from = 0, to = 0; unsigned display_counter = 0; - for (RequestMap::iterator it = Requests.begin(), it_end = Requests.end(); it != it_end; ++it) + for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it) { - HostRequest *hr = it->second; + NickAlias *na = it->second; + HostRequest *hr = na->GetExt("hs_request"); + if (!hr) + continue; + if (((counter >= from && counter <= to) || (!from && !to)) && display_counter < Config->NSListMax) { ++display_counter; @@ -260,8 +293,6 @@ class HSListBase : public Command ++counter; } source.Reply(_("Displayed all records (Count: \002%d\002)"), display_counter); - - return; } public: HSListBase(Module *creator, const Anope::string &cmd, int min, int max) : Command(creator, cmd, min, max) @@ -306,8 +337,7 @@ class HSRequest : public Module { this->SetAuthor("Anope"); - - Implementation i[] = { I_OnDelNick, I_OnDatabaseRead, I_OnDatabaseWrite, I_OnReload }; + Implementation i[] = { I_OnReload }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); this->OnReload(); @@ -315,47 +345,8 @@ class HSRequest : public Module ~HSRequest() { - /* Clean up all open host requests */ - while (!Requests.empty()) - { - delete Requests.begin()->second; - Requests.erase(Requests.begin()); - } - } - - void OnDelNick(NickAlias *na) - { - RequestMap::iterator it = Requests.find(na->nick); - - if (it != Requests.end()) - { - delete it->second; - Requests.erase(it); - } - } - - EventReturn OnDatabaseRead(const std::vector ¶ms) - { - if (params[0].equals_ci("HS_REQUEST") && params.size() >= 5) - { - Anope::string vident = params[2].equals_ci("(null)") ? "" : params[2]; - my_add_host_request(params[1], vident, params[3], params[1], params[4].is_pos_number_only() ? convertTo(params[4]) : 0); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - void OnDatabaseWrite(void (*Write)(const Anope::string &)) - { - for (RequestMap::iterator it = Requests.begin(), it_end = Requests.end(); it != it_end; ++it) - { - HostRequest *hr = it->second; - std::stringstream buf; - buf << "HS_REQUEST " << it->first << " " << (hr->ident.empty() ? "(null)" : hr->ident) << " " << hr->host << " " << hr->time; - Write(buf.str()); - } + for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it) + it->second->Shrink("hs_request"); } void OnReload() @@ -393,28 +384,4 @@ void req_send_memos(CommandSource &source, const Anope::string &vIdent, const An } } -void my_add_host_request(const Anope::string &nick, const Anope::string &vIdent, const Anope::string &vhost, const Anope::string &creator, time_t tmp_time) -{ - HostRequest *hr = new HostRequest; - hr->ident = vIdent; - hr->host = vhost; - hr->time = tmp_time; - RequestMap::iterator it = Requests.find(nick); - if (it != Requests.end()) - { - delete it->second; - Requests.erase(it); - } - Requests.insert(std::make_pair(nick, hr)); -} - -void my_load_config() -{ - ConfigReader config; - HSRequestMemoUser = config.ReadFlag("hs_request", "memouser", "no", 0); - HSRequestMemoOper = config.ReadFlag("hs_request", "memooper", "no", 0); - - Log(LOG_DEBUG) << "[hs_request] Set config vars: MemoUser=" << HSRequestMemoUser << " MemoOper=" << HSRequestMemoOper; -} - MODULE_INIT(HSRequest) diff --git a/modules/commands/ns_ajoin.cpp b/modules/commands/ns_ajoin.cpp index bed0442d7..d7bde685e 100644 --- a/modules/commands/ns_ajoin.cpp +++ b/modules/commands/ns_ajoin.cpp @@ -13,66 +13,113 @@ #include "module.h" +struct AJoinList : std::vector >, ExtensibleItem, Serializable +{ + NickCore *nc; + + AJoinList(NickCore *n) : nc(n) { } + + serialized_data serialize() + { + serialized_data sd; + + sd["nc"] << this->nc->display; + Anope::string channels; + for (unsigned i = 0; i < this->size(); ++i) + channels += this->at(i).first + "," + this->at(i).second; + sd["channels"] << channels; + + return sd; + } + + static void unserialize(serialized_data &sd) + { + NickCore *nc = findcore(sd["nc"].astr()); + if (nc == NULL) + return; + + AJoinList *aj = new AJoinList(nc); + nc->Extend("ns_ajoin_channels", aj); + + Anope::string token; + spacesepstream ssep(sd["channels"].astr()); + while (ssep.GetToken(token)) + { + size_t c = token.find(','); + Anope::string chan, key; + if (c == Anope::string::npos) + chan = token; + else + { + chan = token.substr(0, c); + key = token.substr(c + 1); + } + + aj->push_back(std::make_pair(chan, key)); + } + } +}; + class CommandNSAJoin : public Command { void DoList(CommandSource &source, const std::vector ¶ms) { - std::vector > channels; - source.u->Account()->GetExtRegular("ns_ajoin_channels", channels); + AJoinList *channels = source.u->Account()->GetExt("ns_ajoin_channels"); - if (channels.empty()) + if (channels == NULL || channels->empty()) source.Reply(_("Your auto join list is empty.")); else { source.Reply(_("Your auto join list:\n" " Num Channel Key")); - for (unsigned i = 0; i < channels.size(); ++i) - source.Reply(" %3d %-12s %s", i + 1, channels[i].first.c_str(), channels[i].second.c_str()); + for (unsigned i = 0; i < channels->size(); ++i) + source.Reply(" %3d %-12s %s", i + 1, channels->at(i).first.c_str(), channels->at(i).second.c_str()); } } void DoAdd(CommandSource &source, const std::vector ¶ms) { - std::vector > channels; - source.u->Account()->GetExtRegular("ns_ajoin_channels", channels); + AJoinList *channels = source.u->Account()->GetExt("ns_ajoin_channels"); + if (channels == NULL) + { + channels = new AJoinList(source.u->Account()); + source.u->Account()->Extend("ns_ajoin_channels", channels); + } - unsigned i; - for (i = 0; i < channels.size(); ++i) - if (channels[i].first.equals_ci(params[1])) - break; + unsigned i = 0; + if (channels != NULL) + for (; i < channels->size(); ++i) + if (channels->at(i).first.equals_ci(params[1])) + break; - if (channels.size() >= Config->AJoinMax) + if (channels->size() >= Config->AJoinMax) source.Reply(_("Your auto join list is full.")); - else if (i != channels.size()) + else if (i != channels->size()) source.Reply(_("%s is already on your auto join list."), params[1].c_str()); else if (ircdproto->IsChannelValid(params[1]) == false) source.Reply(CHAN_X_INVALID, params[1].c_str()); else { - channels.push_back(std::make_pair(params[1], params.size() > 2 ? params[2] : "")); + channels->push_back(std::make_pair(params[1], params.size() > 2 ? params[2] : "")); source.Reply(_("Added %s to your auto join list."), params[1].c_str()); - source.u->Account()->Extend("ns_ajoin_channels", new ExtensibleItemRegular > >(channels)); } } void DoDel(CommandSource &source, const std::vector ¶ms) { - std::vector > channels; - source.u->Account()->GetExtRegular("ns_ajoin_channels", channels); + AJoinList *channels = source.u->Account()->GetExt("ns_ajoin_channels"); - unsigned i; - for (i = 0; i < channels.size(); ++i) - if (channels[i].first.equals_ci(params[1])) - break; + unsigned i = 0; + if (channels != NULL) + for (; i < channels->size(); ++i) + if (channels->at(i).first.equals_ci(params[1])) + break; - if (i == channels.size()) + if (channels == NULL || i == channels->size()) source.Reply(_("%s was not found on your auto join list."), params[1].c_str()); else { - channels.erase(channels.begin() + i); - source.u->Account()->Extend("ns_ajoin_channels", new ExtensibleItemRegular > >(channels)); + channels->erase(channels->begin() + i); source.Reply(_("%s was removed from your auto join list."), params[1].c_str()); } } @@ -120,25 +167,28 @@ class NSAJoin : public Module { this->SetAuthor("Anope"); - - Implementation i[] = { I_OnNickIdentify, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; + Implementation i[] = { I_OnNickIdentify }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + + Serializable::Alloc.Register("AJoinList"); } void OnNickIdentify(User *u) { - std::vector > channels; - u->Account()->GetExtRegular("ns_ajoin_channels", channels); + AJoinList *channels = u->Account()->GetExt("ns_ajoin_channels"); + + if (channels == NULL) + return; - for (unsigned i = 0; i < channels.size(); ++i) + for (unsigned i = 0; i < channels->size(); ++i) { - Channel *c = findchan(channels[i].first); - ChannelInfo *ci = c != NULL ? c->ci : cs_findchan(channels[i].first); + Channel *c = findchan(channels->at(i).first); + ChannelInfo *ci = c != NULL ? c->ci : cs_findchan(channels->at(i).first); if (c == NULL && ci != NULL) c = ci->c; bool need_invite = false; - Anope::string key = channels[i].second; + Anope::string key = channels->at(i).second; if (ci != NULL) { @@ -192,54 +242,12 @@ class NSAJoin : public Module BotInfo *bi = findbot(Config->NickServ); if (!bi || !ci->AccessFor(u).HasPriv("INVITE")) continue; - ircdproto->SendInvite(bi, channels[i].first, u->nick); + ircdproto->SendInvite(bi, channels->at(i).first, u->nick); } - ircdproto->SendSVSJoin(Config->NickServ, u->nick, channels[i].first, key); + ircdproto->SendSVSJoin(Config->NickServ, u->nick, channels->at(i).first, key); } } - - void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickCore *nc) - { - std::vector > channels; - nc->GetExtRegular("ns_ajoin_channels", channels); - - Anope::string chans; - for (unsigned i = 0; i < channels.size(); ++i) - chans += " " + channels[i].first + "," + channels[i].second; - - if (!chans.empty()) - { - chans.erase(chans.begin()); - WriteMetadata("NS_AJOIN", chans); - } - } - - EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector ¶ms) - { - if (key == "NS_AJOIN") - { - std::vector > channels; - nc->GetExtRegular("ns_ajoin_channels", channels); - - for (unsigned i = 0; i < params.size(); ++i) - { - Anope::string chan, chankey; - commasepstream sep(params[i]); - sep.GetToken(chan); - sep.GetToken(chankey); - - channels.push_back(std::make_pair(chan, chankey)); - } - - nc->Extend("ns_ajoin_channels", new ExtensibleItemRegular > >(channels)); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } }; MODULE_INIT(NSAJoin) diff --git a/modules/commands/ns_register.cpp b/modules/commands/ns_register.cpp index aced3046e..acfcd2acd 100644 --- a/modules/commands/ns_register.cpp +++ b/modules/commands/ns_register.cpp @@ -46,8 +46,8 @@ class CommandNSConfirm : public Command } else if (u->Account()) { - Anope::string code; - if (u->Account()->GetExtRegular("ns_register_passcode", code) && code == passcode) + Anope::string *code = u->Account()->GetExt("ns_register_passcode"); + if (code != NULL && *code == passcode) { u->Account()->Shrink("ns_register_passcode"); Log(LOG_COMMAND, u, this) << "to confirm their email"; @@ -320,8 +320,9 @@ class NSRegister : public Module static bool SendRegmail(User *u, NickAlias *na, BotInfo *bi) { - Anope::string code; - if (na->nc->GetExtRegular("ns_register_passcode", code) == false) + Anope::string *code = na->nc->GetExt("ns_register_passcode"); + Anope::string codebuf; + if (code == NULL) { int chars[] = { ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', @@ -332,20 +333,22 @@ static bool SendRegmail(User *u, NickAlias *na, BotInfo *bi) }; int idx, min = 1, max = 62; for (idx = 0; idx < 9; ++idx) - code += chars[1 + static_cast((static_cast(max - min)) * getrandom16() / 65536.0) + min]; - na->nc->Extend("ns_register_passcode", new ExtensibleItemRegular(code)); + codebuf += chars[1 + static_cast((static_cast(max - min)) * getrandom16() / 65536.0) + min]; + na->nc->Extend("ns_register_passcode", new ExtensibleString(codebuf)); } + else + codebuf = *code; Anope::string subject = translate(na->nc, Config->MailRegistrationSubject.c_str()); Anope::string message = translate(na->nc, Config->MailRegistrationMessage.c_str()); subject = subject.replace_all_cs("%n", na->nick); subject = subject.replace_all_cs("%N", Config->NetworkName); - subject = subject.replace_all_cs("%c", code); + subject = subject.replace_all_cs("%c", codebuf); message = message.replace_all_cs("%n", na->nick); message = message.replace_all_cs("%N", Config->NetworkName); - message = message.replace_all_cs("%c", code); + message = message.replace_all_cs("%c", codebuf); return Mail(u, na->nc, bi, subject, message); } diff --git a/modules/commands/ns_resetpass.cpp b/modules/commands/ns_resetpass.cpp index 153691cdf..3cced2de2 100644 --- a/modules/commands/ns_resetpass.cpp +++ b/modules/commands/ns_resetpass.cpp @@ -56,6 +56,12 @@ class CommandNSResetPass : public Command } }; +struct ResetInfo : ExtensibleItem +{ + Anope::string code; + time_t time; +}; + class NSResetPass : public Module { CommandNSResetPass commandnsresetpass; @@ -80,28 +86,25 @@ class NSResetPass : public Module User *u = source.u; NickAlias *na = findnick(params[0]); - time_t t; - Anope::string c; - if (na && na->nc->GetExtRegular("ns_resetpass_code", c) && na->nc->GetExtRegular("ns_resetpass_time", t)) + ResetInfo *ri = na ? na->nc->GetExt("ns_resetpass") : NULL; + if (na && ri) { const Anope::string &passcode = params[1]; - if (t < Anope::CurTime - 3600) + if (ri->time < Anope::CurTime - 3600) { - na->nc->Shrink("ns_resetpass_code"); - na->nc->Shrink("ns_resetpass_time"); + na->nc->Shrink("ns_resetpass"); source.Reply(_("Your password reset request has expired.")); } - else if (passcode.equals_cs(c)) + else if (passcode.equals_cs(ri->code)) { - na->nc->Shrink("ns_resetpass_code"); - na->nc->Shrink("ns_resetpass_time"); + na->nc->Shrink("ns_resetpass"); Log(LOG_COMMAND, u, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify to " << na->nick; na->nc->UnsetFlag(NI_UNCONFIRMED); u->Identify(na); - source.Reply(_("You are now identified for your nick. Change your passwor now.")); + source.Reply(_("You are now identified for your nick. Change your password now.")); } else @@ -142,8 +145,10 @@ static bool SendResetEmail(User *u, NickAlias *na, BotInfo *bi) message = message.replace_all_cs("%N", Config->NetworkName); message = message.replace_all_cs("%c", passcode); - na->nc->Extend("ns_resetpass_code", new ExtensibleItemRegular(passcode)); - na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular(Anope::CurTime)); + ResetInfo *ri = new ResetInfo; + ri->code = passcode; + ri->time = Anope::CurTime; + na->nc->Extend("ns_resetpass", ri); return Mail(u, na->nc, bi, subject, message); } diff --git a/modules/commands/ns_set_email.cpp b/modules/commands/ns_set_email.cpp index 175ed5b9e..e86338075 100644 --- a/modules/commands/ns_set_email.cpp +++ b/modules/commands/ns_set_email.cpp @@ -26,7 +26,7 @@ static bool SendConfirmMail(User *u, BotInfo *bi) Anope::string code; for (idx = 0; idx < 9; ++idx) code += chars[1 + static_cast((static_cast(max - min)) * getrandom16() / 65536.0) + min]; - u->Account()->Extend("ns_set_email_passcode", new ExtensibleItemRegular(code)); + u->Account()->Extend("ns_set_email_passcode", new ExtensibleString(code)); Anope::string subject = Config->MailEmailchangeSubject; Anope::string message = Config->MailEmailchangeMessage; @@ -80,7 +80,7 @@ class CommandNSSetEmail : public Command if (!param.empty() && Config->NSConfirmEmailChanges && !u->IsServicesOper()) { - u->Account()->Extend("ns_set_email", new ExtensibleItemRegular(param)); + u->Account()->Extend("ns_set_email", new ExtensibleString(param)); Anope::string old = u->Account()->email; u->Account()->email = param; if (SendConfirmMail(u, source.owner)) @@ -163,12 +163,12 @@ class NSSetEmail : public Module User *u = source.u; if (command->name == "nickserv/confirm" && !params.empty() && u->IsIdentified()) { - Anope::string new_email, passcode; - if (u->Account()->GetExtRegular("ns_set_email", new_email) && u->Account()->GetExtRegular("ns_set_email_passcode", passcode)) + Anope::string *new_email = u->Account()->GetExt("ns_set_email"), *passcode = u->Account()->GetExt("ns_set_email_passcode"); + if (new_email && passcode) { - if (params[0] == passcode) + if (params[0] == *passcode) { - u->Account()->email = new_email; + u->Account()->email = *new_email; Log(LOG_COMMAND, u, command) << "to confirm their email address change to " << u->Account()->email; source.Reply(_("Your email address has been changed to \002%s\002."), u->Account()->email.c_str()); u->Account()->Shrink("ns_set_email"); diff --git a/modules/commands/ns_set_misc.cpp b/modules/commands/ns_set_misc.cpp index c511159d2..a9b93083d 100644 --- a/modules/commands/ns_set_misc.cpp +++ b/modules/commands/ns_set_misc.cpp @@ -13,6 +13,38 @@ #include "module.h" +struct MiscData : Anope::string, ExtensibleItem, Serializable +{ + NickCore *nc; + Anope::string name; + Anope::string data; + + MiscData(NickCore *ncore, const Anope::string &n, const Anope::string &d) : nc(ncore), name(n), data(d) + { + } + + serialized_data serialize() + { + serialized_data sdata; + + sdata["nc"] << this->nc->display; + sdata["name"] << this->name; + sdata["data"] << this->data; + + return sdata; + } + + static void unserialize(serialized_data &data) + { + NickCore *nc = findcore(data["nc"].astr()); + if (nc == NULL) + return; + + nc->Extend(data["name"].astr(), new MiscData(nc, data["name"].astr(), data["data"].astr())); + } +}; + + class CommandNSSetMisc : public Command { public: @@ -31,10 +63,11 @@ class CommandNSSetMisc : public Command } NickCore *nc = na->nc; - nc->Shrink("ns_set_misc:" + source.command.replace_all_cs(" ", "_")); + Anope::string key = "ns_set_misc:" + source.command.replace_all_cs(" ", "_"); + nc->Shrink(key); if (!param.empty()) { - nc->Extend("ns_set_misc:" + source.command.replace_all_cs(" ", "_"), new ExtensibleItemRegular(param)); + nc->Extend(key, new MiscData(nc, key, param)); source.Reply(CHAN_SETTING_CHANGED, source.command.c_str(), nc->display.c_str(), param.c_str()); } else @@ -75,9 +108,10 @@ class NSSetMisc : public Module { this->SetAuthor("Anope"); - Implementation i[] = { I_OnNickInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; + Implementation i[] = { I_OnNickInfo }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + Serializable::Alloc.Register("NSMisc"); } void OnNickInfo(CommandSource &source, NickAlias *na, bool ShowHidden) @@ -90,35 +124,11 @@ class NSSetMisc : public Module if (list[i].find("ns_set_misc:") != 0) continue; - Anope::string value; - if (na->nc->GetExtRegular(list[i], value)) - source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), value.c_str()); - } - } - - void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickCore *nc) - { - std::deque list; - nc->GetExtList(list); - - for (unsigned i = 0; i < list.size(); ++i) - { - if (list[i].find("ns_set_misc:") != 0) - continue; - - Anope::string value; - if (nc->GetExtRegular(list[i], value)) - WriteMetadata(list[i], ":" + value); + MiscData *data = na->nc->GetExt(list[i]); + if (data) + source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), data->data.c_str()); } } - - EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector ¶ms) - { - if (key.find("ns_set_misc:") == 0) - nc->Extend(key, new ExtensibleItemRegular(params[0])); - - return EVENT_CONTINUE; - } }; MODULE_INIT(NSSetMisc) diff --git a/modules/commands/os_forbid.cpp b/modules/commands/os_forbid.cpp index ef591923c..00731f703 100644 --- a/modules/commands/os_forbid.cpp +++ b/modules/commands/os_forbid.cpp @@ -214,10 +214,11 @@ class OSForbid : public Module { this->SetAuthor("Anope"); - Implementation i[] = { I_OnUserConnect, I_OnUserNickChange, I_OnJoinChannel, I_OnPreCommand, I_OnDatabaseWrite, I_OnDatabaseRead }; + Implementation i[] = { I_OnUserConnect, I_OnUserNickChange, I_OnJoinChannel, I_OnPreCommand }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + Serializable::Alloc.Register("Forbid"); } void OnUserConnect(dynamic_reference &u, bool &exempt) @@ -301,48 +302,6 @@ class OSForbid : public Module return EVENT_CONTINUE; } - - void OnDatabaseWrite(void (*Write)(const Anope::string &)) - { - std::vector forbids = this->forbidService.GetForbids(); - for (unsigned i = 0; i < forbids.size(); ++i) - { - ForbidData *f = forbids[i]; - Anope::string ftype; - if (f->type == FT_NICK) - ftype = "NICK"; - else if (f->type == FT_CHAN) - ftype = "CHAN"; - else if (f->type == FT_EMAIL) - ftype = "EMAIL"; - Write("FORBID " + f->mask + " " + f->creator + " " + stringify(f->created) + " " + stringify(f->expires) + " " + ftype + " " + f->reason); - } - } - - EventReturn OnDatabaseRead(const std::vector ¶ms) - { - if (params.size() > 5 && params[0] == "FORBID") - { - ForbidData *f = new ForbidData(); - f->mask = params[1]; - f->creator = params[2]; - f->created = convertTo(params[3]); - f->expires = convertTo(params[4]); - if (params[5] == "NICK") - f->type = FT_NICK; - else if (params[5] == "CHAN") - f->type = FT_CHAN; - else if (params[5] == "EMAIL") - f->type = FT_EMAIL; - else - f->type = FT_NONE; - f->reason = params.size() > 6 ? params[6] : ""; - - this->forbidService.AddForbid(f); - } - - return EVENT_CONTINUE; - } }; MODULE_INIT(OSForbid) diff --git a/modules/commands/os_forbid.h b/modules/commands/os_forbid.h index 06a936645..1aac412a3 100644 --- a/modules/commands/os_forbid.h +++ b/modules/commands/os_forbid.h @@ -9,7 +9,7 @@ enum ForbidType FT_EMAIL }; -struct ForbidData +struct ForbidData : Serializable { Anope::string mask; Anope::string creator; @@ -17,6 +17,9 @@ struct ForbidData time_t created; time_t expires; ForbidType type; + + serialized_data serialize(); + static void unserialize(serialized_data &data); }; class ForbidService : public Service @@ -33,5 +36,40 @@ class ForbidService : public Service virtual const std::vector &GetForbids() = 0; }; +static service_reference forbid_service("forbid"); + +SerializableBase::serialized_data ForbidData::serialize() +{ + serialized_data data; + + data["mask"] << this->mask; + data["creator"] << this->creator; + data["reason"] << this->reason; + data["created"] << this->created; + data["expires"] << this->expires; + data["type"] << this->type; + + return data; +} + +void ForbidData::unserialize(SerializableBase::serialized_data &data) +{ + if (!forbid_service) + return; + + ForbidData *fb = new ForbidData; + + data["mask"] >> fb->mask; + data["creator"] >> fb->creator; + data["reason"] >> fb->reason; + data["created"] >> fb->created; + data["expires"] >> fb->expires; + unsigned int t; + data["type"] >> t; + fb->type = static_cast(t); + + forbid_service->AddForbid(fb); +} + #endif diff --git a/modules/commands/os_ignore.cpp b/modules/commands/os_ignore.cpp index 5f2cbb195..6462284f5 100644 --- a/modules/commands/os_ignore.cpp +++ b/modules/commands/os_ignore.cpp @@ -17,7 +17,7 @@ class OSIgnoreService : public IgnoreService { public: - OSIgnoreService(Module *o, const Anope::string &n) : IgnoreService(o, n) { } + OSIgnoreService(Module *o) : IgnoreService(o) { } void AddIgnore(const Anope::string &mask, const Anope::string &creator, const Anope::string &reason, time_t delta = Anope::CurTime) { @@ -124,7 +124,7 @@ class OSIgnoreService : public IgnoreService } /* Check whether the entry has timed out */ - if (ign != ign_end)// && (*ign)->time && (*ign)->time <= Anope::CurTime) + if (ign != ign_end) { IgnoreData &id = *ign; @@ -146,7 +146,6 @@ class CommandOSIgnore : public Command private: void DoAdd(CommandSource &source, const std::vector ¶ms) { - service_reference ignore_service("ignore"); if (!ignore_service) return; @@ -181,7 +180,6 @@ class CommandOSIgnore : public Command void DoList(CommandSource &source) { - service_reference ignore_service("ignore"); if (!ignore_service) return; @@ -205,7 +203,6 @@ class CommandOSIgnore : public Command void DoDel(CommandSource &source, const std::vector ¶ms) { - service_reference ignore_service("ignore"); if (!ignore_service) return; @@ -222,7 +219,6 @@ class CommandOSIgnore : public Command void DoClear(CommandSource &source) { - service_reference ignore_service("ignore"); if (!ignore_service) return; @@ -287,53 +283,15 @@ class OSIgnore : public Module public: OSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), - osignoreservice(this, "ignore"), commandosignore(this) + osignoreservice(this), commandosignore(this) { this->SetAuthor("Anope"); - Implementation i[] = { I_OnDatabaseRead, I_OnDatabaseWrite, I_OnBotPrivmsg }; + Implementation i[] = { I_OnBotPrivmsg }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - } - - EventReturn OnDatabaseRead(const std::vector ¶ms) - { - if (params.size() >= 4 && params[0].equals_ci("OS") && params[1].equals_ci("IGNORE")) - { - service_reference ignore_service("ignore"); - if (ignore_service) - { - const Anope::string &mask = params[2]; - time_t time = params[3].is_pos_number_only() ? convertTo(params[3]) : 0; - const Anope::string &creator = params.size() > 4 ? params[4] : ""; - const Anope::string &reason = params.size() > 5 ? params[5] : ""; - ignore_service->AddIgnore(mask, creator, reason, time - Anope::CurTime); - - return EVENT_STOP; - } - } - - return EVENT_CONTINUE; - } - - void OnDatabaseWrite(void (*Write)(const Anope::string &)) - { - for (std::list::iterator ign = this->osignoreservice.GetIgnores().begin(), ign_end = this->osignoreservice.GetIgnores().end(); ign != ign_end; ) - { - if (ign->time && ign->time <= Anope::CurTime) - { - Log(LOG_DEBUG) << "[os_ignore] Expiring ignore entry " << ign->mask; - ign = this->osignoreservice.GetIgnores().erase(ign); - } - else - { - std::stringstream buf; - buf << "OS IGNORE " << ign->mask << " " << ign->time << " " << ign->creator << " :" << ign->reason; - Write(buf.str()); - ++ign; - } - } + Serializable::Alloc.Register("Ignore"); } EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) diff --git a/modules/commands/os_ignore.h b/modules/commands/os_ignore.h index b00f427dd..753a4cfaf 100644 --- a/modules/commands/os_ignore.h +++ b/modules/commands/os_ignore.h @@ -10,12 +10,15 @@ */ -struct IgnoreData +struct IgnoreData : Serializable { Anope::string mask; Anope::string creator; Anope::string reason; time_t time; /* When do we stop ignoring them? */ + + serialized_data serialize(); + static void unserialize(serialized_data &data); }; class IgnoreService : public Service @@ -23,7 +26,7 @@ class IgnoreService : public Service protected: std::list ignores; - IgnoreService(Module *c, const Anope::string &n) : Service(c, n) { } + IgnoreService(Module *c) : Service(c, "ignore") { } public: virtual void AddIgnore(const Anope::string &mask, const Anope::string &creator, const Anope::string &reason, time_t delta = Anope::CurTime) = 0; @@ -37,3 +40,28 @@ class IgnoreService : public Service inline std::list &GetIgnores() { return this->ignores; } }; +static service_reference ignore_service("ignore"); + +SerializableBase::serialized_data IgnoreData::serialize() +{ + serialized_data data; + + data["mask"] << this->mask; + data["creator"] << this->creator; + data["reason"] << this->reason; + data