anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
modes.cpp (21521B)
1 /* Mode support 2 * 3 * (C) 2008-2011 Adam <Adam@anope.org> 4 * (C) 2008-2022 Anope Team <team@anope.org> 5 * 6 * Please read COPYING and README for further details. 7 */ 8 9 #include "services.h" 10 #include "modules.h" 11 #include "config.h" 12 #include "sockets.h" 13 #include "protocol.h" 14 #include "channels.h" 15 #include "uplink.h" 16 17 struct StackerInfo; 18 19 /* List of pairs of user/channels and their stacker info */ 20 static std::map<User *, StackerInfo *> UserStackerObjects; 21 static std::map<Channel *, StackerInfo *> ChannelStackerObjects; 22 23 /* Array of all modes Anope knows about.*/ 24 static std::vector<ChannelMode *> ChannelModes; 25 static std::vector<UserMode *> UserModes; 26 27 /* Modes are in this array are at position 28 * modechar. Additionally, status modes are in this array (again) at statuschar. 29 */ 30 static std::vector<ChannelMode *> ChannelModesIdx; 31 static std::vector<UserMode *> UserModesIdx; 32 33 static std::map<Anope::string, ChannelMode *> ChannelModesByName; 34 static std::map<Anope::string, UserMode *> UserModesByName; 35 36 /* Sorted by status */ 37 static std::vector<ChannelModeStatus *> ChannelModesByStatus; 38 39 /* Number of generic modes we support */ 40 unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0; 41 42 struct StackerInfo 43 { 44 /* Modes to be added */ 45 std::list<std::pair<Mode *, Anope::string> > AddModes; 46 /* Modes to be deleted */ 47 std::list<std::pair<Mode *, Anope::string> > DelModes; 48 /* Bot this is sent from */ 49 BotInfo *bi; 50 51 StackerInfo() : bi(NULL) { } 52 53 /** Add a mode to this object 54 * @param mode The mode 55 * @param set true if setting, false if unsetting 56 * @param param The param for the mode 57 */ 58 void AddMode(Mode *mode, bool set, const Anope::string ¶m); 59 }; 60 61 ChannelStatus::ChannelStatus() 62 { 63 } 64 65 ChannelStatus::ChannelStatus(const Anope::string &m) : modes(m) 66 { 67 } 68 69 void ChannelStatus::AddMode(char c) 70 { 71 if (modes.find(c) == Anope::string::npos) 72 modes.append(c); 73 } 74 75 void ChannelStatus::DelMode(char c) 76 { 77 modes = modes.replace_all_cs(c, ""); 78 } 79 80 bool ChannelStatus::HasMode(char c) const 81 { 82 return modes.find(c) != Anope::string::npos; 83 } 84 85 bool ChannelStatus::Empty() const 86 { 87 return modes.empty(); 88 } 89 90 void ChannelStatus::Clear() 91 { 92 modes.clear(); 93 } 94 95 const Anope::string &ChannelStatus::Modes() const 96 { 97 return modes; 98 } 99 100 Anope::string ChannelStatus::BuildModePrefixList() const 101 { 102 Anope::string ret; 103 104 for (size_t i = 0; i < modes.length(); ++i) 105 { 106 ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); 107 if (cm != NULL && cm->type == MODE_STATUS) 108 { 109 ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); 110 ret += cms->symbol; 111 } 112 } 113 114 return ret; 115 } 116 117 Mode::Mode(const Anope::string &mname, ModeClass mcl, char mch, ModeType mt) : name(mname), mclass(mcl), mchar(mch), type(mt) 118 { 119 } 120 121 Mode::~Mode() 122 { 123 } 124 125 bool Mode::CanSet(User *u) const 126 { 127 return true; 128 } 129 130 UserMode::UserMode(const Anope::string &un, char mch) : Mode(un, MC_USER, mch, MODE_REGULAR) 131 { 132 } 133 134 UserModeParam::UserModeParam(const Anope::string &un, char mch) : UserMode(un, mch) 135 { 136 this->type = MODE_PARAM; 137 } 138 139 ChannelMode::ChannelMode(const Anope::string &cm, char mch) : Mode(cm, MC_CHANNEL, mch, MODE_REGULAR) 140 { 141 } 142 143 bool ChannelMode::CanSet(User *u) const 144 { 145 EventReturn MOD_RESULT; 146 FOREACH_RESULT(OnCanSet, MOD_RESULT, (u, this)); 147 return MOD_RESULT != EVENT_STOP; 148 } 149 150 ChannelMode *ChannelMode::Wrap(Anope::string ¶m) 151 { 152 return this; 153 } 154 155 ChannelMode *ChannelMode::Unwrap(Anope::string ¶m) 156 { 157 for (unsigned i = 0; i < listeners.size(); ++i) 158 { 159 ChannelMode *cm = listeners[i]->Unwrap(this, param); 160 if (cm != this) 161 return cm; 162 } 163 164 return this; 165 } 166 167 ChannelMode *ChannelMode::Unwrap(ChannelMode *, Anope::string ¶m) 168 { 169 throw CoreException("Unwrap in channel mode"); 170 } 171 172 ChannelModeList::ChannelModeList(const Anope::string &cm, char mch) : ChannelMode(cm, mch) 173 { 174 this->type = MODE_LIST; 175 } 176 177 bool ChannelModeList::IsValid(Anope::string &mask) const 178 { 179 if (name == "BAN" || name == "EXCEPT" || name == "INVITEOVERRIDE") 180 mask = IRCD->NormalizeMask(mask); 181 return true; 182 } 183 184 ChannelModeParam::ChannelModeParam(const Anope::string &cm, char mch, bool ma) : ChannelMode(cm, mch), minus_no_arg(ma) 185 { 186 this->type = MODE_PARAM; 187 } 188 189 ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar, char msymbol, unsigned mlevel) : ChannelMode(mname, modeChar), symbol(msymbol), level(mlevel) 190 { 191 this->type = MODE_STATUS; 192 } 193 194 template<typename T> 195 ChannelModeVirtual<T>::ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename) : T(mname, 0) 196 , base(basename) 197 { 198 basech = ModeManager::FindChannelModeByName(base); 199 if (basech) 200 basech->listeners.push_back(this); 201 } 202 203 template<typename T> 204 ChannelModeVirtual<T>::~ChannelModeVirtual() 205 { 206 if (basech) 207 { 208 std::vector<ChannelMode *>::iterator it = std::find(basech->listeners.begin(), basech->listeners.end(), this); 209 if (it != basech->listeners.end()) 210 basech->listeners.erase(it); 211 } 212 } 213 214 template<typename T> 215 void ChannelModeVirtual<T>::Check() 216 { 217 if (basech == NULL) 218 { 219 basech = ModeManager::FindChannelModeByName(base); 220 if (basech) 221 basech->listeners.push_back(this); 222 } 223 } 224 225 template<typename T> 226 ChannelMode *ChannelModeVirtual<T>::Wrap(Anope::string ¶m) 227 { 228 return basech; 229 } 230 231 template class ChannelModeVirtual<ChannelMode>; 232 template class ChannelModeVirtual<ChannelModeList>; 233 234 bool UserModeOperOnly::CanSet(User *u) const 235 { 236 return u && u->HasMode("OPER"); 237 } 238 239 bool UserModeNoone::CanSet(User *u) const 240 { 241 return false; 242 } 243 244 bool ChannelModeKey::IsValid(Anope::string &value) const 245 { 246 if (!value.empty() && value.find(':') == Anope::string::npos && value.find(',') == Anope::string::npos) 247 return true; 248 249 return false; 250 } 251 252 bool ChannelModeOperOnly::CanSet(User *u) const 253 { 254 return u && u->HasMode("OPER"); 255 } 256 257 bool ChannelModeNoone::CanSet(User *u) const 258 { 259 return false; 260 } 261 262 void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string ¶m) 263 { 264 bool is_param = mode->type == MODE_PARAM; 265 266 std::list<std::pair<Mode *, Anope::string> > *list, *otherlist; 267 if (set) 268 { 269 list = &AddModes; 270 otherlist = &DelModes; 271 } 272 else 273 { 274 list = &DelModes; 275 otherlist = &AddModes; 276 } 277 278 /* Loop through the list and find if this mode is already on here */ 279 std::list<std::pair<Mode *, Anope::string > >::iterator it, it_end; 280 for (it = list->begin(), it_end = list->end(); it != it_end; ++it) 281 { 282 /* The param must match too (can have multiple status or list modes), but 283 * if it is a param mode it can match no matter what the param is 284 */ 285 if (it->first == mode && (is_param || param.equals_cs(it->second))) 286 { 287 list->erase(it); 288 /* It can only be on this list once */ 289 break; 290 } 291 } 292 /* If the mode is on the other list, remove it from there (eg, we don't want +o-o Adam Adam) */ 293 for (it = otherlist->begin(), it_end = otherlist->end(); it != it_end; ++it) 294 { 295 /* The param must match too (can have multiple status or list modes), but 296 * if it is a param mode it can match no matter what the param is 297 */ 298 if (it->first == mode && (is_param || param.equals_cs(it->second))) 299 { 300 otherlist->erase(it); 301 return; 302 /* Note that we return here because this is like setting + and - on the same mode within the same 303 * cycle, no change is made. This causes no problems with something like - + and -, because after the 304 * second mode change the list is empty, and the third mode change starts fresh. 305 */ 306 } 307 } 308 309 /* Add this mode and its param to our list */ 310 list->push_back(std::make_pair(mode, param)); 311 } 312 313 static class ModePipe : public Pipe 314 { 315 public: 316 void OnNotify() 317 { 318 ModeManager::ProcessModes(); 319 } 320 } *modePipe; 321 322 /** Get the stacker info for an item, if one doesn't exist it is created 323 * @param Item The user/channel etc 324 * @return The stacker info 325 */ 326 template<typename List, typename Object> 327 static StackerInfo *GetInfo(List &l, Object *o) 328 { 329 typename List::const_iterator it = l.find(o); 330 if (it != l.end()) 331 return it->second; 332 333 StackerInfo *s = new StackerInfo(); 334 l[o] = s; 335 return s; 336 } 337 338 /** Build a list of mode strings to send to the IRCd from the mode stacker 339 * @param info The stacker info for a channel or user 340 * @return a list of strings 341 */ 342 static std::list<Anope::string> BuildModeStrings(StackerInfo *info) 343 { 344 std::list<Anope::string> ret; 345 std::list<std::pair<Mode *, Anope::string> >::iterator it, it_end; 346 Anope::string buf = "+", parambuf; 347 unsigned NModes = 0; 348 349 for (it = info->AddModes.begin(), it_end = info->AddModes.end(); it != it_end; ++it) 350 { 351 if (++NModes > IRCD->MaxModes || (buf.length() + parambuf.length() > IRCD->MaxLine - 100)) // Leave room for command, channel, etc 352 { 353 ret.push_back(buf + parambuf); 354 buf = "+"; 355 parambuf.clear(); 356 NModes = 1; 357 } 358 359 buf += it->first->mchar; 360 361 if (!it->second.empty()) 362 parambuf += " " + it->second; 363 } 364 365 if (buf[buf.length() - 1] == '+') 366 buf.erase(buf.length() - 1); 367 368 buf += "-"; 369 for (it = info->DelModes.begin(), it_end = info->DelModes.end(); it != it_end; ++it) 370 { 371 if (++NModes > IRCD->MaxModes || (buf.length() + parambuf.length() > IRCD->MaxLine - 100)) // Leave room for command, channel, etc 372 { 373 ret.push_back(buf + parambuf); 374 buf = "-"; 375 parambuf.clear(); 376 NModes = 1; 377 } 378 379 buf += it->first->mchar; 380 381 if (!it->second.empty()) 382 parambuf += " " + it->second; 383 } 384 385 if (buf[buf.length() - 1] == '-') 386 buf.erase(buf.length() - 1); 387 388 if (!buf.empty()) 389 ret.push_back(buf + parambuf); 390 391 return ret; 392 } 393 394 bool ModeManager::AddUserMode(UserMode *um) 395 { 396 if (ModeManager::FindUserModeByChar(um->mchar) != NULL) 397 return false; 398 if (ModeManager::FindUserModeByName(um->name) != NULL) 399 return false; 400 401 if (um->name.empty()) 402 { 403 um->name = stringify(++GenericUserModes); 404 Log() << "ModeManager: Added generic support for user mode " << um->mchar; 405 } 406 407 unsigned want = um->mchar; 408 if (want >= UserModesIdx.size()) 409 UserModesIdx.resize(want + 1); 410 UserModesIdx[want] = um; 411 412 UserModesByName[um->name] = um; 413 414 UserModes.push_back(um); 415 416 FOREACH_MOD(OnUserModeAdd, (um)); 417 418 return true; 419 } 420 421 bool ModeManager::AddChannelMode(ChannelMode *cm) 422 { 423 if (cm->mchar && ModeManager::FindChannelModeByChar(cm->mchar) != NULL) 424 return false; 425 if (ModeManager::FindChannelModeByName(cm->name) != NULL) 426 return false; 427 428 if (cm->name.empty()) 429 { 430 cm->name = stringify(++GenericChannelModes); 431 Log() << "ModeManager: Added generic support for channel mode " << cm->mchar; 432 } 433 434 if (cm->mchar) 435 { 436 unsigned want = cm->mchar; 437 if (want >= ChannelModesIdx.size()) 438 ChannelModesIdx.resize(want + 1); 439 ChannelModesIdx[want] = cm; 440 } 441 442 if (cm->type == MODE_STATUS) 443 { 444 ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); 445 unsigned want = cms->symbol; 446 if (want >= ChannelModesIdx.size()) 447 ChannelModesIdx.resize(want + 1); 448 ChannelModesIdx[want] = cms; 449 450 RebuildStatusModes(); 451 } 452 453 ChannelModesByName[cm->name] = cm; 454 455 ChannelModes.push_back(cm); 456 457 FOREACH_MOD(OnChannelModeAdd, (cm)); 458 459 for (unsigned int i = 0; i < ChannelModes.size(); ++i) 460 ChannelModes[i]->Check(); 461 462 return true; 463 } 464 465 void ModeManager::RemoveUserMode(UserMode *um) 466 { 467 if (!um) 468 return; 469 470 unsigned want = um->mchar; 471 if (want >= UserModesIdx.size()) 472 return; 473 474 if (UserModesIdx[want] != um) 475 return; 476 477 UserModesIdx[want] = NULL; 478 479 UserModesByName.erase(um->name); 480 481 std::vector<UserMode *>::iterator it = std::find(UserModes.begin(), UserModes.end(), um); 482 if (it != UserModes.end()) 483 UserModes.erase(it); 484 485 StackerDel(um); 486 } 487 488 void ModeManager::RemoveChannelMode(ChannelMode *cm) 489 { 490 if (!cm) 491 return; 492 493 if (cm->mchar) 494 { 495 unsigned want = cm->mchar; 496 if (want >= ChannelModesIdx.size()) 497 return; 498 499 if (ChannelModesIdx[want] != cm) 500 return; 501 502 ChannelModesIdx[want] = NULL; 503 } 504 505 if (cm->type == MODE_STATUS) 506 { 507 ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm); 508 unsigned want = cms->symbol; 509 510 if (want >= ChannelModesIdx.size()) 511 return; 512 513 if (ChannelModesIdx[want] != cm) 514 return; 515 516 ChannelModesIdx[want] = NULL; 517 518 RebuildStatusModes(); 519 } 520 521 ChannelModesByName.erase(cm->name); 522 523 std::vector<ChannelMode *>::iterator it = std::find(ChannelModes.begin(), ChannelModes.end(), cm); 524 if (it != ChannelModes.end()) 525 ChannelModes.erase(it); 526 527 StackerDel(cm); 528 } 529 530 ChannelMode *ModeManager::FindChannelModeByChar(char mode) 531 { 532 unsigned want = mode; 533 if (want >= ChannelModesIdx.size()) 534 return NULL; 535 536 return ChannelModesIdx[want]; 537 } 538 539 UserMode *ModeManager::FindUserModeByChar(char mode) 540 { 541 unsigned want = mode; 542 if (want >= UserModesIdx.size()) 543 return NULL; 544 545 return UserModesIdx[want]; 546 } 547 548 ChannelMode *ModeManager::FindChannelModeByName(const Anope::string &name) 549 { 550 std::map<Anope::string, ChannelMode *>::iterator it = ChannelModesByName.find(name); 551 if (it != ChannelModesByName.end()) 552 return it->second; 553 return NULL; 554 } 555 556 UserMode *ModeManager::FindUserModeByName(const Anope::string &name) 557 { 558 std::map<Anope::string, UserMode *>::iterator it = UserModesByName.find(name); 559 if (it != UserModesByName.end()) 560 return it->second; 561 return NULL; 562 } 563 564 char ModeManager::GetStatusChar(char value) 565 { 566 unsigned want = value; 567 if (want >= ChannelModesIdx.size()) 568 return 0; 569 570 ChannelMode *cm = ChannelModesIdx[want]; 571 if (cm == NULL || cm->type != MODE_STATUS || cm->mchar == value) 572 return 0; 573 574 return cm->mchar; 575 } 576 577 const std::vector<ChannelMode *> &ModeManager::GetChannelModes() 578 { 579 return ChannelModes; 580 } 581 582 const std::vector<UserMode *> &ModeManager::GetUserModes() 583 { 584 return UserModes; 585 } 586 587 const std::vector<ChannelModeStatus *> &ModeManager::GetStatusChannelModesByRank() 588 { 589 return ChannelModesByStatus; 590 } 591 592 static struct StatusSort 593 { 594 bool operator()(ChannelModeStatus *cm1, ChannelModeStatus *cm2) const 595 { 596 return cm1->level > cm2->level; 597 } 598 } statuscmp; 599 600 void ModeManager::RebuildStatusModes() 601 { 602 ChannelModesByStatus.clear(); 603 for (unsigned j = 0; j < ChannelModesIdx.size(); ++j) 604 { 605 ChannelMode *cm = ChannelModesIdx[j]; 606 607 if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end()) 608 ChannelModesByStatus.push_back(anope_dynamic_static_cast<ChannelModeStatus *>(cm)); 609 } 610 std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp); 611 } 612 613 void ModeManager::StackerAdd(BotInfo *bi, Channel *c, ChannelMode *cm, bool Set, const Anope::string &Param) 614 { 615 StackerInfo *s = GetInfo(ChannelStackerObjects, c); 616 s->AddMode(cm, Set, Param); 617 if (bi) 618 s->bi = bi; 619 else 620 s->bi = c->ci->WhoSends(); 621 622 if (!modePipe) 623 modePipe = new ModePipe(); 624 modePipe->Notify(); 625 } 626 627 void ModeManager::StackerAdd(BotInfo *bi, User *u, UserMode *um, bool Set, const Anope::string &Param) 628 { 629 StackerInfo *s = GetInfo(UserStackerObjects, u); 630 s->AddMode(um, Set, Param); 631 if (bi) 632 s->bi = bi; 633 634 if (!modePipe) 635 modePipe = new ModePipe(); 636 modePipe->Notify(); 637 } 638 639 void ModeManager::ProcessModes() 640 { 641 if (!UserStackerObjects.empty()) 642 { 643 for (std::map<User *, StackerInfo *>::const_iterator it = UserStackerObjects.begin(), it_end = UserStackerObjects.end(); it != it_end; ++it) 644 { 645 User *u = it->first; 646 StackerInfo *s = it->second; 647 648 std::list<Anope::string> ModeStrings = BuildModeStrings(s); 649 for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit) 650 IRCD->SendMode(s->bi, u, "%s", lit->c_str()); 651 delete it->second; 652 } 653 UserStackerObjects.clear(); 654 } 655 656 if (!ChannelStackerObjects.empty()) 657 { 658 for (std::map<Channel *, StackerInfo *>::const_iterator it = ChannelStackerObjects.begin(), it_end = ChannelStackerObjects.end(); it != it_end; ++it) 659 { 660 Channel *c = it->first; 661 StackerInfo *s = it->second; 662 663 std::list<Anope::string> ModeStrings = BuildModeStrings(s); 664 for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit) 665 IRCD->SendMode(s->bi, c, "%s", lit->c_str()); 666 delete it->second; 667 } 668 ChannelStackerObjects.clear(); 669 } 670 } 671 672 template<typename T> 673 static void StackerDel(std::map<T *, StackerInfo *> &map, T *obj) 674 { 675 typename std::map<T *, StackerInfo *>::iterator it = map.find(obj); 676 if (it != map.end()) 677 { 678 StackerInfo *si = it->second; 679 std::list<Anope::string> ModeStrings = BuildModeStrings(si); 680 for (std::list<Anope::string>::iterator lit = ModeStrings.begin(), lit_end = ModeStrings.end(); lit != lit_end; ++lit) 681 IRCD->SendMode(si->bi, obj, "%s", lit->c_str()); 682 683 delete si; 684 map.erase(it); 685 } 686 } 687 688 void ModeManager::StackerDel(User *u) 689 { 690 ::StackerDel(UserStackerObjects, u); 691 } 692 693 void ModeManager::StackerDel(Channel *c) 694 { 695 ::StackerDel(ChannelStackerObjects, c); 696 } 697 698 void ModeManager::StackerDel(Mode *m) 699 { 700 for (std::map<User *, StackerInfo *>::const_iterator it = UserStackerObjects.begin(), it_end = UserStackerObjects.end(); it != it_end;) 701 { 702 StackerInfo *si = it->second; 703 ++it; 704 705 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;) 706 { 707 if (it2->first == m) 708 it2 = si->AddModes.erase(it2); 709 else 710 ++it2; 711 } 712 713 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;) 714 { 715 if (it2->first == m) 716 it2 = si->DelModes.erase(it2); 717 else 718 ++it2; 719 } 720 } 721 722 for (std::map<Channel *, StackerInfo *>::const_iterator it = ChannelStackerObjects.begin(), it_end = ChannelStackerObjects.end(); it != it_end;) 723 { 724 StackerInfo *si = it->second; 725 ++it; 726 727 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->AddModes.begin(), it2_end = si->AddModes.end(); it2 != it2_end;) 728 { 729 if (it2->first == m) 730 it2 = si->AddModes.erase(it2); 731 else 732 ++it2; 733 } 734 735 for (std::list<std::pair<Mode *, Anope::string> >::iterator it2 = si->DelModes.begin(), it2_end = si->DelModes.end(); it2 != it2_end;) 736 { 737 if (it2->first == m) 738 it2 = si->DelModes.erase(it2); 739 else 740 ++it2; 741 } 742 } 743 } 744 745 Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0), family(0) 746 { 747 Anope::string n, u, h; 748 749 size_t at = fh.find('@'); 750 if (at != Anope::string::npos) 751 { 752 this->host = fh.substr(at + 1); 753 754 const Anope::string &nu = fh.substr(0, at); 755 756 size_t ex = nu.find('!'); 757 if (ex != Anope::string::npos) 758 { 759 this->user = nu.substr(ex + 1); 760 this->nick = nu.substr(0, ex); 761 } 762 else 763 this->user = nu; 764 } 765 else 766 { 767 if (fh.find('.') != Anope::string::npos || fh.find(':') != Anope::string::npos) 768 this->host = fh; 769 else 770 this->nick = fh; 771 } 772 773 at = this->host.find('#'); 774 if (at != Anope::string::npos) 775 { 776 this->real = this->host.substr(at + 1); 777 this->host = this->host.substr(0, at); 778 } 779 780 /* If the mask is all *'s it will match anything, so just clear it */ 781 if (this->nick.find_first_not_of("*") == Anope::string::npos) 782 this->nick.clear(); 783 784 if (this->user.find_first_not_of("*") == Anope::string::npos) 785 this->user.clear(); 786 787 if (this->host.find_first_not_of("*") == Anope::string::npos) 788 this->host.clear(); 789 else 790 { 791 /* Host might be a CIDR range */ 792 size_t sl = this->host.find_last_of('/'); 793 if (sl != Anope::string::npos) 794 { 795 const Anope::string &cidr_ip = this->host.substr(0, sl), 796 &cidr_range = this->host.substr(sl + 1); 797 798 sockaddrs addr(cidr_ip); 799 800 try 801 { 802 if (addr.valid() && cidr_range.is_pos_number_only()) 803 { 804 this->cidr_len = convertTo<unsigned short>(cidr_range); 805 806 /* If we got here, cidr_len is a valid number. */ 807 808 this->host = cidr_ip; 809 this->family = addr.family(); 810 811 Log(LOG_DEBUG) << "Ban " << mask << " has cidr " << this->cidr_len; 812 } 813 } 814 catch (const ConvertException &) { } 815 } 816 } 817 818 if (this->real.find_first_not_of("*") == Anope::string::npos) 819 this->real.clear(); 820 } 821 822 const Anope::string Entry::GetMask() const 823 { 824 return this->mask; 825 } 826 827 const Anope::string Entry::GetNUHMask() const 828 { 829 Anope::string n = nick.empty() ? "*" : nick, 830 u = user.empty() ? "*" : user, 831 h = host.empty() ? "*" : host, 832 r = real.empty() ? "" : "#" + real, 833 c; 834 switch (family) 835 { 836 case AF_INET: 837 if (cidr_len <= 32) 838 c = "/" + stringify(cidr_len); 839 break; 840 case AF_INET6: 841 if (cidr_len <= 128) 842 c = "/" + stringify(cidr_len); 843 break; 844 } 845 846 return n + "!" + u + "@" + h + c + r; 847 } 848 849 bool Entry::Matches(User *u, bool full) const 850 { 851 /* First check if this mode has defined any matches (usually for extbans). */ 852 if (IRCD->IsExtbanValid(this->mask)) 853 { 854 ChannelMode *cm = ModeManager::FindChannelModeByName(this->name); 855 if (cm != NULL && cm->type == MODE_LIST) 856 { 857 ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); 858 if (cml->Matches(u, this)) 859 return true; 860 } 861 } 862 863 /* If the user's displayed host is their real host, then we can do a full match without 864 * having to worry about exposing a user's IP 865 */ 866 full |= u->GetDisplayedHost() == u->host; 867 868 bool ret = true; 869 870 if (!this->nick.empty() && !Anope::Match(u->nick, this->nick)) 871 ret = false; 872 873 if (!this->user.empty() && !Anope::Match(u->GetVIdent(), this->user) && (!full || !Anope::Match(u->GetIdent(), this->user))) 874 ret = false; 875 876 if (this->cidr_len && full) 877 { 878 try 879 { 880 if (!cidr(this->host, this->cidr_len).match(u->ip)) 881 ret = false; 882 } 883 catch (const SocketException &) 884 { 885 ret = false; 886 } 887 } 888 else if (!this->host.empty() && !Anope::Match(u->GetDisplayedHost(), this->host) && !Anope::Match(u->GetCloakedHost(), this->host) && 889 (!full || (!Anope::Match(u->host, this->host) && !Anope::Match(u->ip.addr(), this->host)))) 890 ret = false; 891 892 if (!this->real.empty() && !Anope::Match(u->realname, this->real)) 893 ret = false; 894 895 return ret; 896 }