00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "services.h"
00014 #include "channels.h"
00015 #include "regchannel.h"
00016 #include "logger.h"
00017 #include "modules.h"
00018 #include "users.h"
00019 #include "bots.h"
00020 #include "servers.h"
00021 #include "protocol.h"
00022 #include "users.h"
00023 #include "config.h"
00024 #include "access.h"
00025 #include "sockets.h"
00026
00027 channel_map ChannelList;
00028
00029 Channel::Channel(const Anope::string &nname, time_t ts)
00030 {
00031 if (nname.empty())
00032 throw CoreException("A channel without a name ?");
00033
00034 this->name = nname;
00035
00036 size_t old = ChannelList.size();
00037 ChannelList[this->name] = this;
00038 if (old == ChannelList.size())
00039 Log(LOG_DEBUG) << "Duplicate channel " << this->name << " in table?";
00040
00041 this->creation_time = ts;
00042 this->server_modetime = this->chanserv_modetime = 0;
00043 this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_ts = this->topic_time = 0;
00044
00045 this->ci = ChannelInfo::Find(this->name);
00046 if (this->ci)
00047 this->ci->c = this;
00048
00049 Log(NULL, this, "create");
00050
00051 FOREACH_MOD(I_OnChannelCreate, OnChannelCreate(this));
00052 }
00053
00054 Channel::~Channel()
00055 {
00056 FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
00057
00058 ModeManager::StackerDel(this);
00059
00060 Log(NULL, this, "destroy");
00061
00062 if (this->ci)
00063 this->ci->c = NULL;
00064
00065 ChannelList.erase(this->name);
00066 }
00067
00068 void Channel::Reset()
00069 {
00070 this->modes.clear();
00071
00072 for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
00073 {
00074 ChanUserContainer *uc = *it;
00075
00076 ChannelStatus f = uc->status;
00077 uc->status.modes.clear();
00078
00079 if (BotInfo::Find(uc->user->nick))
00080 {
00081 for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00082 {
00083 ChannelMode *cm = ModeManager::ChannelModes[i];
00084
00085 if (f.modes.count(cm->name))
00086 this->SetMode(NULL, cm, uc->user->GetUID(), false);
00087 }
00088 }
00089 }
00090
00091 this->CheckModes();
00092
00093 for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
00094 this->SetCorrectModes((*it)->user, true, false);
00095
00096 if (this->ci && Me && Me->IsSynced())
00097 this->ci->RestoreTopic();
00098 }
00099
00100 void Channel::Sync()
00101 {
00102 if (!this->HasMode("PERM") && (this->users.empty() || (this->users.size() == 1 && this->ci && this->ci->bi && *this->ci->bi == this->users.front()->user)))
00103 {
00104 this->Hold();
00105 }
00106 if (this->ci)
00107 {
00108 this->CheckModes();
00109
00110 if (Me && Me->IsSynced())
00111 this->ci->RestoreTopic();
00112 }
00113 }
00114
00115 void Channel::CheckModes()
00116 {
00117 if (this->bouncy_modes)
00118 return;
00119
00120
00121 if (this->server_modecount >= 3 && this->chanserv_modecount >= 3)
00122 {
00123 Log() << "Warning: unable to set modes on channel " << this->name << ". Are your servers' U:lines configured correctly?";
00124 this->bouncy_modes = 1;
00125 return;
00126 }
00127
00128 EventReturn MOD_RESULT;
00129 FOREACH_RESULT(I_OnCheckModes, OnCheckModes(this));
00130 if (MOD_RESULT == EVENT_STOP)
00131 return;
00132
00133 if (this->ci)
00134 for (ChannelInfo::ModeList::const_iterator it = this->ci->GetMLock().begin(), it_end = this->ci->GetMLock().end(); it != it_end; ++it)
00135 {
00136 const ModeLock *ml = it->second;
00137 ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
00138 if (!cm)
00139 continue;
00140
00141 if (cm->type == MODE_REGULAR)
00142 {
00143 if (!this->HasMode(cm->name) && ml->set)
00144 this->SetMode(NULL, cm);
00145 else if (this->HasMode(cm->name) && !ml->set)
00146 this->RemoveMode(NULL, cm);
00147 }
00148 else if (cm->type == MODE_PARAM)
00149 {
00150
00151 if (ml->set)
00152 {
00153 Anope::string param;
00154 this->GetParam(cm->name, param);
00155
00156 if (!this->HasMode(cm->name) || (!param.empty() && !ml->param.empty() && !param.equals_cs(ml->param)))
00157 this->SetMode(NULL, cm, ml->param);
00158 }
00159 else
00160 {
00161 if (this->HasMode(cm->name))
00162 this->RemoveMode(NULL, cm);
00163 }
00164
00165 }
00166 else if (cm->type == MODE_LIST)
00167 {
00168 if (ml->set)
00169 this->SetMode(NULL, cm, ml->param);
00170 else
00171 this->RemoveMode(NULL, cm, ml->param);
00172 }
00173 }
00174 }
00175
00176 ChanUserContainer* Channel::JoinUser(User *user)
00177 {
00178 Log(user, this, "join");
00179
00180 ChanUserContainer *cuc = new ChanUserContainer(user, this);
00181 user->chans.push_back(cuc);
00182 this->users.push_back(cuc);
00183
00184 if (this->ci && this->ci->HasExt("PERSIST") && this->creation_time > this->ci->time_registered)
00185 {
00186 Log(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << this->ci->time_registered;
00187 this->creation_time = this->ci->time_registered;
00188 IRCD->SendChannel(this);
00189 this->Reset();
00190 }
00191
00192 return cuc;
00193 }
00194
00195 void Channel::DeleteUser(User *user)
00196 {
00197 Log(user, this, "leave");
00198 FOREACH_MOD(I_OnLeaveChannel, OnLeaveChannel(user, this));
00199
00200 ChanUserContainer *cul;
00201 ChanUserList::iterator cit, cit_end;
00202 for (cit = this->users.begin(), cit_end = this->users.end(); cit != cit_end && (*cit)->user != user; ++cit);
00203 if (cit == cit_end)
00204 {
00205 Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant user " << user->nick << " from channel " << this->name;
00206 return;
00207 }
00208 cul = *cit;
00209 this->users.erase(cit);
00210
00211 ChanUserList::iterator uit, uit_end;
00212 for (uit = user->chans.begin(), uit_end = user->chans.end(); uit != uit_end && (*uit)->chan != this; ++uit);
00213 if (uit == uit_end)
00214 Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant channel " << this->name << " from " << user->nick << "'s channel list";
00215 else
00216 {
00217 if (cul != *uit)
00218 Log(LOG_DEBUG) << "Channel::DeleteUser() mismatch between user and channel usre container objects";
00219 user->chans.erase(uit);
00220 }
00221 delete cul;
00222
00223
00224 if (this->HasExt("PERSIST") || (this->ci && this->ci->HasExt("PERSIST")))
00225 return;
00226
00227
00228
00229
00230 if (this->HasExt("SYNCING"))
00231 return;
00232
00233
00234 if (this->HasExt("INHABIT"))
00235 return;
00236
00237 if (this->users.empty())
00238 delete this;
00239 }
00240
00241 ChanUserContainer *Channel::FindUser(const User *u) const
00242 {
00243 for (ChanUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it)
00244 if ((*it)->user == u)
00245 return *it;
00246 return NULL;
00247 }
00248
00249 bool Channel::HasUserStatus(const User *u, ChannelModeStatus *cms) const
00250 {
00251
00252 ChanUserContainer *cc = u->FindChannel(this);
00253 if (cc)
00254 {
00255 if (cms)
00256 return cc->status.modes.count(cms->name);
00257 else
00258 return cc->status.modes.empty();
00259 }
00260
00261 return false;
00262 }
00263
00264 bool Channel::HasUserStatus(const User *u, const Anope::string &mname) const
00265 {
00266 return HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(ModeManager::FindChannelModeByName(mname)));
00267 }
00268
00269 size_t Channel::HasMode(const Anope::string &mname, const Anope::string ¶m)
00270 {
00271 if (param.empty())
00272 return modes.count(mname);
00273 std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(mname);
00274 for (; its.first != its.second; ++its.first)
00275 if (its.first->second == param)
00276 return 1;
00277 return 0;
00278 }
00279
00280 Anope::string Channel::GetModes(bool complete, bool plus)
00281 {
00282 Anope::string res, params;
00283
00284 for (std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it)
00285 {
00286 ChannelMode *cm = ModeManager::FindChannelModeByName(it->first);
00287 if (!cm || cm->type == MODE_LIST)
00288 continue;
00289
00290 res += cm->mchar;
00291
00292 if (complete && !it->second.empty())
00293 {
00294 ChannelModeParam *cmp = NULL;
00295 if (cm->type == MODE_PARAM)
00296 cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
00297
00298 if (plus || !cmp || !cmp->minus_no_arg)
00299 params += " " + it->second;
00300 }
00301 }
00302
00303 return res + params;
00304 }
00305
00306 const Channel::ModeList &Channel::GetModes() const
00307 {
00308 return this->modes;
00309 }
00310
00311 std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::GetModeList(const Anope::string &mname)
00312 {
00313 Channel::ModeList::iterator it = this->modes.find(mname), it_end = it;
00314 if (it != this->modes.end())
00315 it_end = this->modes.upper_bound(mname);
00316 return std::make_pair(it, it_end);
00317 }
00318
00319 void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
00320 {
00321 if (!cm)
00322 return;
00323
00324 EventReturn MOD_RESULT;
00325
00326
00327 if (cm->type == MODE_STATUS)
00328 {
00329 if (param.empty())
00330 {
00331 Log() << "Channel::SetModeInternal() mode " << cm->mchar << " with no parameter for channel " << this->name;
00332 return;
00333 }
00334
00335 User *u = User::Find(param);
00336
00337 if (!u)
00338 {
00339 Log() << "MODE " << this->name << " +" << cm->mchar << " for nonexistant user " << param;
00340 return;
00341 }
00342
00343 Log(LOG_DEBUG) << "Setting +" << cm->mchar << " on " << this->name << " for " << u->nick;
00344
00345
00346 ChanUserContainer *cc = u->FindChannel(this);
00347 if (cc)
00348 cc->status.modes.insert(cm->name);
00349
00350 FOREACH_RESULT(I_OnChannelModeSet, OnChannelModeSet(this, setter, cm->name, param));
00351
00352
00353 if (enforce_mlock && MOD_RESULT != EVENT_STOP)
00354 this->SetCorrectModes(u, false, false);
00355 return;
00356 }
00357
00358 if (cm->type != MODE_LIST)
00359 this->modes.erase(cm->name);
00360 this->modes.insert(std::make_pair(cm->name, param));
00361
00362 if (param.empty() && cm->type != MODE_REGULAR)
00363 {
00364 Log() << "Channel::SetModeInternal() mode " << cm->mchar << " for " << this->name << " with no paramater, but is a param mode";
00365 return;
00366 }
00367
00368 if (cm->type == MODE_LIST)
00369 {
00370 ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
00371 cml->OnAdd(this, param);
00372 }
00373
00374
00375 if (cm->name == "PERM")
00376 {
00377 this->Extend("PERSIST");
00378 if (this->ci)
00379 this->ci->ExtendMetadata("PERSIST");
00380 }
00381
00382 FOREACH_RESULT(I_OnChannelModeSet, OnChannelModeSet(this, setter, cm->name, param));
00383
00384
00385 if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
00386 return;
00387
00388 this->CheckModes();
00389 }
00390
00391 void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
00392 {
00393 if (!cm)
00394 return;
00395
00396 EventReturn MOD_RESULT;
00397
00398
00399 if (cm->type == MODE_STATUS)
00400 {
00401 if (param.empty())
00402 {
00403 Log() << "Channel::RemoveModeInternal() mode " << cm->mchar << " with no parameter for channel " << this->name;
00404 return;
00405 }
00406
00407 BotInfo *bi = BotInfo::Find(param);
00408 User *u = bi ? bi : User::Find(param);
00409
00410 if (!u)
00411 {
00412 Log() << "Channel::RemoveModeInternal() MODE " << this->name << "-" << cm->mchar << " for nonexistant user " << param;
00413 return;
00414 }
00415
00416 Log(LOG_DEBUG) << "Setting -" << cm->mchar << " on " << this->name << " for " << u->nick;
00417
00418
00419 ChanUserContainer *cc = u->FindChannel(this);
00420 if (cc)
00421 cc->status.modes.erase(cm->name);
00422
00423 FOREACH_RESULT(I_OnChannelModeUnset, OnChannelModeUnset(this, setter, cm->name, param));
00424
00425 if (enforce_mlock)
00426 {
00427
00428 if (this->ci && this->ci->bi && this->ci->bi == bi)
00429 {
00430 if (ModeManager::DefaultBotModes.modes.count(cm->name))
00431 this->SetMode(bi, cm, bi->GetUID());
00432 }
00433
00434 this->SetCorrectModes(u, false, false);
00435 }
00436 return;
00437 }
00438
00439 if (cm->type == MODE_LIST && !param.empty())
00440 {
00441 std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(cm->name);
00442 for (; its.first != its.second; ++its.first)
00443 if (Anope::Match(param, its.first->second))
00444 {
00445 this->modes.erase(its.first);
00446 break;
00447 }
00448 }
00449 else
00450 this->modes.erase(cm->name);
00451
00452 if (cm->type == MODE_LIST)
00453 {
00454 ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
00455 cml->OnDel(this, param);
00456 }
00457
00458 if (cm->name == "PERM")
00459 {
00460 this->Shrink("PERSIST");
00461
00462 if (this->ci)
00463 this->ci->Shrink("PERSIST");
00464
00465 if (this->users.empty() && !this->HasExt("SYNCING") && !this->HasExt("INHABIT"))
00466 {
00467 delete this;
00468 return;
00469 }
00470 }
00471
00472 FOREACH_RESULT(I_OnChannelModeUnset, OnChannelModeUnset(this, setter, cm->name, param));
00473
00474
00475 if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
00476 return;
00477
00478 this->CheckModes();
00479 }
00480
00481 void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
00482 {
00483 if (!cm)
00484 return;
00485
00486 if (cm->type == MODE_REGULAR && HasMode(cm->name))
00487 return;
00488 else if (cm->type == MODE_PARAM)
00489 {
00490 ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
00491 if (!cmp->IsValid(param))
00492 return;
00493
00494 Anope::string cparam;
00495 if (GetParam(cm->name, cparam) && cparam.equals_cs(param))
00496 return;
00497 }
00498 else if (cm->type == MODE_STATUS)
00499 {
00500 User *u = User::Find(param);
00501 if (!u || HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm)))
00502 return;
00503 }
00504 else if (cm->type == MODE_LIST)
00505 {
00506 ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm);
00507 if (this->HasMode(cm->name, param) || !cml->IsValid(param))
00508 return;
00509 }
00510
00511 if (Me->IsSynced())
00512 {
00513 if (this->chanserv_modetime != Anope::CurTime)
00514 {
00515 this->chanserv_modecount = 0;
00516 this->chanserv_modetime = Anope::CurTime;
00517 }
00518
00519 this->chanserv_modecount++;
00520 }
00521
00522 ModeManager::StackerAdd(bi, this, cm, true, param);
00523 MessageSource ms(bi);
00524 SetModeInternal(ms, cm, param, enforce_mlock);
00525 }
00526
00527 void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock)
00528 {
00529 SetMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
00530 }
00531
00532 void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
00533 {
00534 if (!cm)
00535 return;
00536
00537 if ((cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && !HasMode(cm->name))
00538 return;
00539
00540 else if (cm->type == MODE_STATUS)
00541 {
00542 User *u = User::Find(param);
00543 if (!u || !HasUserStatus(u, anope_dynamic_static_cast<ChannelModeStatus *>(cm)))
00544 return;
00545 }
00546 else if (cm->type == MODE_LIST)
00547 {
00548 if (!this->HasMode(cm->name, param))
00549 return;
00550 }
00551
00552
00553 Anope::string realparam = param;
00554 if (cm->type == MODE_PARAM)
00555 {
00556 realparam.clear();
00557 ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
00558 if (!cmp->minus_no_arg)
00559 this->GetParam(cmp->name, realparam);
00560 }
00561
00562 if (Me->IsSynced())
00563 {
00564 if (this->chanserv_modetime != Anope::CurTime)
00565 {
00566 this->chanserv_modecount = 0;
00567 this->chanserv_modetime = Anope::CurTime;
00568 }
00569
00570 this->chanserv_modecount++;
00571 }
00572
00573 ModeManager::StackerAdd(bi, this, cm, false, realparam);
00574 MessageSource ms(bi);
00575 RemoveModeInternal(ms, cm, realparam, enforce_mlock);
00576 }
00577
00578 void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock)
00579 {
00580 RemoveMode(bi, ModeManager::FindChannelModeByName(mname), param, enforce_mlock);
00581 }
00582
00583 bool Channel::GetParam(const Anope::string &mname, Anope::string &target) const
00584 {
00585 std::multimap<Anope::string, Anope::string>::const_iterator it = this->modes.find(mname);
00586
00587 target.clear();
00588
00589 if (it != this->modes.end())
00590 {
00591 target = it->second;
00592 return true;
00593 }
00594
00595 return false;
00596 }
00597
00598 void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...)
00599 {
00600 char buf[BUFSIZE] = "";
00601 va_list args;
00602 Anope::string modebuf, sbuf;
00603 int add = -1;
00604 va_start(args, cmodes);
00605 vsnprintf(buf, BUFSIZE - 1, cmodes, args);
00606 va_end(args);
00607
00608 spacesepstream sep(buf);
00609 sep.GetToken(modebuf);
00610 for (unsigned i = 0, end = modebuf.length(); i < end; ++i)
00611 {
00612 ChannelMode *cm;
00613
00614 switch (modebuf[i])
00615 {
00616 case '+':
00617 add = 1;
00618 continue;
00619 case '-':
00620 add = 0;
00621 continue;
00622 default:
00623 if (add == -1)
00624 continue;
00625 cm = ModeManager::FindChannelModeByChar(modebuf[i]);
00626 if (!cm)
00627 continue;
00628 }
00629
00630 if (add)
00631 {
00632 if (cm->type != MODE_REGULAR && sep.GetToken(sbuf))
00633 {
00634 if (cm->type == MODE_STATUS)
00635 {
00636 User *targ = User::Find(sbuf);
00637 if (targ != NULL)
00638 sbuf = targ->GetUID();
00639 }
00640 this->SetMode(bi, cm, sbuf, enforce_mlock);
00641 }
00642 else
00643 this->SetMode(bi, cm, "", enforce_mlock);
00644 }
00645 else if (!add)
00646 {
00647 if (cm->type != MODE_REGULAR && sep.GetToken(sbuf))
00648 {
00649 if (cm->type == MODE_STATUS)
00650 {
00651 User *targ = User::Find(sbuf);
00652 if (targ != NULL)
00653 sbuf = targ->GetUID();
00654 }
00655 this->RemoveMode(bi, cm, sbuf, enforce_mlock);
00656 }
00657 else
00658 this->RemoveMode(bi, cm, "", enforce_mlock);
00659 }
00660 }
00661 }
00662
00663 void Channel::SetModesInternal(MessageSource &source, const Anope::string &mode, time_t ts, bool enforce_mlock)
00664 {
00665 if (source.GetServer() && source.GetServer()->IsSynced())
00666 {
00667 if (Anope::CurTime != this->server_modetime)
00668 {
00669 this->server_modecount = 0;
00670 this->server_modetime = Anope::CurTime;
00671 }
00672
00673 ++this->server_modecount;
00674 }
00675
00676 if (!ts)
00677 ;
00678 else if (ts > this->creation_time)
00679 {
00680 Log(LOG_DEBUG) << "Dropping mode " << mode << " on " << this->name << ", " << ts << " > " << this->creation_time;
00681 return;
00682 }
00683 else if (ts < this->creation_time)
00684 {
00685 Log(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << ts;
00686 this->creation_time = ts;
00687 this->Reset();
00688 }
00689
00690 User *setter = source.GetUser();
00691
00692 Reference<Channel> this_reference(this);
00693
00694 spacesepstream sep_modes(mode);
00695 Anope::string m;
00696
00697 sep_modes.GetToken(m);
00698
00699 Anope::string modestring;
00700 Anope::string paramstring;
00701 int add = -1;
00702 for (unsigned int i = 0, end = m.length(); i < end && this_reference; ++i)
00703 {
00704 ChannelMode *cm;
00705
00706 switch (m[i])
00707 {
00708 case '+':
00709 modestring += '+';
00710 add = 1;
00711 continue;
00712 case '-':
00713 modestring += '-';
00714 add = 0;
00715 continue;
00716 default:
00717 if (add == -1)
00718 continue;
00719 cm = ModeManager::FindChannelModeByChar(m[i]);
00720 if (!cm)
00721 {
00722 Log(LOG_DEBUG) << "Channel::SetModeInternal: Unknown mode char " << m[i];
00723 continue;
00724 }
00725 modestring += cm->mchar;
00726 }
00727
00728 if (cm->type == MODE_REGULAR)
00729 {
00730 if (add)
00731 this->SetModeInternal(source, cm, "", false);
00732 else
00733 this->RemoveModeInternal(source, cm, "", false);
00734 continue;
00735 }
00736 else if (cm->type == MODE_PARAM)
00737 {
00738 ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
00739
00740 if (!add && cmp->minus_no_arg)
00741 {
00742 this->RemoveModeInternal(source, cm, "", false);
00743 continue;
00744 }
00745 }
00746 Anope::string token;
00747 if (sep_modes.GetToken(token))
00748 {
00749 User *u = NULL;
00750 if (cm->type == MODE_STATUS && (u = User::Find(token)))
00751 paramstring += " " + u->nick;
00752 else
00753 paramstring += " " + token;
00754
00755 if (add)
00756 this->SetModeInternal(source, cm, token, false);
00757 else
00758 this->RemoveModeInternal(source, cm, token, false);
00759 }
00760 else
00761 Log() << "warning: Channel::SetModesInternal() recieved more modes requiring params than params, modes: " << mode;
00762 }
00763
00764 if (!this_reference)
00765 return;
00766
00767 if (setter)
00768 Log(setter, this, "mode") << modestring << paramstring;
00769 else
00770 Log(LOG_DEBUG) << source.GetName() << " is setting " << this->name << " to " << modestring << paramstring;
00771
00772 if (enforce_mlock)
00773 this->CheckModes();
00774 }
00775
00776 bool Channel::MatchesList(User *u, const Anope::string &mode)
00777 {
00778 if (!this->HasMode(mode))
00779 return false;
00780
00781
00782 std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> m = this->GetModeList(mode);
00783 for (; m.first != m.second; ++m.first)
00784 {
00785 Entry e(mode, m.first->second);
00786 if (e.Matches(u))
00787 return true;
00788 }
00789
00790 return false;
00791 }
00792
00793 void Channel::KickInternal(MessageSource &source, const Anope::string &nick, const Anope::string &reason)
00794 {
00795 User *sender = source.GetUser();
00796 User *target = User::Find(nick);
00797 if (!target)
00798 {
00799 Log() << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason;
00800 return;
00801 }
00802
00803 BotInfo *bi = NULL;
00804 if (target->server == Me)
00805 bi = BotInfo::Find(nick);
00806
00807 if (sender)
00808 Log(sender, this, "kick") << "kicked " << target->nick << " (" << reason << ")";
00809 else
00810 Log(target, this, "kick") << "was kicked by " << source.GetSource() << " (" << reason << ")";
00811
00812 Anope::string chname = this->name;
00813
00814 if (target->FindChannel(this))
00815 {
00816 FOREACH_MOD(I_OnUserKicked, OnUserKicked(this, target, source, reason));
00817 if (bi)
00818 this->Extend("INHABIT");
00819 this->DeleteUser(target);
00820 }
00821 else
00822 Log() << "Channel::KickInternal got kick for user " << target->nick << " from " << source.GetSource() << " who isn't on channel " << this->name;
00823
00824
00825 if (bi)
00826 {
00827 bi->Join(this, &ModeManager::DefaultBotModes);
00828 this->Shrink("INHABIT");
00829 }
00830 }
00831
00832 bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
00833 {
00834 va_list args;
00835 char buf[BUFSIZE] = "";
00836 va_start(args, reason);
00837 vsnprintf(buf, BUFSIZE - 1, reason, args);
00838 va_end(args);
00839
00840
00841 if (u->server->IsULined())
00842 return false;
00843
00844
00845 if (u->IsProtected())
00846 return false;
00847
00848 if (bi == NULL)
00849 bi = this->ci->WhoSends();
00850
00851 EventReturn MOD_RESULT;
00852 FOREACH_RESULT(I_OnBotKick, OnBotKick(bi, this, u, buf));
00853 if (MOD_RESULT == EVENT_STOP)
00854 return false;
00855 IRCD->SendKick(bi, this, u, "%s", buf);
00856 MessageSource ms(bi);
00857 this->KickInternal(ms, u->nick, buf);
00858 return true;
00859 }
00860
00861 void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts)
00862 {
00863 User *u = User::Find(user);
00864
00865 this->topic = newtopic;
00866 this->topic_setter = u ? u->nick : user;
00867 this->topic_ts = ts;
00868 this->topic_time = Anope::CurTime;
00869
00870 Log(LOG_DEBUG) << "Topic of " << this->name << " changed by " << (u ? u->nick : user) << " to " << newtopic;
00871
00872 FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, user, this->topic));
00873
00874 if (this->ci)
00875 this->ci->CheckTopic();
00876 }
00877
00878 void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtopic, time_t ts)
00879 {
00880 User *u = User::Find(user);
00881
00882 this->topic = newtopic;
00883 this->topic_setter = u ? u->nick : user;
00884 this->topic_ts = ts;
00885
00886 IRCD->SendTopic(this->ci->WhoSends(), this);
00887
00888
00889 this->topic_time = Anope::CurTime;
00890
00891 FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, user, this->topic));
00892
00893 if (this->ci)
00894 this->ci->CheckTopic();
00895 }
00896
00897 void Channel::Hold()
00898 {
00902 class ChanServTimer : public Timer
00903 {
00904 private:
00905 Reference<Channel> c;
00906
00907 public:
00911 ChanServTimer(Channel *chan) : Timer(Config->CSInhabit), c(chan)
00912 {
00913 if (!ChanServ || !c)
00914 return;
00915 c->Extend("INHABIT");
00916 if (!c->ci || !c->ci->bi)
00917 ChanServ->Join(c);
00918 else if (!c->FindUser(c->ci->bi))
00919 c->ci->bi->Join(c);
00920 }
00921
00925 void Tick(time_t) anope_override
00926 {
00927 if (!c)
00928 return;
00929
00930 c->Shrink("INHABIT");
00931
00932 if (!c->ci || !c->ci->bi)
00933 {
00934 if (ChanServ)
00935 ChanServ->Part(c);
00936 }
00937 else if (c->users.size() == 1 || c->users.size() < Config->BSMinUsers)
00938 c->ci->bi->Part(c);
00939 }
00940 };
00941
00942 new ChanServTimer(this);
00943 }
00944
00945 void Channel::SetCorrectModes(User *user, bool give_modes, bool check_noop)
00946 {
00947 ChannelMode *owner = ModeManager::FindChannelModeByName("OWNER"),
00948 *admin = ModeManager::FindChannelModeByName("PROTECT"),
00949 *op = ModeManager::FindChannelModeByName("OP"),
00950 *halfop = ModeManager::FindChannelModeByName("HALFOP"),
00951 *voice = ModeManager::FindChannelModeByName("VOICE"),
00952 *registered = ModeManager::FindChannelModeByName("REGISTERED");
00953
00954 if (user == NULL)
00955 return;
00956
00957 if (!this->ci)
00958 return;
00959
00960 Log(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << this->name << " (" << (give_modes ? "" : "not ") << "giving modes)";
00961
00962 AccessGroup u_access = ci->AccessFor(user);
00963
00964 if (give_modes && (!user->Account() || user->Account()->HasExt("AUTOOP")) && (!check_noop || !ci->HasExt("NOAUTOOP")))
00965 {
00966 if (owner && u_access.HasPriv("AUTOOWNER"))
00967 this->SetMode(NULL, "OWNER", user->GetUID());
00968 else if (admin && u_access.HasPriv("AUTOPROTECT"))
00969 this->SetMode(NULL, "PROTECT", user->GetUID());
00970
00971 if (op && u_access.HasPriv("AUTOOP"))
00972 this->SetMode(NULL, "OP", user->GetUID());
00973 else if (halfop && u_access.HasPriv("AUTOHALFOP"))
00974 this->SetMode(NULL, "HALFOP", user->GetUID());
00975 else if (voice && u_access.HasPriv("AUTOVOICE"))
00976 this->SetMode(NULL, "VOICE", user->GetUID());
00977 }
00978
00979
00980
00981
00982
00983 if ((ci->HasExt("SECUREOPS") || (registered && !this->HasMode("REGISTERED")) || (!registered && this->HasExt("SYNCING") && user->server->IsSynced())) && !user->server->IsULined())
00984 {
00985 if (owner && !u_access.HasPriv("AUTOOWNER") && !u_access.HasPriv("OWNERME"))
00986 this->RemoveMode(NULL, "OWNER", user->GetUID());
00987
00988 if (admin && !u_access.HasPriv("AUTOPROTECT") && !u_access.HasPriv("PROTECTME"))
00989 this->RemoveMode(NULL, "PROTECT", user->GetUID());
00990
00991 if (op && this->HasUserStatus(user, "OP") && !u_access.HasPriv("AUTOOP") && !u_access.HasPriv("OPDEOPME"))
00992 this->RemoveMode(NULL, "OP", user->GetUID());
00993
00994 if (halfop && !u_access.HasPriv("AUTOHALFOP") && !u_access.HasPriv("HALFOPME"))
00995 this->RemoveMode(NULL, "HALFOP", user->GetUID());
00996 }
00997
00998
00999 for (ChannelInfo::ModeList::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it)
01000 {
01001 const ModeLock *ml = it->second;
01002 ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
01003 if (!cm || cm->type != MODE_STATUS)
01004 continue;
01005
01006 if (Anope::Match(user->nick, ml->param) || Anope::Match(user->GetDisplayedMask(), ml->param))
01007 {
01008 if (ml->set != this->HasUserStatus(user, ml->name))
01009 {
01010 if (ml->set)
01011 this->SetMode(NULL, cm, user->GetUID(), false);
01012 else if (!ml->set)
01013 this->RemoveMode(NULL, cm, user->GetUID(), false);
01014 }
01015 }
01016 }
01017 }
01018
01019 bool Channel::Unban(const User *u, bool full)
01020 {
01021 if (!this->HasMode("BAN"))
01022 return false;
01023
01024 bool ret = false;
01025
01026 std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = this->GetModeList("BAN");
01027 for (; bans.first != bans.second;)
01028 {
01029 Entry ban("BAN", bans.first->second);
01030 ++bans.first;
01031 if (ban.Matches(u, full))
01032 {
01033 this->RemoveMode(NULL, "BAN", ban.GetMask());
01034 ret = true;
01035 }
01036 }
01037
01038 return ret;
01039 }
01040
01041 Channel* Channel::Find(const Anope::string &name)
01042 {
01043 channel_map::const_iterator it = ChannelList.find(name);
01044
01045 if (it != ChannelList.end())
01046 return it->second;
01047 return NULL;
01048 }
01049