summaryrefslogtreecommitdiff
path: root/src/xline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xline.cpp')
-rw-r--r--src/xline.cpp425
1 files changed, 425 insertions, 0 deletions
diff --git a/src/xline.cpp b/src/xline.cpp
new file mode 100644
index 000000000..4ac6581a1
--- /dev/null
+++ b/src/xline.cpp
@@ -0,0 +1,425 @@
+/* XLine functions.
+ *
+ * (C) 2003-2012 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 "services.h"
+#include "modules.h"
+#include "xline.h"
+#include "users.h"
+#include "sockets.h"
+#include "regexpr.h"
+#include "config.h"
+#include "commands.h"
+
+/* List of XLine managers we check users against in XLineManager::CheckAll */
+std::list<XLineManager *> XLineManager::XLineManagers;
+Serialize::Checker<std::multimap<Anope::string, XLine *, ci::less> > XLineManager::XLinesByUID("XLine");
+
+void XLine::InitRegex()
+{
+ if (!Config->RegexEngine.empty() && this->mask.length() >= 2 && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/')
+ {
+ Anope::string stripped_mask = this->mask.substr(1, this->mask.length() - 2);
+
+ ServiceReference<RegexProvider> provider("Regex", Config->RegexEngine);
+ if (provider)
+ {
+ try
+ {
+ this->regex = provider->Compile(stripped_mask);
+ }
+ catch (const RegexException &ex)
+ {
+ Log(LOG_DEBUG) << ex.GetReason();
+ }
+ }
+ }
+}
+
+XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(Config->OperServ), created(0), expires(0), reason(r), id(uid)
+{
+ regex = NULL;
+ manager = NULL;
+
+ this->InitRegex();
+}
+
+XLine::XLine(const Anope::string &ma, const Anope::string &b, const time_t ex, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(b), created(Anope::CurTime), expires(ex), reason(r), id(uid)
+{
+ regex = NULL;
+ manager = NULL;
+
+ this->InitRegex();
+}
+
+XLine::~XLine()
+{
+ delete regex;
+}
+
+Anope::string XLine::GetNick() const
+{
+ size_t nick_t = this->mask.find('!');
+
+ if (nick_t == Anope::string::npos)
+ return "";
+
+ return this->mask.substr(0, nick_t);
+}
+
+Anope::string XLine::GetUser() const
+{
+ size_t user_t = this->mask.find('!'), host_t = this->mask.find('@');
+
+ if (host_t != Anope::string::npos)
+ {
+ if (user_t != Anope::string::npos && host_t > user_t)
+ return this->mask.substr(user_t + 1, host_t - user_t - 1);
+ else
+ return this->mask.substr(0, host_t);
+ }
+ else
+ return "";
+}
+
+Anope::string XLine::GetHost() const
+{
+ size_t host_t = this->mask.find('@'), real_t = this->mask.find('#');
+
+ if (host_t != Anope::string::npos)
+ {
+ if (real_t != Anope::string::npos && real_t > host_t)
+ return this->mask.substr(host_t + 1, real_t - host_t - 1);
+ else
+ return this->mask.substr(host_t + 1);
+ }
+ else
+ return "";
+}
+
+Anope::string XLine::GetReal() const
+{
+ size_t real_t = this->mask.find('#');
+
+ if (real_t != Anope::string::npos)
+ return this->mask.substr(real_t + 1);
+ else
+ return "";
+}
+
+Anope::string XLine::GetReason() const
+{
+ Anope::string r = this->reason;
+ if (Config->AddAkiller && !this->by.empty())
+ r = "[" + this->by + "] " + r;
+ if (!this->id.empty())
+ r += " (ID: " + this->id + ")";
+ return r;
+}
+
+bool XLine::HasNickOrReal() const
+{
+ bool r = this->GetNick().find_first_not_of("?*") != Anope::string::npos;
+ r = r || this->GetReal().find_first_not_of("?*") != Anope::string::npos;
+ return r;
+}
+
+bool XLine::IsRegex() const
+{
+ return !this->mask.empty() && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/';
+}
+
+Serialize::Data XLine::Serialize() const
+{
+ Serialize::Data data;
+
+ data["mask"] << this->mask;
+ data["by"] << this->by;
+ data["created"] << this->created;
+ data["expires"] << this->expires;
+ data["reason"] << this->reason;
+ data["uid"] << this->id;
+ if (this->manager)
+ data["manager"] << this->manager->name;
+
+ return data;
+}
+
+Serializable* XLine::Unserialize(Serializable *obj, Serialize::Data &data)
+{
+ ServiceReference<XLineManager> xlm("XLineManager", data["manager"].astr());
+ if (!xlm)
+ return NULL;
+
+ XLine *xl;
+ if (obj)
+ {
+ xl = anope_dynamic_static_cast<XLine *>(obj);
+ data["mask"] >> xl->mask;
+ data["by"] >> xl->by;
+ data["reason"] >> xl->reason;
+ data["uid"] >> xl->id;
+
+ if (xlm != xl->manager)
+ {
+ xl->manager->DelXLine(xl);
+ xlm->AddXLine(xl);
+ }
+ }
+ else
+ {
+ time_t expires;
+ data["expires"] >> expires;
+ xl = new XLine(data["mask"].astr(), data["by"].astr(), expires, data["reason"].astr(), data["uid"].astr());
+ xlm->AddXLine(xl);
+ }
+
+ data["created"] >> xl->created;
+ xl->manager = xlm;
+
+ return xl;
+}
+
+void XLineManager::RegisterXLineManager(XLineManager *xlm)
+{
+ XLineManagers.push_back(xlm);
+}
+
+void XLineManager::UnregisterXLineManager(XLineManager *xlm)
+{
+ std::list<XLineManager *>::iterator it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm);
+
+ if (it != XLineManagers.end())
+ XLineManagers.erase(it);
+}
+
+void XLineManager::CheckAll(User *u)
+{
+ for (std::list<XLineManager *>::iterator it = XLineManagers.begin(), it_end = XLineManagers.end(); it != it_end; ++it)
+ {
+ XLineManager *xlm = *it;
+
+ XLine *x = xlm->CheckAllXLines(u);
+
+ if (x)
+ {
+ xlm->OnMatch(u, x);
+ break;
+ }
+ }
+}
+
+Anope::string XLineManager::GenerateUID()
+{
+ Anope::string id;
+ int count = 0;
+ while (id.empty() || XLinesByUID->count(id) > 0)
+ {
+ if (++count > 10)
+ {
+ id.clear();
+ Log(LOG_DEBUG) << "Unable to generate XLine UID";
+ break;
+ }
+
+ for (int i = 0; i < 10; ++i)
+ {
+ char c;
+ do
+ c = (rand() % 75) + 48;
+ while (!isupper(c) && !isdigit(c));
+ id += c;
+ }
+ }
+
+ return id;
+}
+
+XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, "XLineManager", xname), type(t), xlines("XLine")
+{
+}
+
+XLineManager::~XLineManager()
+{
+ this->Clear();
+}
+
+const char &XLineManager::Type()
+{
+ return this->type;
+}
+
+size_t XLineManager::GetCount() const
+{
+ return this->xlines->size();
+}
+
+const std::vector<XLine *> &XLineManager::GetList() const
+{
+ return this->xlines;
+}
+
+void XLineManager::AddXLine(XLine *x)
+{
+ if (!x->id.empty())
+ XLinesByUID->insert(std::make_pair(x->id, x));
+ this->xlines->push_back(x);
+ x->manager = this;
+}
+
+bool XLineManager::DelXLine(XLine *x)
+{
+ std::vector<XLine *>::iterator it = std::find(this->xlines->begin(), this->xlines->end(), x);
+
+ if (!x->id.empty())
+ {
+ std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->id), it3 = XLinesByUID->upper_bound(x->id);
+ for (; it2 != XLinesByUID->end() && it2 != it3; ++it2)
+ if (it2->second == x)
+ {
+ XLinesByUID->erase(it2);
+ break;
+ }
+ }
+
+ if (it != this->xlines->end())
+ {
+ this->SendDel(x);
+
+ x->Destroy();
+ this->xlines->erase(it);
+
+ return true;
+ }
+
+ return false;
+}
+
+XLine* XLineManager::GetEntry(unsigned index)
+{
+ if (index >= this->xlines->size())
+ return NULL;
+
+ XLine *x = this->xlines->at(index);
+ x->QueueUpdate();
+ return x;
+}
+
+void XLineManager::Clear()
+{
+ for (unsigned i = 0; i < this->xlines->size(); ++i)
+ {
+ XLine *x = this->xlines->at(i);
+ if (!x->id.empty())
+ XLinesByUID->erase(x->id);
+ x->Destroy();
+ }
+ this->xlines->clear();
+}
+
+bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time_t expires, const Anope::string &reason)
+{
+ for (unsigned i = this->GetCount(); i > 0; --i)
+ {
+ XLine *x = this->GetEntry(i - 1);
+
+ if (x->mask.equals_ci(mask))
+ {
+ if (!x->expires || x->expires >= expires)
+ {
+ if (x->reason != reason)
+ {
+ x->reason = reason;
+ source.Reply(_("Reason for %s updated."), x->mask.c_str());
+ }
+ else
+ source.Reply(_("%s already exists."), mask.c_str());
+ }
+ else
+ {
+ x->expires = expires;
+ if (x->reason != reason)
+ {
+ x->reason = reason;
+ source.Reply(_("Expiry and reason updated for %s."), x->mask.c_str());
+ }
+ else
+ source.Reply(_("Expiry for %s updated."), x->mask.c_str());
+ }
+
+ return false;
+ }
+ else if (Anope::Match(mask, x->mask) && (!x->expires || x->expires >= expires))
+ {
+ source.Reply(_("%s is already covered by %s."), mask.c_str(), x->mask.c_str());
+ return false;
+ }
+ else if (Anope::Match(x->mask, mask) && (!expires || x->expires <= expires))
+ {
+ source.Reply(_("Removing %s because %s covers it."), x->mask.c_str(), mask.c_str());
+ this->DelXLine(x);
+ }
+ }
+
+ return true;
+}
+
+XLine* XLineManager::HasEntry(const Anope::string &mask)
+{
+ std::multimap<Anope::string, XLine *, ci::less>::iterator it = XLinesByUID->find(mask);
+ if (it != XLinesByUID->end())
+ for (std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->upper_bound(mask); it != it2; ++it)
+ if (it->second->manager == NULL || it->second->manager == this)
+ {
+ it->second->QueueUpdate();
+ return it->second;
+ }
+ for (unsigned i = 0, end = this->xlines->size(); i < end; ++i)
+ {
+ XLine *x = this->xlines->at(i);
+
+ if (x->mask.equals_ci(mask))
+ {
+ x->QueueUpdate();
+ return x;
+ }
+ }
+
+ return NULL;
+}
+
+XLine *XLineManager::CheckAllXLines(User *u)
+{
+ for (unsigned i = this->xlines->size(); i > 0; --i)
+ {
+ XLine *x = this->xlines->at(i - 1);
+
+ if (x->expires && x->expires < Anope::CurTime)
+ {
+ this->OnExpire(x);
+ this->DelXLine(x);
+ continue;
+ }
+
+ if (this->Check(u, x))
+ {
+ this->OnMatch(u, x);
+ return x;
+ }
+ }
+
+ return NULL;
+}
+
+void XLineManager::OnExpire(const XLine *x)
+{
+}
+