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 }