anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
regchannel.cpp (15817B)
1 /* Registered channel 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 "regchannel.h" 15 #include "account.h" 16 #include "access.h" 17 #include "channels.h" 18 #include "config.h" 19 #include "bots.h" 20 #include "servers.h" 21 22 Serialize::Checker<registered_channel_map> RegisteredChannelList("ChannelInfo"); 23 24 AutoKick::AutoKick() : Serializable("AutoKick") 25 { 26 } 27 28 AutoKick::~AutoKick() 29 { 30 if (this->ci) 31 { 32 std::vector<AutoKick *>::iterator it = std::find(this->ci->akick->begin(), this->ci->akick->end(), this); 33 if (it != this->ci->akick->end()) 34 this->ci->akick->erase(it); 35 36 if (nc) 37 nc->RemoveChannelReference(this->ci); 38 } 39 } 40 41 void AutoKick::Serialize(Serialize::Data &data) const 42 { 43 data["ci"] << this->ci->name; 44 if (this->nc) 45 data["nc"] << this->nc->display; 46 else 47 data["mask"] << this->mask; 48 data["reason"] << this->reason; 49 data["creator"] << this->creator; 50 data.SetType("addtime", Serialize::Data::DT_INT); data["addtime"] << this->addtime; 51 data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used; 52 } 53 54 Serializable* AutoKick::Unserialize(Serializable *obj, Serialize::Data &data) 55 { 56 Anope::string sci, snc; 57 58 data["ci"] >> sci; 59 data["nc"] >> snc; 60 61 ChannelInfo *ci = ChannelInfo::Find(sci); 62 if (!ci) 63 return NULL; 64 65 AutoKick *ak; 66 NickCore *nc = NickCore::Find(snc); 67 if (obj) 68 { 69 ak = anope_dynamic_static_cast<AutoKick *>(obj); 70 data["creator"] >> ak->creator; 71 data["reason"] >> ak->reason; 72 ak->nc = NickCore::Find(snc); 73 data["mask"] >> ak->mask; 74 data["addtime"] >> ak->addtime; 75 data["last_used"] >> ak->last_used; 76 } 77 else 78 { 79 time_t addtime, lastused; 80 data["addtime"] >> addtime; 81 data["last_used"] >> lastused; 82 83 Anope::string screator, sreason, smask; 84 85 data["creator"] >> screator; 86 data["reason"] >> sreason; 87 data["mask"] >> smask; 88 89 if (nc) 90 ak = ci->AddAkick(screator, nc, sreason, addtime, lastused); 91 else 92 ak = ci->AddAkick(screator, smask, sreason, addtime, lastused); 93 } 94 95 return ak; 96 } 97 98 ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable("ChannelInfo"), 99 access("ChanAccess"), akick("AutoKick") 100 { 101 if (chname.empty()) 102 throw CoreException("Empty channel passed to ChannelInfo constructor"); 103 104 this->founder = NULL; 105 this->successor = NULL; 106 this->c = Channel::Find(chname); 107 if (this->c) 108 this->c->ci = this; 109 this->banexpire = 0; 110 this->bi = NULL; 111 this->last_topic_time = 0; 112 113 this->name = chname; 114 115 this->bantype = 2; 116 this->memos.memomax = 0; 117 this->last_used = this->time_registered = Anope::CurTime; 118 119 size_t old = RegisteredChannelList->size(); 120 (*RegisteredChannelList)[this->name] = this; 121 if (old == RegisteredChannelList->size()) 122 Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in registered channel table?"; 123 124 FOREACH_MOD(OnCreateChan, (this)); 125 } 126 127 ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"), 128 access("ChanAccess"), akick("AutoKick") 129 { 130 *this = ci; 131 132 if (this->founder) 133 ++this->founder->channelcount; 134 135 this->access->clear(); 136 this->akick->clear(); 137 138 FOREACH_MOD(OnCreateChan, (this)); 139 } 140 141 ChannelInfo::~ChannelInfo() 142 { 143 FOREACH_MOD(OnDelChan, (this)); 144 145 UnsetExtensibles(); 146 147 Log(LOG_DEBUG) << "Deleting channel " << this->name; 148 149 if (this->c) 150 { 151 if (this->bi && this->c->FindUser(this->bi)) 152 this->bi->Part(this->c); 153 154 /* Parting the service bot can cause the channel to go away */ 155 156 if (this->c) 157 { 158 if (this->c && this->c->CheckDelete()) 159 this->c->QueueForDeletion(); 160 161 this->c = NULL; 162 } 163 } 164 165 RegisteredChannelList->erase(this->name); 166 167 this->SetFounder(NULL); 168 this->SetSuccessor(NULL); 169 170 this->ClearAccess(); 171 this->ClearAkick(); 172 173 if (!this->memos.memos->empty()) 174 { 175 for (unsigned i = 0, end = this->memos.memos->size(); i < end; ++i) 176 delete this->memos.GetMemo(i); 177 this->memos.memos->clear(); 178 } 179 } 180 181 void ChannelInfo::Serialize(Serialize::Data &data) const 182 { 183 data["name"] << this->name; 184 if (this->founder) 185 data["founder"] << this->founder->display; 186 if (this->successor) 187 data["successor"] << this->successor->display; 188 data["description"] << this->desc; 189 data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered; 190 data.SetType("last_used", Serialize::Data::DT_INT); data["last_used"] << this->last_used; 191 data["last_topic"] << this->last_topic; 192 data["last_topic_setter"] << this->last_topic_setter; 193 data.SetType("last_topic_time", Serialize::Data::DT_INT); data["last_topic_time"] << this->last_topic_time; 194 data.SetType("bantype", Serialize::Data::DT_INT); data["bantype"] << this->bantype; 195 { 196 Anope::string levels_buffer; 197 for (Anope::map<int16_t>::const_iterator it = this->levels.begin(), it_end = this->levels.end(); it != it_end; ++it) 198 levels_buffer += it->first + " " + stringify(it->second) + " "; 199 data["levels"] << levels_buffer; 200 } 201 if (this->bi) 202 data["bi"] << this->bi->nick; 203 data.SetType("banexpire", Serialize::Data::DT_INT); data["banexpire"] << this->banexpire; 204 data["memomax"] << this->memos.memomax; 205 for (unsigned i = 0; i < this->memos.ignores.size(); ++i) 206 data["memoignores"] << this->memos.ignores[i] << " "; 207 208 Extensible::ExtensibleSerialize(this, this, data); 209 } 210 211 Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data) 212 { 213 Anope::string sname, sfounder, ssuccessor, slevels, sbi; 214 215 data["name"] >> sname; 216 data["founder"] >> sfounder; 217 data["successor"] >> ssuccessor; 218 data["levels"] >> slevels; 219 data["bi"] >> sbi; 220 221 ChannelInfo *ci; 222 if (obj) 223 ci = anope_dynamic_static_cast<ChannelInfo *>(obj); 224 else 225 ci = new ChannelInfo(sname); 226 227 ci->SetFounder(NickCore::Find(sfounder)); 228 ci->SetSuccessor(NickCore::Find(ssuccessor)); 229 230 data["description"] >> ci->desc; 231 data["time_registered"] >> ci->time_registered; 232 data["last_used"] >> ci->last_used; 233 data["last_topic"] >> ci->last_topic; 234 data["last_topic_setter"] >> ci->last_topic_setter; 235 data["last_topic_time"] >> ci->last_topic_time; 236 data["bantype"] >> ci->bantype; 237 { 238 std::vector<Anope::string> v; 239 spacesepstream(slevels).GetTokens(v); 240 for (unsigned i = 0; i + 1 < v.size(); i += 2) 241 try 242 { 243 ci->levels[v[i]] = convertTo<int16_t>(v[i + 1]); 244 } 245 catch (const ConvertException &) { } 246 } 247 BotInfo *bi = BotInfo::Find(sbi, true); 248 if (*ci->bi != bi) 249 { 250 if (bi) 251 bi->Assign(NULL, ci); 252 else if (ci->bi) 253 ci->bi->UnAssign(NULL, ci); 254 } 255 data["banexpire"] >> ci->banexpire; 256 data["memomax"] >> ci->memos.memomax; 257 { 258 Anope::string buf; 259 data["memoignores"] >> buf; 260 spacesepstream sep(buf); 261 ci->memos.ignores.clear(); 262 while (sep.GetToken(buf)) 263 ci->memos.ignores.push_back(buf); 264 } 265 266 Extensible::ExtensibleUnserialize(ci, ci, data); 267 268 /* compat */ 269 bool b; 270 b = false; 271 data["extensible:SECURE"] >> b; 272 if (b) 273 ci->Extend<bool>("CS_SECURE"); 274 b = false; 275 data["extensible:PRIVATE"] >> b; 276 if (b) 277 ci->Extend<bool>("CS_PRIVATE"); 278 b = false; 279 data["extensible:NO_EXPIRE"] >> b; 280 if (b) 281 ci->Extend<bool>("CS_NO_EXPIRE"); 282 b = false; 283 data["extensible:FANTASY"] >> b; 284 if (b) 285 ci->Extend<bool>("BS_FANTASY"); 286 b = false; 287 data["extensible:GREET"] >> b; 288 if (b) 289 ci->Extend<bool>("BS_GREET"); 290 b = false; 291 data["extensible:PEACE"] >> b; 292 if (b) 293 ci->Extend<bool>("PEACE"); 294 b = false; 295 data["extensible:SECUREFOUNDER"] >> b; 296 if (b) 297 ci->Extend<bool>("SECUREFOUNDER"); 298 b = false; 299 data["extensible:RESTRICTED"] >> b; 300 if (b) 301 ci->Extend<bool>("RESTRICTED"); 302 b = false; 303 data["extensible:KEEPTOPIC"] >> b; 304 if (b) 305 ci->Extend<bool>("KEEPTOPIC"); 306 b = false; 307 data["extensible:SIGNKICK"] >> b; 308 if (b) 309 ci->Extend<bool>("SIGNKICK"); 310 b = false; 311 data["extensible:SIGNKICK_LEVEL"] >> b; 312 if (b) 313 ci->Extend<bool>("SIGNKICK_LEVEL"); 314 /* end compat */ 315 316 return ci; 317 } 318 319 320 void ChannelInfo::SetFounder(NickCore *nc) 321 { 322 if (this->founder) 323 { 324 --this->founder->channelcount; 325 this->founder->RemoveChannelReference(this); 326 } 327 328 this->founder = nc; 329 330 if (this->founder) 331 { 332 ++this->founder->channelcount; 333 this->founder->AddChannelReference(this); 334 } 335 } 336 337 NickCore *ChannelInfo::GetFounder() const 338 { 339 return this->founder; 340 } 341 342 void ChannelInfo::SetSuccessor(NickCore *nc) 343 { 344 if (this->successor) 345 this->successor->RemoveChannelReference(this); 346 this->successor = nc; 347 if (this->successor) 348 this->successor->AddChannelReference(this); 349 } 350 351 NickCore *ChannelInfo::GetSuccessor() const 352 { 353 return this->successor; 354 } 355 356 BotInfo *ChannelInfo::WhoSends() const 357 { 358 if (this && this->bi) 359 return this->bi; 360 361 BotInfo *ChanServ = Config->GetClient("ChanServ"); 362 if (ChanServ) 363 return ChanServ; 364 365 if (!BotListByNick->empty()) 366 return BotListByNick->begin()->second; 367 368 return NULL; 369 } 370 371 void ChannelInfo::AddAccess(ChanAccess *taccess) 372 { 373 this->access->push_back(taccess); 374 } 375 376 ChanAccess *ChannelInfo::GetAccess(unsigned index) const 377 { 378 if (this->access->empty() || index >= this->access->size()) 379 return NULL; 380 381 ChanAccess *acc = (*this->access)[index]; 382 acc->QueueUpdate(); 383 return acc; 384 } 385 386 static void FindMatchesRecurse(ChannelInfo *ci, const User *u, const NickCore *account, unsigned int depth, std::vector<ChanAccess::Path> &paths, ChanAccess::Path &path) 387 { 388 if (depth > ChanAccess::MAX_DEPTH) 389 return; 390 391 for (unsigned int i = 0; i < ci->GetAccessCount(); ++i) 392 { 393 ChanAccess *a = ci->GetAccess(i); 394 ChannelInfo *next = NULL; 395 396 if (a->Matches(u, account, next)) 397 { 398 ChanAccess::Path next_path = path; 399 next_path.push_back(a); 400 401 paths.push_back(next_path); 402 } 403 else if (next) 404 { 405 ChanAccess::Path next_path = path; 406 next_path.push_back(a); 407 408 FindMatchesRecurse(next, u, account, depth + 1, paths, next_path); 409 } 410 } 411 } 412 413 static void FindMatches(AccessGroup &group, ChannelInfo *ci, const User *u, const NickCore *account) 414 { 415 ChanAccess::Path path; 416 FindMatchesRecurse(ci, u, account, 0, group.paths, path); 417 } 418 419 AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed) 420 { 421 AccessGroup group; 422 423 if (u == NULL) 424 return group; 425 426 const NickCore *nc = u->Account(); 427 if (nc == NULL && !this->HasExt("NS_SECURE") && u->IsRecognized()) 428 { 429 const NickAlias *na = NickAlias::Find(u->nick); 430 if (na != NULL) 431 nc = na->nc; 432 } 433 434 group.super_admin = u->super_admin; 435 group.founder = IsFounder(u, this); 436 group.ci = this; 437 group.nc = nc; 438 439 FindMatches(group, this, u, u->Account()); 440 441 if (group.founder || !group.paths.empty()) 442 { 443 if (updateLastUsed) 444 this->last_used = Anope::CurTime; 445 446 for (unsigned i = 0; i < group.paths.size(); ++i) 447 { 448 ChanAccess::Path &p = group.paths[i]; 449 450 for (unsigned int j = 0; j < p.size(); ++j) 451 p[j]->last_seen = Anope::CurTime; 452 } 453 } 454 455 return group; 456 } 457 458 AccessGroup ChannelInfo::AccessFor(const NickCore *nc, bool updateLastUsed) 459 { 460 AccessGroup group; 461 462 group.founder = (this->founder && this->founder == nc); 463 group.ci = this; 464 group.nc = nc; 465 466 FindMatches(group, this, NULL, nc); 467 468 if (group.founder || !group.paths.empty()) 469 if (updateLastUsed) 470 this->last_used = Anope::CurTime; 471 472 /* don't update access last seen here, this isn't the user requesting access */ 473 474 return group; 475 } 476 477 unsigned ChannelInfo::GetAccessCount() const 478 { 479 return this->access->size(); 480 } 481 482 static unsigned int GetDeepAccessCount(const ChannelInfo *ci, std::set<const ChannelInfo *> &seen, unsigned int depth) 483 { 484 if (depth > ChanAccess::MAX_DEPTH || seen.count(ci)) 485 return 0; 486 seen.insert(ci); 487 488 unsigned int total = 0; 489 490 for (unsigned int i = 0; i < ci->GetAccessCount(); ++i) 491 { 492 ChanAccess::Path path; 493 ChanAccess *a = ci->GetAccess(i); 494 ChannelInfo *next = NULL; 495 496 a->Matches(NULL, NULL, next); 497 ++total; 498 499 if (next) 500 total += GetDeepAccessCount(ci, seen, depth + 1); 501 } 502 503 return total; 504 } 505 506 unsigned ChannelInfo::GetDeepAccessCount() const 507 { 508 std::set<const ChannelInfo *> seen; 509 return ::GetDeepAccessCount(this, seen, 0); 510 } 511 512 ChanAccess *ChannelInfo::EraseAccess(unsigned index) 513 { 514 if (this->access->empty() || index >= this->access->size()) 515 return NULL; 516 517 ChanAccess *ca = this->access->at(index); 518 this->access->erase(this->access->begin() + index); 519 return ca; 520 } 521 522 void ChannelInfo::ClearAccess() 523 { 524 for (unsigned i = this->access->size(); i > 0; --i) 525 delete this->GetAccess(i - 1); 526 } 527 528 AutoKick *ChannelInfo::AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t, time_t lu) 529 { 530 AutoKick *autokick = new AutoKick(); 531 autokick->ci = this; 532 autokick->nc = akicknc; 533 autokick->reason = reason; 534 autokick->creator = user; 535 autokick->addtime = t; 536 autokick->last_used = lu; 537 538 this->akick->push_back(autokick); 539 540 akicknc->AddChannelReference(this); 541 542 return autokick; 543 } 544 545 AutoKick *ChannelInfo::AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t, time_t lu) 546 { 547 AutoKick *autokick = new AutoKick(); 548 autokick->ci = this; 549 autokick->mask = mask; 550 autokick->nc = NULL; 551 autokick->reason = reason; 552 autokick->creator = user; 553 autokick->addtime = t; 554 autokick->last_used = lu; 555 556 this->akick->push_back(autokick); 557 558 return autokick; 559 } 560 561 AutoKick *ChannelInfo::GetAkick(unsigned index) const 562 { 563 if (this->akick->empty() || index >= this->akick->size()) 564 return NULL; 565 566 AutoKick *ak = (*this->akick)[index]; 567 ak->QueueUpdate(); 568 return ak; 569 } 570 571 unsigned ChannelInfo::GetAkickCount() const 572 { 573 return this->akick->size(); 574 } 575 576 void ChannelInfo::EraseAkick(unsigned index) 577 { 578 if (this->akick->empty() || index >= this->akick->size()) 579 return; 580 581 delete this->GetAkick(index); 582 } 583 584 void ChannelInfo::ClearAkick() 585 { 586 while (!this->akick->empty()) 587 delete this->akick->back(); 588 } 589 590 const Anope::map<int16_t> &ChannelInfo::GetLevelEntries() 591 { 592 return this->levels; 593 } 594 595 int16_t ChannelInfo::GetLevel(const Anope::string &priv) const 596 { 597 if (PrivilegeManager::FindPrivilege(priv) == NULL) 598 { 599 Log(LOG_DEBUG) << "Unknown privilege " + priv; 600 return ACCESS_INVALID; 601 } 602 603 Anope::map<int16_t>::const_iterator it = this->levels.find(priv); 604 if (it == this->levels.end()) 605 return 0; 606 return it->second; 607 } 608 609 void ChannelInfo::SetLevel(const Anope::string &priv, int16_t level) 610 { 611 if (PrivilegeManager::FindPrivilege(priv) == NULL) 612 { 613 Log(LOG_DEBUG) << "Unknown privilege " + priv; 614 return; 615 } 616 617 this->levels[priv] = level; 618 } 619 620 void ChannelInfo::RemoveLevel(const Anope::string &priv) 621 { 622 this->levels.erase(priv); 623 } 624 625 void ChannelInfo::ClearLevels() 626 { 627 this->levels.clear(); 628 } 629 630 Anope::string ChannelInfo::GetIdealBan(User *u) const 631 { 632 int bt = this ? this->bantype : -1; 633 switch (bt) 634 { 635 case 0: 636 return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost(); 637 case 1: 638 if (u->GetVIdent()[0] == '~') 639 return "*!*" + u->GetVIdent() + "@" + u->GetDisplayedHost(); 640 else 641 return "*!" + u->GetVIdent() + "@" + u->GetDisplayedHost(); 642 case 3: 643 return "*!" + u->Mask(); 644 case 2: 645 default: 646 return "*!*@" + u->GetDisplayedHost(); 647 } 648 } 649 650 ChannelInfo* ChannelInfo::Find(const Anope::string &name) 651 { 652 registered_channel_map::const_iterator it = RegisteredChannelList->find(name); 653 if (it != RegisteredChannelList->end()) 654 { 655 it->second->QueueUpdate(); 656 return it->second; 657 } 658 659 return NULL; 660 } 661 662 bool IsFounder(const User *user, const ChannelInfo *ci) 663 { 664 if (!user || !ci) 665 return false; 666 667 if (user->super_admin) 668 return true; 669 670 if (user->Account() && user->Account() == ci->GetFounder()) 671 return true; 672 673 return false; 674 } 675 676 677 void ChannelInfo::AddChannelReference(const Anope::string &what) 678 { 679 ++references[what]; 680 } 681 682 void ChannelInfo::RemoveChannelReference(const Anope::string &what) 683 { 684 int &i = references[what]; 685 if (--i <= 0) 686 references.erase(what); 687 } 688 689 void ChannelInfo::GetChannelReferences(std::deque<Anope::string> &chans) 690 { 691 chans.clear(); 692 for (Anope::map<int>::iterator it = references.begin(); it != references.end(); ++it) 693 chans.push_back(it->first); 694 }