00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "inspircd.h"
00017 #include <cstdarg>
00018 #include "mode.h"
00019
00020 Channel::Channel(InspIRCd* Instance, const std::string &cname, time_t ts) : ServerInstance(Instance)
00021 {
00022 chan_hash::iterator findchan = ServerInstance->chanlist->find(cname);
00023 if (findchan != Instance->chanlist->end())
00024 throw CoreException("Cannot create duplicate channel " + cname);
00025
00026 (*(ServerInstance->chanlist))[cname.c_str()] = this;
00027 this->name.assign(cname, 0, ServerInstance->Config->Limits.ChanMax);
00028 this->created = ts ? ts : ServerInstance->Time();
00029 this->age = this->created;
00030
00031 maxbans = topicset = 0;
00032 modes.reset();
00033 }
00034
00035 void Channel::SetMode(char mode,bool mode_on)
00036 {
00037 modes[mode-65] = mode_on;
00038 if (!mode_on)
00039 this->SetModeParam(mode,"",false);
00040 }
00041
00042
00043 void Channel::SetModeParam(char mode,const char* parameter,bool mode_on)
00044 {
00045 CustomModeList::iterator n = custom_mode_params.find(mode);
00046
00047 if (mode_on)
00048 {
00049 if (n == custom_mode_params.end())
00050 custom_mode_params[mode] = strdup(parameter);
00051 }
00052 else
00053 {
00054 if (n != custom_mode_params.end())
00055 {
00056 free(n->second);
00057 custom_mode_params.erase(n);
00058 }
00059 }
00060 }
00061
00062 bool Channel::IsModeSet(char mode)
00063 {
00064 return modes[mode-65];
00065 }
00066
00067 std::string Channel::GetModeParameter(char mode)
00068 {
00069 CustomModeList::iterator n = custom_mode_params.find(mode);
00070 if (n != custom_mode_params.end())
00071 return n->second;
00072 return "";
00073 }
00074
00075 int Channel::SetTopic(User *u, std::string &ntopic, bool forceset)
00076 {
00077 if (u && IS_LOCAL(u))
00078 {
00079 if(!forceset)
00080 {
00081 int MOD_RESULT = 0;
00082
00083
00084 FOREACH_RESULT(I_OnLocalTopicChange,OnLocalTopicChange(u,this,ntopic));
00085
00086 if (MOD_RESULT == 1)
00087 return CMD_FAILURE;
00088 else if (MOD_RESULT == 0)
00089 {
00090 if (!this->HasUser(u))
00091 {
00092 u->WriteNumeric(442, "%s %s :You're not on that channel!",u->nick.c_str(), this->name.c_str());
00093 return CMD_FAILURE;
00094 }
00095 if ((this->IsModeSet('t')) && (this->GetStatus(u) < STATUS_HOP))
00096 {
00097 u->WriteNumeric(482, "%s %s :You must be at least a half-operator to change the topic on this channel", u->nick.c_str(), this->name.c_str());
00098 return CMD_FAILURE;
00099 }
00100 }
00101 }
00102 }
00103
00104 this->topic.assign(ntopic, 0, ServerInstance->Config->Limits.MaxTopic);
00105 if (u)
00106 {
00107 this->setby.assign(ServerInstance->Config->FullHostInTopic ? u->GetFullHost() : u->nick, 0, 128);
00108 this->WriteChannel(u, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
00109 }
00110 else
00111 {
00112 this->setby.assign(ServerInstance->Config->ServerName);
00113 this->WriteChannelWithServ(ServerInstance->Config->ServerName, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
00114 }
00115
00116 this->topicset = ServerInstance->Time();
00117
00118 if (u && IS_LOCAL(u))
00119 {
00120 FOREACH_MOD(I_OnPostLocalTopicChange,OnPostLocalTopicChange(u, this, this->topic));
00121 }
00122
00123 return CMD_SUCCESS;
00124 }
00125
00126 long Channel::GetUserCounter()
00127 {
00128 return (this->internal_userlist.size());
00129 }
00130
00131 void Channel::AddUser(User* user)
00132 {
00133 internal_userlist[user] = user->nick;
00134 }
00135
00136 unsigned long Channel::DelUser(User* user)
00137 {
00138 CUListIter a = internal_userlist.find(user);
00139
00140 if (a != internal_userlist.end())
00141 {
00142 internal_userlist.erase(a);
00143
00144 DelOppedUser(user);
00145 DelHalfoppedUser(user);
00146 DelVoicedUser(user);
00147 }
00148
00149 return internal_userlist.size();
00150 }
00151
00152 bool Channel::HasUser(User* user)
00153 {
00154 return (internal_userlist.find(user) != internal_userlist.end());
00155 }
00156
00157 void Channel::AddOppedUser(User* user)
00158 {
00159 internal_op_userlist[user] = user->nick;
00160 }
00161
00162 void Channel::DelOppedUser(User* user)
00163 {
00164 CUListIter a = internal_op_userlist.find(user);
00165 if (a != internal_op_userlist.end())
00166 {
00167 internal_op_userlist.erase(a);
00168 return;
00169 }
00170 }
00171
00172 void Channel::AddHalfoppedUser(User* user)
00173 {
00174 internal_halfop_userlist[user] = user->nick;
00175 }
00176
00177 void Channel::DelHalfoppedUser(User* user)
00178 {
00179 CUListIter a = internal_halfop_userlist.find(user);
00180
00181 if (a != internal_halfop_userlist.end())
00182 {
00183 internal_halfop_userlist.erase(a);
00184 }
00185 }
00186
00187 void Channel::AddVoicedUser(User* user)
00188 {
00189 internal_voice_userlist[user] = user->nick;
00190 }
00191
00192 void Channel::DelVoicedUser(User* user)
00193 {
00194 CUListIter a = internal_voice_userlist.find(user);
00195
00196 if (a != internal_voice_userlist.end())
00197 {
00198 internal_voice_userlist.erase(a);
00199 }
00200 }
00201
00202 CUList* Channel::GetUsers()
00203 {
00204 return &internal_userlist;
00205 }
00206
00207 CUList* Channel::GetOppedUsers()
00208 {
00209 return &internal_op_userlist;
00210 }
00211
00212 CUList* Channel::GetHalfoppedUsers()
00213 {
00214 return &internal_halfop_userlist;
00215 }
00216
00217 CUList* Channel::GetVoicedUsers()
00218 {
00219 return &internal_voice_userlist;
00220 }
00221
00222 void Channel::SetDefaultModes()
00223 {
00224 ServerInstance->Logs->Log("CHANNELS", DEBUG, "SetDefaultModes %s", ServerInstance->Config->DefaultModes);
00225 irc::spacesepstream list(ServerInstance->Config->DefaultModes);
00226 std::string modeseq;
00227 std::string parameter;
00228
00229 list.GetToken(modeseq);
00230
00231 for (std::string::iterator n = modeseq.begin(); n != modeseq.end(); ++n)
00232 {
00233 ModeHandler* mode = ServerInstance->Modes->FindMode(*n, MODETYPE_CHANNEL);
00234 if (mode)
00235 {
00236 if (mode->GetNumParams(true))
00237 list.GetToken(parameter);
00238 else
00239 parameter.clear();
00240
00241 mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, parameter, true);
00242 }
00243 }
00244 }
00245
00246
00247
00248
00249
00250 Channel* Channel::JoinUser(InspIRCd* Instance, User *user, const char* cn, bool override, const char* key, bool bursting, time_t TS)
00251 {
00252 if (!user || !cn)
00253 return NULL;
00254
00255 char cname[MAXBUF];
00256 int MOD_RESULT = 0;
00257 std::string privs;
00258 Channel *Ptr;
00259
00260
00261
00262
00263
00264
00265
00266 if (IS_LOCAL(user) && !override)
00267 {
00268
00269 if (user->MyClass && user->MyClass->GetMaxChans())
00270 {
00271 if (user->chans.size() >= user->MyClass->GetMaxChans())
00272 {
00273 user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
00274 return NULL;
00275 }
00276 }
00277 else
00278 {
00279 if (IS_OPER(user))
00280 {
00281 if (user->chans.size() >= Instance->Config->OperMaxChans)
00282 {
00283 user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
00284 return NULL;
00285 }
00286 }
00287 else
00288 {
00289 if (user->chans.size() >= Instance->Config->MaxChans)
00290 {
00291 user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
00292 return NULL;
00293 }
00294 }
00295 }
00296 }
00297
00298 strlcpy(cname, cn, Instance->Config->Limits.ChanMax);
00299 Ptr = Instance->FindChan(cname);
00300
00301 if (!Ptr)
00302 {
00303
00304
00305
00306 if (!IS_LOCAL(user))
00307 {
00308 if (!TS)
00309 Instance->Logs->Log("CHANNEL",DEBUG,"*** BUG *** Channel::JoinUser called for REMOTE user '%s' on channel '%s' but no TS given!", user->nick.c_str(), cn);
00310 }
00311 else
00312 {
00313 privs = "@";
00314 }
00315
00316 if (IS_LOCAL(user) && override == false)
00317 {
00318 MOD_RESULT = 0;
00319 FOREACH_RESULT_I(Instance,I_OnUserPreJoin, OnUserPreJoin(user, NULL, cname, privs, key ? key : ""));
00320 if (MOD_RESULT == 1)
00321 return NULL;
00322 }
00323
00324 Ptr = new Channel(Instance, cname, TS);
00325 }
00326 else
00327 {
00328
00329 if (Ptr->HasUser(user))
00330 return NULL;
00331
00332
00333
00334
00335
00336 if (IS_LOCAL(user) && override == false)
00337 {
00338 MOD_RESULT = 0;
00339 FOREACH_RESULT_I(Instance,I_OnUserPreJoin, OnUserPreJoin(user, Ptr, cname, privs, key ? key : ""));
00340 if (MOD_RESULT == 1)
00341 {
00342 return NULL;
00343 }
00344 else if (MOD_RESULT == 0)
00345 {
00346 std::string ckey = Ptr->GetModeParameter('k');
00347 bool invited = user->IsInvited(Ptr->name.c_str());
00348 bool can_bypass = Instance->Config->InvBypassModes && invited;
00349
00350 if (!ckey.empty())
00351 {
00352 MOD_RESULT = 0;
00353 FOREACH_RESULT_I(Instance, I_OnCheckKey, OnCheckKey(user, Ptr, key ? key : ""));
00354 if (!MOD_RESULT)
00355 {
00356
00357 if ((!key || ckey != key) && !can_bypass)
00358 {
00359 user->WriteNumeric(ERR_BADCHANNELKEY, "%s %s :Cannot join channel (Incorrect channel key)",user->nick.c_str(), Ptr->name.c_str());
00360 return NULL;
00361 }
00362 }
00363 }
00364
00365 if (Ptr->IsModeSet('i'))
00366 {
00367 MOD_RESULT = 0;
00368 FOREACH_RESULT_I(Instance,I_OnCheckInvite,OnCheckInvite(user, Ptr));
00369 if (!MOD_RESULT)
00370 {
00371 if (!invited)
00372 {
00373 user->WriteNumeric(ERR_INVITEONLYCHAN, "%s %s :Cannot join channel (Invite only)",user->nick.c_str(), Ptr->name.c_str());
00374 return NULL;
00375 }
00376 }
00377 }
00378
00379 std::string limit = Ptr->GetModeParameter('l');
00380 if (!limit.empty())
00381 {
00382 MOD_RESULT = 0;
00383 FOREACH_RESULT_I(Instance, I_OnCheckLimit, OnCheckLimit(user, Ptr));
00384 if (!MOD_RESULT)
00385 {
00386 long llimit = atol(limit.c_str());
00387 if (Ptr->GetUserCounter() >= llimit && !can_bypass)
00388 {
00389 user->WriteNumeric(ERR_CHANNELISFULL, "%s %s :Cannot join channel (Channel is full)",user->nick.c_str(), Ptr->name.c_str());
00390 return NULL;
00391 }
00392 }
00393 }
00394
00395 if (Ptr->bans.size())
00396 {
00397 if (Ptr->IsBanned(user) && !can_bypass)
00398 {
00399 user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s %s :Cannot join channel (You're banned)",user->nick.c_str(), Ptr->name.c_str());
00400 return NULL;
00401 }
00402 }
00403
00404
00405
00406
00407
00408 if (invited)
00409 {
00410 user->RemoveInvite(Ptr->name.c_str());
00411 }
00412 }
00413 }
00414 }
00415
00416
00417 if (IS_LOCAL(user) && Ptr->GetUserCounter() == 0)
00418 Ptr->SetDefaultModes();
00419
00420 return Channel::ForceChan(Instance, Ptr, user, privs, bursting);
00421 }
00422
00423 Channel* Channel::ForceChan(InspIRCd* Instance, Channel* Ptr, User* user, const std::string &privs, bool bursting)
00424 {
00425 std::string nick = user->nick;
00426 bool silent = false;
00427
00428 Ptr->AddUser(user);
00429
00430
00431 user->chans[Ptr] = 0;
00432
00433 for (std::string::const_iterator x = privs.begin(); x != privs.end(); x++)
00434 {
00435 const char status = *x;
00436 ModeHandler* mh = Instance->Modes->FindPrefix(status);
00437 if (mh)
00438 {
00439
00440 Ptr->SetPrefix(user, status, mh->GetPrefixRank(), true);
00441 mh->OnModeChange(Instance->FakeClient, Instance->FakeClient, Ptr, nick, true);
00442
00443 switch (mh->GetPrefix())
00444 {
00445
00446
00447
00448
00449
00450 case '@':
00451 user->chans[Ptr] |= UCMODE_OP;
00452 break;
00453 case '%':
00454 user->chans[Ptr] |= UCMODE_HOP;
00455 break;
00456 case '+':
00457 user->chans[Ptr] |= UCMODE_VOICE;
00458 break;
00459 }
00460 }
00461 }
00462
00463 FOREACH_MOD_I(Instance,I_OnUserJoin,OnUserJoin(user, Ptr, bursting, silent));
00464
00465 if (!silent)
00466 Ptr->WriteChannel(user,"JOIN :%s",Ptr->name.c_str());
00467
00468
00469 std::string ms = Instance->Modes->ModeString(user, Ptr);
00470 if ((Ptr->GetUserCounter() > 1) && (ms.length()))
00471 Ptr->WriteAllExceptSender(user, true, 0, "MODE %s +%s", Ptr->name.c_str(), ms.c_str());
00472
00473
00474 if (IS_LOCAL(user))
00475 {
00476 if (Ptr->topicset)
00477 {
00478 user->WriteNumeric(RPL_TOPIC, "%s %s :%s", user->nick.c_str(), Ptr->name.c_str(), Ptr->topic.c_str());
00479 user->WriteNumeric(RPL_TOPICTIME, "%s %s %s %lu", user->nick.c_str(), Ptr->name.c_str(), Ptr->setby.c_str(), (unsigned long)Ptr->topicset);
00480 }
00481 Ptr->UserList(user);
00482 }
00483 FOREACH_MOD_I(Instance,I_OnPostJoin,OnPostJoin(user, Ptr));
00484 return Ptr;
00485 }
00486
00487 bool Channel::IsBanned(User* user)
00488 {
00489 char mask[MAXBUF];
00490 int MOD_RESULT = 0;
00491 FOREACH_RESULT(I_OnCheckBan,OnCheckBan(user, this));
00492
00493 if (MOD_RESULT == -1)
00494 return true;
00495 else if (MOD_RESULT == 0)
00496 {
00497 snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), user->GetIPString());
00498 for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++)
00499 {
00500 if ((InspIRCd::Match(user->GetFullHost(),i->data, NULL)) ||
00501 (InspIRCd::Match(user->GetFullRealHost(),i->data, NULL)) ||
00502 (InspIRCd::MatchCIDR(mask, i->data, NULL)))
00503 {
00504 return true;
00505 }
00506 }
00507 }
00508 return false;
00509 }
00510
00511 bool Channel::IsExtBanned(const std::string &str, char type)
00512 {
00513 int MOD_RESULT = 0;
00514 FOREACH_RESULT(I_OnCheckStringExtBan, OnCheckStringExtBan(str, this, type));
00515
00516 if (MOD_RESULT == -1)
00517 return true;
00518 else if (MOD_RESULT == 0)
00519 {
00520 for (BanList::iterator i = this->bans.begin(); i != this->bans.end(); i++)
00521 {
00522 if (i->data[0] != type || i->data[1] != ':')
00523 continue;
00524
00525
00526 std::string maskptr = i->data.substr(2);
00527 ServerInstance->Logs->Log("EXTBANS", DEBUG, "Checking %s against %s, type is %c", str.c_str(), maskptr.c_str(), type);
00528
00529 if (InspIRCd::Match(str, maskptr, NULL))
00530 return true;
00531 }
00532 }
00533
00534 return false;
00535 }
00536
00537 bool Channel::IsExtBanned(User *user, char type)
00538 {
00539 int MOD_RESULT = 0;
00540 FOREACH_RESULT(I_OnCheckExtBan, OnCheckExtBan(user, this, type));
00541
00542 if (MOD_RESULT == -1)
00543 return true;
00544 else if (MOD_RESULT == 0)
00545 {
00546 char mask[MAXBUF];
00547 snprintf(mask, MAXBUF, "%s!%s@%s", user->nick.c_str(), user->ident.c_str(), user->GetIPString());
00548
00549
00550 if (this->IsExtBanned(mask, type))
00551 return true;
00552
00553 if (this->IsExtBanned(user->GetFullHost(), type))
00554 return true;
00555
00556 if (this->IsExtBanned(user->GetFullRealHost(), type))
00557 return true;
00558 }
00559
00560 return false;
00561 }
00562
00563
00564
00565
00566
00567 long Channel::PartUser(User *user, std::string &reason)
00568 {
00569 bool silent = false;
00570
00571 if (!user)
00572 return this->GetUserCounter();
00573
00574 UCListIter i = user->chans.find(this);
00575 if (i != user->chans.end())
00576 {
00577 FOREACH_MOD(I_OnUserPart,OnUserPart(user, this, reason, silent));
00578
00579 if (!silent)
00580 this->WriteChannel(user, "PART %s%s%s", this->name.c_str(), reason.empty() ? "" : " :", reason.c_str());
00581
00582 user->chans.erase(i);
00583 this->RemoveAllPrefixes(user);
00584 }
00585
00586 if (!this->DelUser(user))
00587 {
00588 chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
00589
00590 if (iter != ServerInstance->chanlist->end())
00591 {
00592 int MOD_RESULT = 0;
00593 FOREACH_RESULT_I(ServerInstance,I_OnChannelPreDelete, OnChannelPreDelete(this));
00594 if (MOD_RESULT == 1)
00595 return 1;
00596 FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
00597 ServerInstance->chanlist->erase(iter);
00598 }
00599 return 0;
00600 }
00601
00602 return this->GetUserCounter();
00603 }
00604
00605 long Channel::ServerKickUser(User* user, const char* reason, bool triggerevents, const char* servername)
00606 {
00607 bool silent = false;
00608
00609 if (!user || !reason)
00610 return this->GetUserCounter();
00611
00612 if (IS_LOCAL(user))
00613 {
00614 if (!this->HasUser(user))
00615 {
00616
00617 return this->GetUserCounter();
00618 }
00619 }
00620
00621 if (servername == NULL || *ServerInstance->Config->HideWhoisServer)
00622 servername = ServerInstance->Config->ServerName;
00623
00624 if (triggerevents)
00625 {
00626 FOREACH_MOD(I_OnUserKick,OnUserKick(NULL, user, this, reason, silent));
00627 }
00628
00629 UCListIter i = user->chans.find(this);
00630 if (i != user->chans.end())
00631 {
00632 if (!silent)
00633 this->WriteChannelWithServ(servername, "KICK %s %s :%s", this->name.c_str(), user->nick.c_str(), reason);
00634
00635 user->chans.erase(i);
00636 this->RemoveAllPrefixes(user);
00637 }
00638
00639 if (!this->DelUser(user))
00640 {
00641 chan_hash::iterator iter = ServerInstance->chanlist->find(this->name);
00642
00643 if (iter != ServerInstance->chanlist->end())
00644 {
00645 int MOD_RESULT = 0;
00646 FOREACH_RESULT_I(ServerInstance,I_OnChannelPreDelete, OnChannelPreDelete(this));
00647 if (MOD_RESULT == 1)
00648 return 1;
00649 FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
00650 ServerInstance->chanlist->erase(iter);
00651 }
00652 return 0;
00653 }
00654
00655 return this->GetUserCounter();
00656 }
00657
00658 long Channel::KickUser(User *src, User *user, const char* reason)
00659 {
00660 bool silent = false;
00661
00662 if (!src || !user || !reason)
00663 return this->GetUserCounter();
00664
00665 if (IS_LOCAL(src))
00666 {
00667 if (!this->HasUser(user))
00668 {
00669 src->WriteNumeric(ERR_USERNOTINCHANNEL, "%s %s %s :They are not on that channel",src->nick.c_str(), user->nick.c_str(), this->name.c_str());
00670 return this->GetUserCounter();
00671 }
00672 if ((ServerInstance->ULine(user->server)) && (!ServerInstance->ULine(src->server)))
00673 {
00674 src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :Only a u-line may kick a u-line from a channel.",src->nick.c_str(), this->name.c_str());
00675 return this->GetUserCounter();
00676 }
00677 int MOD_RESULT = 0;
00678
00679 if (!ServerInstance->ULine(src->server))
00680 {
00681 MOD_RESULT = 0;
00682 FOREACH_RESULT(I_OnUserPreKick,OnUserPreKick(src,user,this,reason));
00683 if (MOD_RESULT == 1)
00684 return this->GetUserCounter();
00685 }
00686
00687 if (MOD_RESULT != -1)
00688 {
00689 FOREACH_RESULT(I_OnAccessCheck,OnAccessCheck(src,user,this,AC_KICK));
00690 if ((MOD_RESULT == ACR_DENY) && (!ServerInstance->ULine(src->server)))
00691 return this->GetUserCounter();
00692
00693 if ((MOD_RESULT == ACR_DEFAULT) || (!ServerInstance->ULine(src->server)))
00694 {
00695 int them = this->GetStatus(src);
00696 int us = this->GetStatus(user);
00697 if ((them < STATUS_HOP) || (them < us))
00698 {
00699 src->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must be a channel %soperator",src->nick.c_str(), this->name.c_str(), them == STATUS_HOP ? "" : "half-");
00700 return this->GetUserCounter();
00701 }
00702 }
00703 }
00704 }
00705
00706 FOREACH_MOD(I_OnUserKick,OnUserKick(src, user, this, reason, silent));
00707
00708 UCListIter i = user->chans.find(this);
00709 if (i != user->chans.end())
00710 {
00711
00712 if (!silent)
00713 this->WriteChannel(src, "KICK %s %s :%s", this->name.c_str(), user->nick.c_str(), reason);
00714
00715 user->chans.erase(i);
00716 this->RemoveAllPrefixes(user);
00717 }
00718
00719 if (!this->DelUser(user))
00720
00721 {
00722 chan_hash::iterator iter = ServerInstance->chanlist->find(this->name.c_str());
00723
00724
00725 if (iter != ServerInstance->chanlist->end())
00726 {
00727 int MOD_RESULT = 0;
00728 FOREACH_RESULT_I(ServerInstance,I_OnChannelPreDelete, OnChannelPreDelete(this));
00729 if (MOD_RESULT == 1)
00730 return 1;
00731 FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this));
00732 ServerInstance->chanlist->erase(iter);
00733 }
00734 return 0;
00735 }
00736
00737 return this->GetUserCounter();
00738 }
00739
00740 void Channel::WriteChannel(User* user, const char* text, ...)
00741 {
00742 char textbuffer[MAXBUF];
00743 va_list argsPtr;
00744
00745 if (!user || !text)
00746 return;
00747
00748 va_start(argsPtr, text);
00749 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
00750 va_end(argsPtr);
00751
00752 this->WriteChannel(user, std::string(textbuffer));
00753 }
00754
00755 void Channel::WriteChannel(User* user, const std::string &text)
00756 {
00757 CUList *ulist = this->GetUsers();
00758 char tb[MAXBUF];
00759
00760 if (!user)
00761 return;
00762
00763 snprintf(tb,MAXBUF,":%s %s", user->GetFullHost().c_str(), text.c_str());
00764 std::string out = tb;
00765
00766 for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
00767 {
00768 if (IS_LOCAL(i->first))
00769 i->first->Write(out);
00770 }
00771 }
00772
00773 void Channel::WriteChannelWithServ(const char* ServName, const char* text, ...)
00774 {
00775 char textbuffer[MAXBUF];
00776 va_list argsPtr;
00777
00778 if (!text)
00779 return;
00780
00781 va_start(argsPtr, text);
00782 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
00783 va_end(argsPtr);
00784
00785 this->WriteChannelWithServ(ServName, std::string(textbuffer));
00786 }
00787
00788 void Channel::WriteChannelWithServ(const char* ServName, const std::string &text)
00789 {
00790 CUList *ulist = this->GetUsers();
00791 char tb[MAXBUF];
00792
00793 snprintf(tb,MAXBUF,":%s %s", ServName ? ServName : ServerInstance->Config->ServerName, text.c_str());
00794 std::string out = tb;
00795
00796 for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
00797 {
00798 if (IS_LOCAL(i->first))
00799 i->first->Write(out);
00800 }
00801 }
00802
00803
00804
00805 void Channel::WriteAllExceptSender(User* user, bool serversource, char status, const char* text, ...)
00806 {
00807 char textbuffer[MAXBUF];
00808 va_list argsPtr;
00809
00810 if (!text)
00811 return;
00812
00813 va_start(argsPtr, text);
00814 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
00815 va_end(argsPtr);
00816
00817 this->WriteAllExceptSender(user, serversource, status, std::string(textbuffer));
00818 }
00819
00820 void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const char* text, ...)
00821 {
00822 char textbuffer[MAXBUF];
00823 va_list argsPtr;
00824
00825 if (!text)
00826 return;
00827
00828 va_start(argsPtr, text);
00829 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
00830 va_end(argsPtr);
00831
00832 this->WriteAllExcept(user, serversource, status, except_list, std::string(textbuffer));
00833 }
00834
00835 void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &text)
00836 {
00837 CUList *ulist = this->GetUsers();
00838 char tb[MAXBUF];
00839
00840 snprintf(tb,MAXBUF,":%s %s", user->GetFullHost().c_str(), text.c_str());
00841 std::string out = tb;
00842
00843 for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
00844 {
00845 if ((IS_LOCAL(i->first)) && (except_list.find(i->first) == except_list.end()))
00846 {
00847
00848 if (status && !strchr(this->GetAllPrefixChars(i->first), status))
00849 continue;
00850
00851 if (serversource)
00852 i->first->WriteServ(text);
00853 else
00854 i->first->Write(out);
00855 }
00856 }
00857 }
00858
00859 void Channel::WriteAllExceptSender(User* user, bool serversource, char status, const std::string& text)
00860 {
00861 CUList except_list;
00862 except_list[user] = user->nick;
00863 this->WriteAllExcept(user, serversource, status, except_list, std::string(text));
00864 }
00865
00866
00867
00868
00869
00870 int Channel::CountInvisible()
00871 {
00872 int count = 0;
00873 CUList *ulist= this->GetUsers();
00874 for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
00875 {
00876 if (!(i->first->IsModeSet('i')))
00877 count++;
00878 }
00879
00880 return count;
00881 }
00882
00883 char* Channel::ChanModes(bool showkey)
00884 {
00885 static char scratch[MAXBUF];
00886 static char sparam[MAXBUF];
00887 char* offset = scratch;
00888 std::string extparam;
00889
00890 *scratch = '\0';
00891 *sparam = '\0';
00892
00893
00894 for(int n = 0; n < 64; n++)
00895 {
00896 if(this->modes[n])
00897 {
00898 *offset++ = n + 65;
00899 extparam.clear();
00900 switch (n)
00901 {
00902 case CM_KEY:
00903
00904 if (showkey)
00905 {
00906 extparam = this->GetModeParameter('k');
00907 }
00908 else
00909 {
00910 extparam = "<key>";
00911 }
00912 break;
00913 case CM_NOEXTERNAL:
00914 case CM_TOPICLOCK:
00915 case CM_INVITEONLY:
00916 case CM_MODERATED:
00917 case CM_SECRET:
00918 case CM_PRIVATE:
00919
00920 break;
00921 default:
00922 extparam = this->GetModeParameter(n + 65);
00923 break;
00924 }
00925 if (!extparam.empty())
00926 {
00927 charlcat(sparam,' ',MAXBUF);
00928 strlcat(sparam,extparam.c_str(),MAXBUF);
00929 }
00930 }
00931 }
00932
00933
00934 *offset = '\0';
00935 strlcat(scratch,sparam,MAXBUF);
00936 return scratch;
00937 }
00938
00939
00940
00941
00942 void Channel::UserList(User *user, CUList *ulist)
00943 {
00944 char list[MAXBUF];
00945 size_t dlen, curlen;
00946 int MOD_RESULT = 0;
00947 bool call_modules = true;
00948
00949 if (!IS_LOCAL(user))
00950 return;
00951
00952 FOREACH_RESULT(I_OnUserList,OnUserList(user, this, ulist));
00953 if (MOD_RESULT == 1)
00954 call_modules = false;
00955
00956 if (MOD_RESULT != -1)
00957 {
00958 if ((this->IsModeSet('s')) && (!this->HasUser(user)))
00959 {
00960 user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), this->name.c_str());
00961 return;
00962 }
00963 }
00964
00965 dlen = curlen = snprintf(list,MAXBUF,"%s %c %s :", user->nick.c_str(), this->IsModeSet('s') ? '@' : this->IsModeSet('p') ? '*' : '=', this->name.c_str());
00966
00967 int numusers = 0;
00968 char* ptr = list + dlen;
00969
00970 if (!ulist)
00971 ulist = this->GetUsers();
00972
00973
00974
00975
00976 bool has_user = this->HasUser(user);
00977
00978 for (CUList::iterator i = ulist->begin(); i != ulist->end(); i++)
00979 {
00980 if ((!has_user) && (i->first->IsModeSet('i')))
00981 {
00982
00983
00984
00985