anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

xline.cpp (9922B)

      1 /* XLine functions.
      2  *
      3  * (C) 2003-2022 Anope Team
      4  * Contact us at team@anope.org
      5  *
      6  * Please read COPYING and README for further details.
      7  *
      8  * Based on the original code of Epona by Lara.
      9  * Based on the original code of Services by Andy Church.
     10  */
     11 
     12 #include "services.h"
     13 #include "modules.h"
     14 #include "xline.h"
     15 #include "users.h"
     16 #include "sockets.h"
     17 #include "regexpr.h"
     18 #include "config.h"
     19 #include "commands.h"
     20 #include "servers.h"
     21 
     22 /* List of XLine managers we check users against in XLineManager::CheckAll */
     23 std::list<XLineManager *> XLineManager::XLineManagers;
     24 Serialize::Checker<std::multimap<Anope::string, XLine *, ci::less> > XLineManager::XLinesByUID("XLine");
     25 
     26 void XLine::Init()
     27 {
     28 	if (this->mask.length() >= 2 && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/' && !Config->GetBlock("options")->Get<const Anope::string>("regexengine").empty())
     29 	{
     30 		Anope::string stripped_mask = this->mask.substr(1, this->mask.length() - 2);
     31 
     32 		ServiceReference<RegexProvider> provider("Regex", Config->GetBlock("options")->Get<const Anope::string>("regexengine"));
     33 		if (provider)
     34 		{
     35 			try
     36 			{
     37 				this->regex = provider->Compile(stripped_mask);
     38 			}
     39 			catch (const RegexException &ex)
     40 			{
     41 				Log(LOG_DEBUG) << ex.GetReason();
     42 			}
     43 		}
     44 	}
     45 
     46 	size_t nick_t = this->mask.find('!');
     47 	if (nick_t != Anope::string::npos)
     48 		nick = this->mask.substr(0, nick_t);
     49 
     50 	size_t user_t = this->mask.find('!'), host_t = this->mask.find('@');
     51 	if (host_t != Anope::string::npos)
     52 	{
     53 		if (user_t != Anope::string::npos && host_t > user_t)
     54 			user = this->mask.substr(user_t + 1, host_t - user_t - 1);
     55 		else
     56 			user = this->mask.substr(0, host_t);
     57 	}
     58 
     59 	size_t real_t = this->mask.find('#');
     60 	if (host_t != Anope::string::npos)
     61 	{
     62 		if (real_t != Anope::string::npos && real_t > host_t)
     63 			host = this->mask.substr(host_t + 1, real_t - host_t - 1);
     64 		else
     65 			host = this->mask.substr(host_t + 1);
     66 	}
     67 	else
     68 	{
     69 		if (real_t != Anope::string::npos)
     70 			host = this->mask.substr(0, real_t);
     71 		else
     72 			host = this->mask;
     73 	}
     74 
     75 	if (real_t != Anope::string::npos)
     76 		real = this->mask.substr(real_t + 1);
     77 
     78 	if (host.find('/') != Anope::string::npos)
     79 	{
     80 		c = new cidr(host);
     81 		if (!c->valid())
     82 		{
     83 			delete c;
     84 			c = NULL;
     85 		}
     86 	}
     87 }
     88 
     89 XLine::XLine(const Anope::string &ma, const Anope::string &r, const Anope::string &uid) : Serializable("XLine"), mask(ma), by(Me->GetName()), created(0), expires(0), reason(r), id(uid)
     90 {
     91 	regex = NULL;
     92 	manager = NULL;
     93 	c = NULL;
     94 
     95 	this->Init();
     96 }
     97 
     98 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)
     99 {
    100 	regex = NULL;
    101 	manager = NULL;
    102 	c = NULL;
    103 
    104 	this->Init();
    105 }
    106 
    107 XLine::~XLine()
    108 {
    109 	if (manager)
    110 		manager->RemoveXLine(this);
    111 
    112 	delete regex;
    113 	delete c;
    114 }
    115 
    116 const Anope::string &XLine::GetNick() const
    117 {
    118 	return nick;
    119 }
    120 
    121 const Anope::string &XLine::GetUser() const
    122 {
    123 	return user;
    124 }
    125 
    126 const Anope::string &XLine::GetHost() const
    127 {
    128 	return host;
    129 }
    130 
    131 const Anope::string &XLine::GetReal() const
    132 {
    133 	return real;
    134 }
    135 
    136 Anope::string XLine::GetReason() const
    137 {
    138 	Anope::string r = this->reason;
    139 	if (!this->id.empty())
    140 		r += " (ID: " + this->id + ")";
    141 	return r;
    142 }
    143 
    144 bool XLine::HasNickOrReal() const
    145 {
    146 	return !this->GetNick().empty() || !this->GetReal().empty();
    147 }
    148 
    149 bool XLine::IsRegex() const
    150 {
    151 	return !this->mask.empty() && this->mask[0] == '/' && this->mask[this->mask.length() - 1] == '/';
    152 }
    153 
    154 void XLine::Serialize(Serialize::Data &data) const
    155 {
    156 	data["mask"] << this->mask;
    157 	data["by"] << this->by;
    158 	data["created"] << this->created;
    159 	data["expires"] << this->expires;
    160 	data["reason"] << this->reason;
    161 	data["uid"] << this->id;
    162 	if (this->manager)
    163 		data["manager"] << this->manager->name;
    164 }
    165 
    166 Serializable* XLine::Unserialize(Serializable *obj, Serialize::Data &data)
    167 {
    168 	Anope::string smanager;
    169 
    170 	data["manager"] >> smanager;
    171 
    172 	ServiceReference<XLineManager> xlm("XLineManager", smanager);
    173 	if (!xlm)
    174 		return NULL;
    175 
    176 	XLine *xl;
    177 	if (obj)
    178 	{
    179 		xl = anope_dynamic_static_cast<XLine *>(obj);
    180 		data["mask"] >> xl->mask;
    181 		data["by"] >> xl->by;
    182 		data["reason"] >> xl->reason;
    183 		data["uid"] >> xl->id;
    184 
    185 		if (xlm != xl->manager)
    186 		{
    187 			xl->manager->DelXLine(xl);
    188 			xlm->AddXLine(xl);
    189 		}
    190 	}
    191 	else
    192 	{
    193 		Anope::string smask, sby, sreason, suid;
    194 		time_t expires;
    195 
    196 		data["mask"] >> smask;
    197 		data["by"] >> sby;
    198 		data["reason"] >> sreason;
    199 		data["uid"] >> suid;
    200 		data["expires"] >> expires;
    201 
    202 		xl = new XLine(smask, sby, expires, sreason, suid);
    203 		xlm->AddXLine(xl);
    204 	}
    205 
    206 	data["created"] >> xl->created;
    207 	xl->manager = xlm;
    208 
    209 	return xl;
    210 }
    211 
    212 void XLineManager::RegisterXLineManager(XLineManager *xlm)
    213 {
    214 	XLineManagers.push_back(xlm);
    215 }
    216 
    217 void XLineManager::UnregisterXLineManager(XLineManager *xlm)
    218 {
    219 	std::list<XLineManager *>::iterator it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm);
    220 
    221 	if (it != XLineManagers.end())
    222 		XLineManagers.erase(it);
    223 }
    224 
    225 void XLineManager::CheckAll(User *u)
    226 {
    227 	for (std::list<XLineManager *>::iterator it = XLineManagers.begin(), it_end = XLineManagers.end(); it != it_end; ++it)
    228 	{
    229 		XLineManager *xlm = *it;
    230 
    231 		if (xlm->CheckAllXLines(u))
    232 			break;
    233 	}
    234 }
    235 
    236 Anope::string XLineManager::GenerateUID()
    237 {
    238 	Anope::string id;
    239 	int count = 0;
    240 	do
    241 	{
    242 		id.clear();
    243 
    244 		if (++count > 10)
    245 		{
    246 			Log(LOG_DEBUG) << "Unable to generate XLine UID";
    247 			break;
    248 		}
    249 
    250 		for (int i = 0; i < 10; ++i)
    251 		{
    252 			char c;
    253 			do
    254 				c = (rand() % 75) + 48;
    255 			while (!isupper(c) && !isdigit(c));
    256 			id += c;
    257 		}
    258 	}
    259 	while (XLinesByUID->count(id) > 0);
    260 
    261 	return id;
    262 }
    263 
    264 XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, "XLineManager", xname), type(t), xlines("XLine")
    265 {
    266 }
    267 
    268 XLineManager::~XLineManager()
    269 {
    270 	this->Clear();
    271 }
    272 
    273 const char &XLineManager::Type()
    274 {
    275 	return this->type;
    276 }
    277 
    278 size_t XLineManager::GetCount() const
    279 {
    280 	return this->xlines->size();
    281 }
    282 
    283 const std::vector<XLine *> &XLineManager::GetList() const
    284 {
    285 	return this->xlines;
    286 }
    287 
    288 void XLineManager::AddXLine(XLine *x)
    289 {
    290 	if (!x->id.empty())
    291 		XLinesByUID->insert(std::make_pair(x->id, x));
    292 	this->xlines->push_back(x);
    293 	x->manager = this;
    294 }
    295 
    296 void XLineManager::RemoveXLine(XLine *x)
    297 {
    298 	/* called from the destructor */
    299 
    300 	std::vector<XLine *>::iterator it = std::find(this->xlines->begin(), this->xlines->end(), x);
    301 
    302 	if (!x->id.empty())
    303 	{
    304 		std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->id), it3 = XLinesByUID->upper_bound(x->id);
    305 		for (; it2 != XLinesByUID->end() && it2 != it3; ++it2)
    306 			if (it2->second == x)
    307 			{
    308 				XLinesByUID->erase(it2);
    309 				break;
    310 			}
    311 	}
    312 
    313 	if (it != this->xlines->end())
    314 	{
    315 		this->SendDel(x);
    316 		this->xlines->erase(it);
    317 	}
    318 }
    319 
    320 bool XLineManager::DelXLine(XLine *x)
    321 {
    322 	std::vector<XLine *>::iterator it = std::find(this->xlines->begin(), this->xlines->end(), x);
    323 
    324 	if (!x->id.empty())
    325 	{
    326 		std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->id), it3 = XLinesByUID->upper_bound(x->id);
    327 		for (; it2 != XLinesByUID->end() && it2 != it3; ++it2)
    328 			if (it2->second == x)
    329 			{
    330 				XLinesByUID->erase(it2);
    331 				break;
    332 			}
    333 	}
    334 
    335 	if (it != this->xlines->end())
    336 	{
    337 		this->SendDel(x);
    338 
    339 		x->manager = NULL; // Don't call remove
    340 		delete x;
    341 		this->xlines->erase(it);
    342 
    343 		return true;
    344 	}
    345 
    346 	return false;
    347 }
    348 
    349 XLine* XLineManager::GetEntry(unsigned index)
    350 {
    351 	if (index >= this->xlines->size())
    352 		return NULL;
    353 
    354 	XLine *x = this->xlines->at(index);
    355 	x->QueueUpdate();
    356 	return x;
    357 }
    358 
    359 void XLineManager::Clear()
    360 {
    361 	std::vector<XLine *> xl;
    362 	this->xlines->swap(xl);
    363 
    364 	for (unsigned i = 0; i < xl.size(); ++i)
    365 	{
    366 		XLine *x = xl[i];
    367 		if (!x->id.empty())
    368 			XLinesByUID->erase(x->id);
    369 		delete x;
    370 	}
    371 }
    372 
    373 bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time_t expires, const Anope::string &reason)
    374 {
    375 	for (unsigned i = this->GetCount(); i > 0; --i)
    376 	{
    377 		XLine *x = this->GetEntry(i - 1);
    378 
    379 		if (x->mask.equals_ci(mask))
    380 		{
    381 			if (!x->expires || x->expires >= expires)
    382 			{
    383 				if (x->reason != reason)
    384 				{
    385 					x->reason = reason;
    386 					source.Reply(_("Reason for %s updated."), x->mask.c_str());
    387 				}
    388 				else
    389 					source.Reply(_("%s already exists."), mask.c_str());
    390 			}
    391 			else
    392 			{
    393 				x->expires = expires;
    394 				if (x->reason != reason)
    395 				{
    396 					x->reason = reason;
    397 					source.Reply(_("Expiry and reason updated for %s."), x->mask.c_str());
    398 				}
    399 				else
    400 					source.Reply(_("Expiry for %s updated."), x->mask.c_str());
    401 			}
    402 
    403 			return false;
    404 		}
    405 		else if (Anope::Match(mask, x->mask) && (!x->expires || x->expires >= expires))
    406 		{
    407 			source.Reply(_("%s is already covered by %s."), mask.c_str(), x->mask.c_str());
    408 			return false;
    409 		}
    410 		else if (Anope::Match(x->mask, mask) && (!expires || x->expires <= expires))
    411 		{
    412 			source.Reply(_("Removing %s because %s covers it."), x->mask.c_str(), mask.c_str());
    413 			this->DelXLine(x);
    414 		}
    415 	}
    416 
    417 	return true;
    418 }
    419 
    420 XLine* XLineManager::HasEntry(const Anope::string &mask)
    421 {
    422 	std::multimap<Anope::string, XLine *, ci::less>::iterator it = XLinesByUID->find(mask);
    423 	if (it != XLinesByUID->end())
    424 		for (std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->upper_bound(mask); it != it2; ++it)
    425 			if (it->second->manager == NULL || it->second->manager == this)
    426 			{
    427 				it->second->QueueUpdate();
    428 				return it->second;
    429 			}
    430 	for (unsigned i = 0, end = this->xlines->size(); i < end; ++i)
    431 	{
    432 		XLine *x = this->xlines->at(i);
    433 
    434 		if (x->mask.equals_ci(mask))
    435 		{
    436 			x->QueueUpdate();
    437 			return x;
    438 		}
    439 	}
    440 
    441 	return NULL;
    442 }
    443 
    444 XLine *XLineManager::CheckAllXLines(User *u)
    445 {
    446 	for (unsigned i = this->xlines->size(); i > 0; --i)
    447 	{
    448 		XLine *x = this->xlines->at(i - 1);
    449 
    450 		if (x->expires && x->expires < Anope::CurTime)
    451 		{
    452 			this->OnExpire(x);
    453 			this->DelXLine(x);
    454 			continue;
    455 		}
    456 
    457 		if (this->Check(u, x))
    458 		{
    459 			this->OnMatch(u, x);
    460 			return x;
    461 		}
    462 	}
    463 
    464 	return NULL;
    465 }
    466 
    467 void XLineManager::OnExpire(const XLine *x)
    468 {
    469 }