00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "services.h"
00014 #include "modules.h"
00015 #include "oper.h"
00016 #include "users.h"
00017 #include "extern.h"
00018 #include "sockets.h"
00019 #include "regexpr.h"
00020 #include "config.h"
00021 #include "commands.h"
00022
00023
00024 std::list<XLineManager *> XLineManager::XLineManagers;
00025 serialize_checker<std::multimap<Anope::string, XLine *, ci::less> > XLineManager::XLinesByUID("XLine");
00026
00027 void XLine::InitRegex()
00028 {
00029 if (!Config->RegexEngine.empty() && this->Mask.length() >= 2 && this->Mask[0] == '/' && this->Mask[this->Mask.length() - 1] == '/')
00030 {
00031 Anope::string stripped_mask = this->Mask.substr(1, this->Mask.length() - 2);
00032
00033 service_reference<RegexProvider> provider("Regex", Config->RegexEngine);
00034 if (provider)
00035 {
00036 try
00037 {
00038 this->regex = provider->Compile(stripped_mask);
00039 }
00040 catch (const RegexException &ex)
00041 {
00042 Log(LOG_DEBUG) << ex.GetReason();
00043 }
00044 }
00045 }
00046 }
00047
00048 XLine::XLine(const Anope::string &mask, const Anope::string &reason, const Anope::string &uid) : Serializable("XLine"), Mask(mask), By(Config->OperServ), Created(0), Expires(0), Reason(reason), UID(uid)
00049 {
00050 regex = NULL;
00051 manager = NULL;
00052
00053 this->InitRegex();
00054 }
00055
00056 XLine::XLine(const Anope::string &mask, const Anope::string &by, const time_t expires, const Anope::string &reason, const Anope::string &uid) : Serializable("XLine"), Mask(mask), By(by), Created(Anope::CurTime), Expires(expires), Reason(reason), UID(uid)
00057 {
00058 regex = NULL;
00059 manager = NULL;
00060
00061 this->InitRegex();
00062 }
00063
00064 XLine::~XLine()
00065 {
00066 delete regex;
00067 }
00068
00069 Anope::string XLine::GetNick() const
00070 {
00071 size_t nick_t = this->Mask.find('!');
00072
00073 if (nick_t == Anope::string::npos)
00074 return "";
00075
00076 return this->Mask.substr(0, nick_t);
00077 }
00078
00079 Anope::string XLine::GetUser() const
00080 {
00081 size_t user_t = this->Mask.find('!'), host_t = this->Mask.find('@');
00082
00083 if (host_t != Anope::string::npos)
00084 {
00085 if (user_t != Anope::string::npos && host_t > user_t)
00086 return this->Mask.substr(user_t + 1, host_t - user_t - 1);
00087 else
00088 return this->Mask.substr(0, host_t);
00089 }
00090 else
00091 return "";
00092 }
00093
00094 Anope::string XLine::GetHost() const
00095 {
00096 size_t host_t = this->Mask.find('@'), real_t = this->Mask.find('#');
00097
00098 if (host_t != Anope::string::npos)
00099 {
00100 if (real_t != Anope::string::npos && real_t > host_t)
00101 return this->Mask.substr(host_t + 1, real_t - host_t - 1);
00102 else
00103 return this->Mask.substr(host_t + 1);
00104 }
00105 else
00106 return "";
00107 }
00108
00109 Anope::string XLine::GetReal() const
00110 {
00111 size_t real_t = this->Mask.find('#');
00112
00113 if (real_t != Anope::string::npos)
00114 return this->Mask.substr(real_t + 1);
00115 else
00116 return "";
00117 }
00118
00119 Anope::string XLine::GetReason() const
00120 {
00121 Anope::string r = this->Reason;
00122 if (Config->AddAkiller && !this->By.empty())
00123 r = "[" + this->By + "] " + r;
00124 if (!this->UID.empty())
00125 r += " (ID: " + this->UID + ")";
00126 return r;
00127 }
00128
00129 bool XLine::HasNickOrReal() const
00130 {
00131 bool r = this->GetNick().find_first_not_of("?*") != Anope::string::npos;
00132 r = r || this->GetReal().find_first_not_of("?*") != Anope::string::npos;
00133 return r;
00134 }
00135
00136 bool XLine::IsRegex() const
00137 {
00138 return !this->Mask.empty() && this->Mask[0] == '/' && this->Mask[this->Mask.length() - 1] == '/';
00139 }
00140
00141 Serialize::Data XLine::serialize() const
00142 {
00143 Serialize::Data data;
00144
00145 data["mask"] << this->Mask;
00146 data["by"] << this->By;
00147 data["created"] << this->Created;
00148 data["expires"] << this->Expires;
00149 data["reason"] << this->Reason;
00150 data["uid"] << this->UID;
00151 if (this->manager)
00152 data["manager"] << this->manager->name;
00153
00154 return data;
00155 }
00156
00157 Serializable* XLine::unserialize(Serializable *obj, Serialize::Data &data)
00158 {
00159 service_reference<XLineManager> xlm("XLineManager", data["manager"].astr());
00160 if (!xlm)
00161 return NULL;
00162
00163 XLine *xl;
00164 if (obj)
00165 {
00166 xl = anope_dynamic_static_cast<XLine *>(obj);
00167 data["mask"] >> xl->Mask;
00168 data["by"] >> xl->By;
00169 data["reason"] >> xl->Reason;
00170 data["uid"] >> xl->UID;
00171
00172 if (xlm != xl->manager)
00173 {
00174 xl->manager->DelXLine(xl);
00175 xlm->AddXLine(xl);
00176 }
00177 }
00178 else
00179 {
00180 time_t expires;
00181 data["expires"] >> expires;
00182 xl = new XLine(data["mask"].astr(), data["by"].astr(), expires, data["reason"].astr(), data["uid"].astr());
00183 xlm->AddXLine(xl);
00184 }
00185
00186 data["created"] >> xl->Created;
00187 xl->manager = xlm;
00188
00189 return xl;
00190 }
00191
00198 void XLineManager::RegisterXLineManager(XLineManager *xlm)
00199 {
00200 XLineManagers.push_back(xlm);
00201 }
00202
00206 void XLineManager::UnregisterXLineManager(XLineManager *xlm)
00207 {
00208 std::list<XLineManager *>::iterator it = std::find(XLineManagers.begin(), XLineManagers.end(), xlm);
00209
00210 if (it != XLineManagers.end())
00211 XLineManagers.erase(it);
00212 }
00213
00214
00215
00216
00217
00218 void XLineManager::CheckAll(User *u)
00219 {
00220 for (std::list<XLineManager *>::iterator it = XLineManagers.begin(), it_end = XLineManagers.end(); it != it_end; ++it)
00221 {
00222 XLineManager *xlm = *it;
00223
00224 XLine *x = xlm->CheckAllXLines(u);
00225
00226 if (x)
00227 {
00228 xlm->OnMatch(u, x);
00229 break;
00230 }
00231 }
00232 }
00233
00234 Anope::string XLineManager::GenerateUID()
00235 {
00236 Anope::string id;
00237 int count = 0;
00238 while (id.empty() || XLinesByUID->count(id) > 0)
00239 {
00240 if (++count > 10)
00241 {
00242 id.clear();
00243 Log(LOG_DEBUG) << "Unable to generate XLine UID";
00244 break;
00245 }
00246
00247 for (int i = 0; i < 10; ++i)
00248 {
00249 char c;
00250 do
00251 c = (rand() % 75) + 48;
00252 while (!isupper(c) && !isdigit(c));
00253 id += c;
00254 }
00255 }
00256
00257 return id;
00258 }
00259
00262 XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service(creator, "XLineManager", xname), type(t), XLines("XLine")
00263 {
00264 }
00265
00269 XLineManager::~XLineManager()
00270 {
00271 this->Clear();
00272 }
00273
00277 const char &XLineManager::Type()
00278 {
00279 return this->type;
00280 }
00281
00285 size_t XLineManager::GetCount() const
00286 {
00287 return this->XLines->size();
00288 }
00289
00293 const std::vector<XLine *> &XLineManager::GetList() const
00294 {
00295 return this->XLines;
00296 }
00297
00301 void XLineManager::AddXLine(XLine *x)
00302 {
00303 if (!x->UID.empty())
00304 XLinesByUID->insert(std::make_pair(x->UID, x));
00305 this->XLines->push_back(x);
00306 x->manager = this;
00307 }
00308
00313 bool XLineManager::DelXLine(XLine *x)
00314 {
00315 std::vector<XLine *>::iterator it = std::find(this->XLines->begin(), this->XLines->end(), x);
00316
00317 if (!x->UID.empty())
00318 {
00319 std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->find(x->UID), it3 = XLinesByUID->upper_bound(x->UID);
00320 for (; it2 != XLinesByUID->end() && it2 != it3; ++it2)
00321 if (it2->second == x)
00322 {
00323 XLinesByUID->erase(it2);
00324 break;
00325 }
00326 }
00327
00328 if (it != this->XLines->end())
00329 {
00330 this->SendDel(x);
00331
00332 x->destroy();
00333 this->XLines->erase(it);
00334
00335 return true;
00336 }
00337
00338 return false;
00339 }
00340
00345 XLine* XLineManager::GetEntry(unsigned index)
00346 {
00347 if (index >= this->XLines->size())
00348 return NULL;
00349
00350 XLine *x = this->XLines->at(index);
00351 x->QueueUpdate();
00352 return x;
00353 }
00354
00357 void XLineManager::Clear()
00358 {
00359 for (unsigned i = 0; i < this->XLines->size(); ++i)
00360 {
00361 XLine *x = this->XLines->at(i);
00362 if (!x->UID.empty())
00363 XLinesByUID->erase(x->UID);
00364 x->destroy();
00365 }
00366 this->XLines->clear();
00367 }
00368
00376 bool XLineManager::CanAdd(CommandSource &source, const Anope::string &mask, time_t expires, const Anope::string &reason)
00377 {
00378 for (unsigned i = this->GetCount(); i > 0; --i)
00379 {
00380 XLine *x = this->GetEntry(i - 1);
00381
00382 if (x->Mask.equals_ci(mask))
00383 {
00384 if (!x->Expires || x->Expires >= expires)
00385 {
00386 if (x->Reason != reason)
00387 {
00388 x->Reason = reason;
00389 source.Reply(_("Reason for %s updated."), x->Mask.c_str());
00390 }
00391 else
00392 source.Reply(_("%s already exists."), mask.c_str());
00393 }
00394 else
00395 {
00396 x->Expires = expires;
00397 if (x->Reason != reason)
00398 {
00399 x->Reason = reason;
00400 source.Reply(_("Expiry and reason updated for %s."), x->Mask.c_str());
00401 }
00402 else
00403 source.Reply(_("Expiry for %s updated."), x->Mask.c_str());
00404 }
00405
00406 return false;
00407 }
00408 else if (Anope::Match(mask, x->Mask) && (!x->Expires || x->Expires >= expires))
00409 {
00410 source.Reply(_("%s is already covered by %s."), mask.c_str(), x->Mask.c_str());
00411 return false;
00412 }
00413 else if (Anope::Match(x->Mask, mask) && (!expires || x->Expires <= expires))
00414 {
00415 source.Reply(_("Removing %s because %s covers it."), x->Mask.c_str(), mask.c_str());
00416 this->DelXLine(x);
00417 }
00418 }
00419
00420 return true;
00421 }
00422
00427 XLine* XLineManager::HasEntry(const Anope::string &mask)
00428 {
00429 std::multimap<Anope::string, XLine *, ci::less>::iterator it = XLinesByUID->find(mask);
00430 if (it != XLinesByUID->end())
00431 for (std::multimap<Anope::string, XLine *, ci::less>::iterator it2 = XLinesByUID->upper_bound(mask); it != it2; ++it)
00432 if (it->second->manager == NULL || it->second->manager == this)
00433 {
00434 it->second->QueueUpdate();
00435 return it->second;
00436 }
00437 for (unsigned i = 0, end = this->XLines->size(); i < end; ++i)
00438 {
00439 XLine *x = this->XLines->at(i);
00440
00441 if (x->Mask.equals_ci(mask))
00442 {
00443 x->QueueUpdate();
00444 return x;
00445 }
00446 }
00447
00448 return NULL;
00449 }
00450
00455 XLine *XLineManager::CheckAllXLines(User *u)
00456 {
00457 for (unsigned i = this->XLines->size(); i > 0; --i)
00458 {
00459 XLine *x = this->XLines->at(i - 1);
00460
00461 if (x->Expires && x->Expires < Anope::CurTime)
00462 {
00463 this->OnExpire(x);
00464 this->DelXLine(x);
00465 continue;
00466 }
00467
00468 if (this->Check(u, x))
00469 {
00470 this->OnMatch(u, x);
00471 return x;
00472 }
00473 }
00474
00475 return NULL;
00476 }
00477
00481 void XLineManager::OnExpire(const XLine *x)
00482 {
00483 }
00484