anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
channels.cpp (23936B)
1 /* Channel-handling routines. 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 "channels.h" 14 #include "regchannel.h" 15 #include "logger.h" 16 #include "modules.h" 17 #include "users.h" 18 #include "bots.h" 19 #include "servers.h" 20 #include "protocol.h" 21 #include "users.h" 22 #include "config.h" 23 #include "access.h" 24 #include "sockets.h" 25 #include "language.h" 26 #include "uplink.h" 27 28 channel_map ChannelList; 29 std::vector<Channel *> Channel::deleting; 30 31 Channel::Channel(const Anope::string &nname, time_t ts) 32 { 33 if (nname.empty()) 34 throw CoreException("A channel without a name ?"); 35 36 this->name = nname; 37 38 this->creation_time = ts; 39 this->syncing = this->botchannel = false; 40 this->server_modetime = this->chanserv_modetime = 0; 41 this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_ts = this->topic_time = 0; 42 43 this->ci = ChannelInfo::Find(this->name); 44 if (this->ci) 45 this->ci->c = this; 46 47 if (Me && Me->IsSynced()) 48 Log(NULL, this, "create"); 49 50 FOREACH_MOD(OnChannelCreate, (this)); 51 } 52 53 Channel::~Channel() 54 { 55 UnsetExtensibles(); 56 57 FOREACH_MOD(OnChannelDelete, (this)); 58 59 ModeManager::StackerDel(this); 60 61 if (Me && Me->IsSynced()) 62 Log(NULL, this, "destroy"); 63 64 if (this->ci) 65 this->ci->c = NULL; 66 67 ChannelList.erase(this->name); 68 } 69 70 void Channel::Reset() 71 { 72 this->modes.clear(); 73 74 for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) 75 { 76 ChanUserContainer *uc = it->second; 77 78 ChannelStatus f = uc->status; 79 uc->status.Clear(); 80 81 /* reset modes for my clients */ 82 if (uc->user->server == Me) 83 { 84 for (size_t i = 0; i < f.Modes().length(); ++i) 85 this->SetMode(NULL, ModeManager::FindChannelModeByChar(f.Modes()[i]), uc->user->GetUID(), false); 86 /* Modes might not exist yet, so be sure the status is really reset */ 87 uc->status = f; 88 } 89 } 90 91 for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) 92 this->SetCorrectModes(it->second->user, true); 93 94 // If the channel is syncing now, do not force a sync due to Reset(), as we are probably iterating over users in Message::SJoin 95 // A sync will come soon 96 if (!syncing) 97 this->Sync(); 98 } 99 100 void Channel::Sync() 101 { 102 syncing = false; 103 FOREACH_MOD(OnChannelSync, (this)); 104 CheckModes(); 105 } 106 107 void Channel::CheckModes() 108 { 109 if (this->bouncy_modes || this->syncing) 110 return; 111 112 /* Check for mode bouncing */ 113 if (this->chanserv_modetime == Anope::CurTime && this->server_modetime == Anope::CurTime && this->server_modecount >= 3 && this->chanserv_modecount >= 3) 114 { 115 Log() << "Warning: unable to set modes on channel " << this->name << ". Are your servers' U:lines configured correctly?"; 116 this->bouncy_modes = 1; 117 return; 118 } 119 120 Reference<Channel> ref = this; 121 FOREACH_MOD(OnCheckModes, (ref)); 122 } 123 124 bool Channel::CheckDelete() 125 { 126 /* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediately 127 * We also don't part the bot here either, if necessary we will part it after the sync 128 */ 129 if (this->syncing) 130 return false; 131 132 /* Permanent channels never get deleted */ 133 if (this->HasMode("PERM")) 134 return false; 135 136 EventReturn MOD_RESULT; 137 FOREACH_RESULT(OnCheckDelete, MOD_RESULT, (this)); 138 139 return MOD_RESULT != EVENT_STOP && this->users.empty(); 140 } 141 142 ChanUserContainer* Channel::JoinUser(User *user, const ChannelStatus *status) 143 { 144 if (user->server && user->server->IsSynced()) 145 Log(user, this, "join"); 146 147 ChanUserContainer *cuc = new ChanUserContainer(user, this); 148 user->chans[this] = cuc; 149 this->users[user] = cuc; 150 if (status) 151 cuc->status = *status; 152 153 return cuc; 154 } 155 156 void Channel::DeleteUser(User *user) 157 { 158 if (user->server && user->server->IsSynced() && !user->Quitting()) 159 Log(user, this, "leave"); 160 161 FOREACH_MOD(OnLeaveChannel, (user, this)); 162 163 ChanUserContainer *cu = user->FindChannel(this); 164 if (!this->users.erase(user)) 165 Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistent user " << user->nick << " from channel " << this->name; 166 167 if (!user->chans.erase(this)) 168 Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistent channel " << this->name << " from " << user->nick << "'s channel list"; 169 delete cu; 170 171 QueueForDeletion(); 172 } 173 174 ChanUserContainer *Channel::FindUser(User *u) const 175 { 176 ChanUserList::const_iterator it = this->users.find(u); 177 if (it != this->users.end()) 178 return it->second; 179 return NULL; 180 } 181 182 bool Channel::HasUserStatus(User *u, ChannelModeStatus *cms) 183 { 184 /* Usually its more efficient to search the users channels than the channels users */ 185 ChanUserContainer *cc = u->FindChannel(this); 186 if (cc) 187 { 188 if (cms) 189 return cc->status.HasMode(cms->mchar); 190 else 191 return cc->status.Empty(); 192 } 193 194 return false; 195 } 196 197 bool Channel::HasUserStatus(User *u, const Anope::string &mname) 198 { 199 return HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(ModeManager::FindChannelModeByName(mname))); 200 } 201 202 size_t Channel::HasMode(const Anope::string &mname, const Anope::string ¶m) 203 { 204 if (param.empty()) 205 return modes.count(mname); 206 std::vector<Anope::string> v = this->GetModeList(mname); 207 for (unsigned int i = 0; i < v.size(); ++i) 208 if (v[i].equals_ci(param)) 209 return 1; 210 return 0; 211 } 212 213 Anope::string Channel::GetModes(bool complete, bool plus) 214 { 215 Anope::string res, params; 216 217 for (std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it) 218 { 219 ChannelMode *cm = ModeManager::FindChannelModeByName(it->first); 220 if (!cm || cm->type == MODE_LIST) 221 continue; 222 223 res += cm->mchar; 224 225 if (complete && !it->second.empty()) 226 { 227 ChannelModeParam *cmp = NULL; 228 if (cm->type == MODE_PARAM) 229 cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm); 230 231 if (plus || !cmp || !cmp->minus_no_arg) 232 params += " " + it->second; 233 } 234 } 235 236 return res + params; 237 } 238 239 const Channel::ModeList &Channel::GetModes() const 240 { 241 return this->modes; 242 } 243 244 template<typename F, typename S> 245 struct second 246 { 247 S operator()(const std::pair<F, S> &p) 248 { 249 return p.second; 250 } 251 }; 252 253 std::vector<Anope::string> Channel::GetModeList(const Anope::string &mname) 254 { 255 std::vector<Anope::string> r; 256 std::transform(modes.lower_bound(mname), modes.upper_bound(mname), std::back_inserter(r), second<Anope::string, Anope::string>()); 257 return r; 258 } 259 260 void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock) 261 { 262 if (!ocm) 263 return; 264 265 Anope::string param = oparam; 266 ChannelMode *cm = ocm->Unwrap(param); 267 268 EventReturn MOD_RESULT; 269 270 /* Setting v/h/o/a/q etc */ 271 if (cm->type == MODE_STATUS) 272 { 273 if (param.empty()) 274 { 275 Log() << "Channel::SetModeInternal() mode " << cm->mchar << " with no parameter for channel " << this->name; 276 return; 277 } 278 279 User *u = User::Find(param); 280 281 if (!u) 282 { 283 Log(LOG_DEBUG) << "MODE " << this->name << " +" << cm->mchar << " for nonexistent user " << param; 284 return; 285 } 286 287 Log(LOG_DEBUG) << "Setting +" << cm->mchar << " on " << this->name << " for " << u->nick; 288 289 /* Set the status on the user */ 290 ChanUserContainer *cc = u->FindChannel(this); 291 if (cc) 292 cc->status.AddMode(cm->mchar); 293 294 FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param)); 295 296 /* Enforce secureops, etc */ 297 if (enforce_mlock && MOD_RESULT != EVENT_STOP) 298 this->SetCorrectModes(u, false); 299 return; 300 } 301 302 if (cm->type != MODE_LIST) 303 this->modes.erase(cm->name); 304 else if (this->HasMode(cm->name, param)) 305 return; 306 307 this->modes.insert(std::make_pair(cm->name, param)); 308 309 if (param.empty() && cm->type != MODE_REGULAR) 310 { 311 Log() << "Channel::SetModeInternal() mode " << cm->mchar << " for " << this->name << " with no paramater, but is a param mode"; 312 return; 313 } 314 315 if (cm->type == MODE_LIST) 316 { 317 ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); 318 cml->OnAdd(this, param); 319 } 320 321 FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param)); 322 323 /* Check if we should enforce mlock */ 324 if (!enforce_mlock || MOD_RESULT == EVENT_STOP) 325 return; 326 327 this->CheckModes(); 328 } 329 330 void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock) 331 { 332 if (!ocm) 333 return; 334 335 Anope::string param = oparam; 336 ChannelMode *cm = ocm->Unwrap(param); 337 338 EventReturn MOD_RESULT; 339 340 /* Setting v/h/o/a/q etc */ 341 if (cm->type == MODE_STATUS) 342 { 343 if (param.empty()) 344 { 345 Log() << "Channel::RemoveModeInternal() mode " << cm->mchar << " with no parameter for channel " << this->name; 346 return; 347 } 348 349 BotInfo *bi = BotInfo::Find(param); 350 User *u = bi ? bi : User::Find(param); 351 352 if (!u) 353 { 354 Log(LOG_DEBUG) << "Channel::RemoveModeInternal() MODE " << this->name << "-" << cm->mchar << " for nonexistent user " << param; 355 return; 356 } 357 358 Log(LOG_DEBUG) << "Setting -" << cm->mchar << " on " << this->name << " for " << u->nick; 359 360 /* Remove the status on the user */ 361 ChanUserContainer *cc = u->FindChannel(this); 362 if (cc) 363 cc->status.DelMode(cm->mchar); 364 365 FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param)); 366 367 if (enforce_mlock && MOD_RESULT != EVENT_STOP) 368 this->SetCorrectModes(u, false); 369 370 return; 371 } 372 373 if (cm->type == MODE_LIST) 374 { 375 for (Channel::ModeList::iterator it = modes.lower_bound(cm->name), it_end = modes.upper_bound(cm->name); it != it_end; ++it) 376 if (param.equals_ci(it->second)) 377 { 378 this->modes.erase(it); 379 break; 380 } 381 } 382 else 383 this->modes.erase(cm->name); 384 385 if (cm->type == MODE_LIST) 386 { 387 ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); 388 cml->OnDel(this, param); 389 } 390 391 FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param)); 392 393 if (cm->name == "PERM") 394 { 395 if (this->CheckDelete()) 396 { 397 delete this; 398 return; 399 } 400 } 401 402 /* Check for mlock */ 403 if (!enforce_mlock || MOD_RESULT == EVENT_STOP) 404 return; 405 406 this->CheckModes(); 407 } 408 409 void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock) 410 { 411 Anope::string wparam = param; 412 if (!cm) 413 return; 414 /* Don't set modes already set */ 415 if (cm->type == MODE_REGULAR && HasMode(cm->name)) 416 return; 417 else if (cm->type == MODE_PARAM) 418 { 419 ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm); 420 if (!cmp->IsValid(wparam)) 421 return; 422 423 Anope::string cparam; 424 if (GetParam(cm->name, cparam) && cparam.equals_cs(wparam)) 425 return; 426 } 427 else if (cm->type == MODE_STATUS) 428 { 429 User *u = User::Find(param); 430 if (!u || HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm))) 431 return; 432 } 433 else if (cm->type == MODE_LIST) 434 { 435 ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); 436 437 if (!cml->IsValid(wparam)) 438 return; 439 440 if (this->HasMode(cm->name, wparam)) 441 return; 442 } 443 444 if (Me->IsSynced()) 445 { 446 if (this->chanserv_modetime != Anope::CurTime) 447 { 448 this->chanserv_modecount = 0; 449 this->chanserv_modetime = Anope::CurTime; 450 } 451 452 this->chanserv_modecount++; 453 } 454 455 ChannelMode *wcm = cm->Wrap(wparam); 456 457 ModeManager::StackerAdd(bi, this, wcm, true, wparam); 458 MessageSource ms(bi); 459 SetModeInternal(ms, wcm, wparam, enforce_mlock); 460 } 461 462 void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock) 463 { 464 SetMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock); 465 } 466 467 void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &wparam, bool enforce_mlock) 468 { 469 if (!cm) 470 return; 471 472 /* Don't unset modes that arent set */ 473 if ((cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && !HasMode(cm->name)) 474 return; 475 476 /* Unwrap to be sure we have the internal representation */ 477 Anope::string param = wparam; 478 cm = cm->Unwrap(param); 479 480 /* Don't unset status that aren't set */ 481 if (cm->type == MODE_STATUS) 482 { 483 User *u = User::Find(param); 484 if (!u || !HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm))) 485 return; 486 } 487 else if (cm->type == MODE_LIST) 488 { 489 if (!this->HasMode(cm->name, param)) 490 return; 491 } 492 493 /* Get the param to send, if we need it */ 494 if (cm->type == MODE_PARAM) 495 { 496 param.clear(); 497 ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm); 498 if (!cmp->minus_no_arg) 499 this->GetParam(cmp->name, param); 500 } 501 502 if (Me->IsSynced()) 503 { 504 if (this->chanserv_modetime != Anope::CurTime) 505 { 506 this->chanserv_modecount = 0; 507 this->chanserv_modetime = Anope::CurTime; 508 } 509 510 this->chanserv_modecount++; 511 } 512 513 /* Wrap to get ircd representation */ 514 ChannelMode *wcm = cm->Wrap(param); 515 516 ModeManager::StackerAdd(bi, this, wcm, false, param); 517 MessageSource ms(bi); 518 RemoveModeInternal(ms, wcm, param, enforce_mlock); 519 } 520 521 void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock) 522 { 523 RemoveMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock); 524 } 525 526 bool Channel::GetParam(const Anope::string &mname, Anope::string &target) const 527 { 528 std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.find(mname); 529 530 target.clear(); 531 532 if (it != this->modes.end()) 533 { 534 target = it->second; 535 return true; 536 } 537 538 return false; 539 } 540 541 void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...) 542 { 543 char buf[BUFSIZE] = ""; 544 va_list args; 545 Anope::string modebuf, sbuf; 546 int add = -1; 547 va_start(args, cmodes); 548 vsnprintf(buf, BUFSIZE - 1, cmodes, args); 549 va_end(args); 550 551 Reference<Channel> this_reference(this); 552 553 spacesepstream sep(buf); 554 sep.GetToken(modebuf); 555 for (unsigned i = 0, end = modebuf.length(); this_reference && i < end; ++i) 556 { 557 ChannelMode *cm; 558 559 switch (modebuf[i]) 560 { 561 case '+': 562 add = 1; 563 continue; 564 case '-': 565 add = 0; 566 continue; 567 default: 568 if (add == -1) 569 continue; 570 cm = ModeManager::FindChannelModeByChar(modebuf[i]); 571 if (!cm) 572 continue; 573 } 574 575 if (add) 576 { 577 if (cm->type != MODE_REGULAR && sep.GetToken(sbuf)) 578 { 579 if (cm->type == MODE_STATUS) 580 { 581 User *targ = User::Find(sbuf); 582 if (targ != NULL) 583 sbuf = targ->GetUID(); 584 } 585 this->SetMode(bi, cm, sbuf, enforce_mlock); 586 } 587 else 588 this->SetMode(bi, cm, "", enforce_mlock); 589 } 590 else if (!add) 591 { 592 if (cm->type != MODE_REGULAR && sep.GetToken(sbuf)) 593 { 594 if (cm->type == MODE_STATUS) 595 { 596 User *targ = User::Find(sbuf); 597 if (targ != NULL) 598 sbuf = targ->GetUID(); 599 } 600 this->RemoveMode(bi, cm, sbuf, enforce_mlock); 601 } 602 else 603 this->RemoveMode(bi, cm, "", enforce_mlock); 604 } 605 } 606 } 607 608 void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts, bool enforce_mlock) 609 { 610 if (!ts) 611 ; 612 else if (ts > this->creation_time) 613 { 614 Log(LOG_DEBUG) << "Dropping mode " << mode << " on " << this->name << ", " << ts << " > " << this->creation_time; 615 return; 616 } 617 else if (ts < this->creation_time) 618 { 619 Log(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << ts; 620 this->creation_time = ts; 621 this->Reset(); 622 } 623 624 User *setter = source.GetUser(); 625 /* Removing channel modes *may* delete this channel */ 626 Reference<Channel> this_reference(this); 627 628 spacesepstream sep_modes(mode); 629 Anope::string m; 630 631 sep_modes.GetToken(m); 632 633 Anope::string modestring; 634 Anope::string paramstring; 635 int add = -1; 636 bool changed = false; 637 for (unsigned int i = 0, end = m.length(); i < end && this_reference; ++i) 638 { 639 ChannelMode *cm; 640 641 switch (m[i]) 642 { 643 case '+': 644 modestring += '+'; 645 add = 1; 646 continue; 647 case '-': 648 modestring += '-'; 649 add = 0; 650 continue; 651 default: 652 if (add == -1) 653 continue; 654 cm = ModeManager::FindChannelModeByChar(m[i]); 655 if (!cm) 656 { 657 Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << m[i]; 658 continue; 659 } 660 modestring += cm->mchar; 661 } 662 663 if (cm->type == MODE_REGULAR) 664 { 665 /* something changed if we are adding a mode we don't have, or removing one we have */ 666 changed |= !!add != this->HasMode(cm->name); 667 if (add) 668 this->SetModeInternal(source, cm, "", false); 669 else 670 this->RemoveModeInternal(source, cm, "", false); 671 continue; 672 } 673 else if (cm->type == MODE_PARAM) 674 { 675 ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm); 676 677 if (!add && cmp->minus_no_arg) 678 { 679 this->RemoveModeInternal(source, cm, "", false); 680 continue; 681 } 682 } 683 Anope::string token; 684 if (sep_modes.GetToken(token)) 685 { 686 User *u = NULL; 687 if (cm->type == MODE_STATUS && (u = User::Find(token))) 688 paramstring += " " + u->nick; 689 else 690 paramstring += " " + token; 691 692 changed |= !!add != this->HasMode(cm->name, token); 693 /* CheckModes below doesn't check secureops (+ the module event) */ 694 if (add) 695 this->SetModeInternal(source, cm, token, enforce_mlock); 696 else 697 this->RemoveModeInternal(source, cm, token, enforce_mlock); 698 } 699 else 700 Log() << "warning: Channel::SetModesInternal() received more modes requiring params than params, modes: " << mode; 701 } 702 703 if (!this_reference) 704 return; 705 706 if (changed && source.GetServer() && source.GetServer()->IsSynced()) 707 { 708 if (Anope::CurTime != this->server_modetime) 709 { 710 this->server_modecount = 0; 711 this->server_modetime = Anope::CurTime; 712 } 713 714 ++this->server_modecount; 715 } 716 717 if (setter) 718 Log(setter, this, "mode") << modestring << paramstring; 719 else 720 Log(LOG_DEBUG) << source.GetName() << " is setting " << this->name << " to " << modestring << paramstring; 721 722 if (enforce_mlock) 723 this->CheckModes(); 724 } 725 726 bool Channel::MatchesList(User *u, const Anope::string &mode) 727 { 728 if (!this->HasMode(mode)) 729 return false; 730 731 std::vector<Anope::string> v = this->GetModeList(mode); 732 for (unsigned i = 0; i < v.size(); ++i) 733 { 734 Entry e(mode, v[i]); 735 if (e.Matches(u)) 736 return true; 737 } 738 739 return false; 740 } 741 742 void Channel::KickInternal(const MessageSource &source, const Anope::string &nick, const Anope::string &reason) 743 { 744 User *sender = source.GetUser(); 745 User *target = User::Find(nick); 746 if (!target) 747 { 748 Log(LOG_DEBUG) << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason; 749 return; 750 } 751 752 if (sender) 753 Log(sender, this, "kick") << "kicked " << target->nick << " (" << reason << ")"; 754 else 755 Log(target, this, "kick") << "was kicked by " << source.GetName() << " (" << reason << ")"; 756 757 Anope::string chname = this->name; 758 759 ChanUserContainer *cu = target->FindChannel(this); 760 if (cu == NULL) 761 { 762 Log(LOG_DEBUG) << "Channel::KickInternal got kick for user " << target->nick << " from " << source.GetSource() << " who isn't on channel " << this->name; 763 return; 764 } 765 766 ChannelStatus status = cu->status; 767 768 FOREACH_MOD(OnPreUserKicked, (source, cu, reason)); 769 this->DeleteUser(target); 770 FOREACH_MOD(OnUserKicked, (source, target, this->name, status, reason)); 771 } 772 773 bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) 774 { 775 va_list args; 776 char buf[BUFSIZE] = ""; 777 va_start(args, reason); 778 vsnprintf(buf, BUFSIZE - 1, reason, args); 779 va_end(args); 780 781 /* Do not kick protected clients or Ulines */ 782 if (u->IsProtected()) 783 return false; 784 785 if (bi == NULL) 786 bi = this->ci->WhoSends(); 787 788 EventReturn MOD_RESULT; 789 FOREACH_RESULT(OnBotKick, MOD_RESULT, (bi, this, u, buf)); 790 if (MOD_RESULT == EVENT_STOP) 791 return false; 792 IRCD->SendKick(bi, this, u, "%s", buf); 793 this->KickInternal(bi, u->nick, buf); 794 return true; 795 } 796 797 void Channel::ChangeTopicInternal(User *u, const Anope::string &user, const Anope::string &newtopic, time_t ts) 798 { 799 this->topic = newtopic; 800 this->topic_setter = u ? u->nick : user; 801 this->topic_ts = ts; 802 this->topic_time = Anope::CurTime; 803 804 Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << this->topic_setter << " to " << newtopic; 805 806 FOREACH_MOD(OnTopicUpdated, (u, this, user, this->topic)); 807 } 808 809 void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts) 810 { 811 this->topic = newtopic; 812 this->topic_setter = user; 813 this->topic_ts = ts; 814 815 IRCD->SendTopic(this->ci->WhoSends(), this); 816 817 /* Now that the topic is set update the time set. This is *after* we set it so the protocol modules are able to tell the old last set time */ 818 this->topic_time = Anope::CurTime; 819 820 FOREACH_MOD(OnTopicUpdated, (NULL, this, user, this->topic)); 821 } 822 823 void Channel::SetCorrectModes(User *user, bool give_modes) 824 { 825 if (user == NULL) 826 return; 827 828 if (!this->ci) 829 return; 830 831 Log(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << this->name << " (" << (give_modes ? "" : "not ") << "giving modes)"; 832 833 AccessGroup u_access = ci->AccessFor(user); 834 835 /* Initially only take modes if the channel is being created by a non netmerge */ 836 bool take_modes = this->syncing && user->server->IsSynced(); 837 838 FOREACH_MOD(OnSetCorrectModes, (user, this, u_access, give_modes, take_modes)); 839 840 /* Never take modes from ulines */ 841 if (user->server->IsULined()) 842 take_modes = false; 843 844 /* whether or not we are giving modes */ 845 bool giving = give_modes; 846 /* whether or not we have given a mode */ 847 bool given = false; 848 for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i) 849 { 850 ChannelModeStatus *cm = ModeManager::GetStatusChannelModesByRank()[i]; 851 bool has_priv = u_access.HasPriv("AUTO" + cm->name); 852 853 if (give_modes && has_priv) 854 { 855 /* Always give op. If we have already given one mode, don't give more until it has a symbol */ 856 if (cm->name == "OP" || !given || (giving && cm->symbol)) 857 { 858 this->SetMode(NULL, cm, user->GetUID(), false); 859 /* Now if this contains a symbol don't give any more modes, to prevent setting +qaohv etc on users */ 860 giving = !cm->symbol; 861 given = true; 862 } 863 } 864 /* modes that have no privileges assigned shouldn't be removed (like operprefix, ojoin) */ 865 else if (take_modes && !has_priv && ci->GetLevel(cm->name + "ME") != ACCESS_INVALID && !u_access.HasPriv(cm->name + "ME")) 866 { 867 /* Only remove modes if they are > voice */ 868 if (cm->name == "VOICE") 869 take_modes = false; 870 else 871 this->RemoveMode(NULL, cm, user->GetUID(), false); 872 } 873 } 874 } 875 876 bool Channel::Unban(User *u, const Anope::string &mode, bool full) 877 { 878 if (!this->HasMode(mode)) 879 return false; 880 881 bool ret = false; 882 883 std::vector<Anope::string> v = this->GetModeList(mode); 884 for (unsigned int i = 0; i < v.size(); ++i) 885 { 886 Entry ban(mode, v[i]); 887 if (ban.Matches(u, full)) 888 { 889 this->RemoveMode(NULL, mode, ban.GetMask()); 890 ret = true; 891 } 892 } 893 894 return ret; 895 } 896 897 bool Channel::CheckKick(User *user) 898 { 899 if (user->super_admin) 900 return false; 901 902 /* We don't enforce services restrictions on clients on ulined services 903 * as this will likely lead to kick/rejoin floods. ~ Viper */ 904 if (user->IsProtected()) 905 return false; 906 907 Anope::string mask, reason; 908 909 EventReturn MOD_RESULT; 910 FOREACH_RESULT(OnCheckKick, MOD_RESULT, (user, this, mask, reason)); 911 if (MOD_RESULT != EVENT_STOP) 912 return false; 913 914 if (mask.empty()) 915 mask = this->ci->GetIdealBan(user); 916 if (reason.empty()) 917 reason = Language::Translate(user->Account(), CHAN_NOT_ALLOWED_TO_JOIN); 918 919 Log(LOG_DEBUG) << "Autokicking " << user->nick << " (" << mask << ") from " << this->name; 920 921 this->SetMode(NULL, "BAN", mask); 922 this->Kick(NULL, user, "%s", reason.c_str()); 923 924 return true; 925 } 926 927 Channel* Channel::Find(const Anope::string &name) 928 { 929 channel_map::const_iterator it = ChannelList.find(name); 930 931 if (it != ChannelList.end()) 932 return it->second; 933 return NULL; 934 } 935 936 Channel *Channel::FindOrCreate(const Anope::string &name, bool &created, time_t ts) 937 { 938 Channel* &chan = ChannelList[name]; 939 created = chan == NULL; 940 if (!chan) 941 chan = new Channel(name, ts); 942 return chan; 943 } 944 945 void Channel::QueueForDeletion() 946 { 947 if (std::find(deleting.begin(), deleting.end(), this) == deleting.end()) 948 deleting.push_back(this); 949 } 950 951 void Channel::DeleteChannels() 952 { 953 for (unsigned int i = 0; i < deleting.size(); ++i) 954 { 955 Channel *c = deleting[i]; 956 957 if (c->CheckDelete()) 958 delete c; 959 } 960 deleting.clear(); 961 }