diff options
| author | Adam <Adam@Anope.org> | 2010-05-25 00:57:25 -0500 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2010-06-18 21:04:07 -0400 |
| commit | 4a2b9ebcf38d6c0a2860b966421b3af125438488 (patch) | |
| tree | e4af4e59fd29352138db0fb0ff614d50233850b8 /src/channels.c | |
| parent | 2fba686904e6f78ebab35df171c5757afeebf05d (diff) | |
Renamed all of source files from .c to .cpp
Diffstat (limited to 'src/channels.c')
| -rw-r--r-- | src/channels.c | 1929 |
1 files changed, 0 insertions, 1929 deletions
diff --git a/src/channels.c b/src/channels.c deleted file mode 100644 index 5a439726f..000000000 --- a/src/channels.c +++ /dev/null @@ -1,1929 +0,0 @@ -/* Channel-handling routines. - * - * (C) 2003-2010 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * - */ - -#include "services.h" -#include "language.h" -#include "modules.h" - -channel_map ChannelList; - -/** Default constructor - * @param name The channel name - * @param ts The time the channel was created - */ -Channel::Channel(const std::string &name, time_t ts) -{ - if (name.empty()) - throw CoreException("A channel without a name ?"); - - this->name = name; - - ChannelList[this->name.c_str()] = this; - - this->creation_time = ts; - this->topic = NULL; - this->bans = this->excepts = this->invites = NULL; - this->bd = NULL; - this->server_modetime = this->chanserv_modetime = 0; - this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_sync = this->topic_time = 0; - - this->ci = cs_findchan(this->name); - if (this->ci) - this->ci->c = this; - - FOREACH_MOD(I_OnChannelCreate, OnChannelCreate(this)); -} - -/** Default destructor - */ -Channel::~Channel() -{ - BanData *bd, *next; - - FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this)); - - Alog(LOG_DEBUG) << "Deleting channel " << this->name; - - for (bd = this->bd; bd; bd = next) - { - if (bd->mask) - delete [] bd->mask; - next = bd->next; - delete bd; - } - - if (this->ci) - this->ci->c = NULL; - - if (this->topic) - delete [] this->topic; - - if (this->bans && this->bans->count) - { - while (this->bans->entries) - entry_delete(this->bans, this->bans->entries); - } - - if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) - { - if (this->excepts && this->excepts->count) - { - while (this->excepts->entries) - entry_delete(this->excepts, this->excepts->entries); - } - } - - if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)) - { - if (this->invites && this->invites->count) - { - while (this->invites->entries) - entry_delete(this->invites, this->invites->entries); - } - } - - ChannelList.erase(this->name.c_str()); -} - -void Channel::Sync() -{ - if (this->ci) - { - check_modes(this); - stick_all(this->ci); - } - - if (Me && Me->IsSynced() && !this->topic_sync) - restore_topic(name.c_str()); -} - -void Channel::JoinUser(User *user) -{ - Alog(LOG_DEBUG) << user->nick << " joins " << this->name; - - Flags<ChannelModeName> *Status = new Flags<ChannelModeName>; - ChannelContainer *cc = new ChannelContainer(this); - cc->Status = Status; - user->chans.push_back(cc); - - UserContainer *uc = new UserContainer(user); - uc->Status = Status; - this->users.push_back(uc); - - if (get_ignore(user->nick.c_str()) == NULL) - { - if (this->ci && (check_access(user, this->ci, CA_MEMO)) && (this->ci->memos.memos.size() > 0)) - { - if (this->ci->memos.memos.size() == 1) - notice_lang(Config.s_MemoServ, user, MEMO_X_ONE_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); - else - notice_lang(Config.s_MemoServ, user, MEMO_X_MANY_NOTICE, this->ci->memos.memos.size(), this->ci->name.c_str()); - } - /* Added channelname to entrymsg - 30.03.2004, Certus */ - /* Also, don't send the entrymsg when bursting -GD */ - if (this->ci && this->ci->entry_message && user->server->IsSynced()) - user->SendMessage(whosends(this->ci)->nick, "[%s] %s", this->name.c_str(), this->ci->entry_message); - } - - /** - * We let the bot join even if it was an ignored user, as if we don't, - * and the ignored user doesnt just leave, the bot will never - * make it into the channel, leaving the channel botless even for - * legit users - Rob - * But don't join the bot if the channel is persistant - Adam - * But join persistant channels when syncing with our uplink- DP - **/ - if (Config.s_BotServ && this->ci && this->ci->bi && (!Me->IsSynced() || !this->ci->HasFlag(CI_PERSIST))) - { - if (this->users.size() == Config.BSMinUsers) - bot_join(this->ci); - } - if (Config.s_BotServ && this->ci && this->ci->bi) - { - if (this->users.size() >= Config.BSMinUsers && (this->ci->botflags.HasFlag(BS_GREET)) - && user->Account() && user->Account()->greet && check_access(user, this->ci, CA_GREET)) - { - /* Only display the greet if the main uplink we're connected - * to has synced, or we'll get greet-floods when the net - * recovers from a netsplit. -GD - */ - if (user->server->IsSynced()) - { - ircdproto->SendPrivmsg(this->ci->bi, this->name.c_str(), "[%s] %s", user->Account()->display, user->Account()->greet); - this->ci->bi->lastmsg = time(NULL); - } - } - } -} - -/** Remove a user internally from the channel - * @param u The user - */ -void Channel::DeleteUser(User *user) -{ - if (this->ci) - update_cs_lastseen(user, this->ci); - - CUserList::iterator cit; - for (cit = this->users.begin(); (*cit)->user != user && cit != this->users.end(); ++cit); - if (cit == this->users.end()) - { - Alog(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant user " << user->nick << " from channel " << this->name; - return; - } - - delete (*cit)->Status; - delete *cit; - this->users.erase(cit); - - UChannelList::iterator uit; - for (uit = user->chans.begin(); (*uit)->chan != this && uit != user->chans.end(); ++uit); - if (uit == user->chans.end()) - { - Alog(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant channel " << this->name << " from " << user->nick << "'s channel list"; - return; - } - - delete *uit; - user->chans.erase(uit); - - /* Channel is persistant, it shouldn't be deleted and the service bot should stay */ - if (this->HasFlag(CH_PERSIST) || (this->ci && this->ci->HasFlag(CI_PERSIST))) - return; - - /* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediatly - * We also don't part the bot here either, if necessary we will part it after the sync - */ - if (this->HasFlag(CH_SYNCING)) - return; - - /* Additionally, do not delete this channel if ChanServ/a BotServ bot is inhabiting it */ - if (this->ci && this->ci->HasFlag(CI_INHABIT)) - return; - - if (Config.s_BotServ && this->ci && this->ci->bi && this->users.size() <= Config.BSMinUsers - 1) - ircdproto->SendPart(this->ci->bi, this, NULL); - - if (this->users.empty()) - delete this; -} - -/** Check if the user is on the channel - * @param u The user - * @return A user container if found, else NULL - */ -UserContainer *Channel::FindUser(User *u) -{ - for (CUserList::iterator it = this->users.begin(); it != this->users.end(); ++it) - if ((*it)->user == u) - return *it; - return NULL; -} - -/** Check if a user has a status on a channel - * @param u The user - * @param cms The status mode, or NULL to represent no status - * @return true or false - */ -bool Channel::HasUserStatus(User *u, ChannelModeStatus *cms) -{ - if (!u || (cms && cms->Type != MODE_STATUS)) - throw CoreException("Channel::HasUserStatus got bad mode"); - - /* Usually its more efficient to search the users channels than the channels users */ - ChannelContainer *cc = u->FindChannel(this); - if (cc) - { - if (cms) - return cc->Status->HasFlag(cms->Name); - else - return !cc->Status->FlagCount(); - } - - return false; -} - -/** Check if a user has a status on a channel - * Use the overloaded function for ChannelModeStatus* to check for no status - * @param u The user - * @param Name The Mode name, eg CMODE_OP, CMODE_VOICE - * @return true or false - */ -bool Channel::HasUserStatus(User *u, ChannelModeName Name) -{ - return HasUserStatus(u, dynamic_cast<ChannelModeStatus *>(ModeManager::FindChannelModeByName(Name))); -} - -/** - * See if a channel has a mode - * @param Name The mode name - * @return true or false - */ -bool Channel::HasMode(ChannelModeName Name) -{ - return modes.HasFlag(Name); -} - -/** Set a mode internally on a channel, this is not sent out to the IRCd - * @param cm The mode - * @param param The param - * @param EnforeMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::SetModeInternal(ChannelMode *cm, const std::string ¶m, bool EnforceMLock) -{ - if (!cm) - return; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnChannelModeSet, OnChannelModeSet(this, cm->Name, param)); - - /* Setting v/h/o/a/q etc */ - if (cm->Type == MODE_STATUS) - { - if (param.empty()) - { - Alog() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; - return; - } - - /* We don't track bots */ - if (findbot(param)) - return; - - User *u = finduser(param); - if (!u) - { - Alog(LOG_DEBUG) << "MODE " << this->name << " +" << cm->ModeChar << " for nonexistant user " << param; - return; - } - - Alog(LOG_DEBUG) << "Setting +" << cm->ModeChar << " on " << this->name << " for " << u->nick; - - /* Set the status on the user */ - ChannelContainer *cc = u->FindChannel(this); - if (cc) - { - cc->Status->SetFlag(cm->Name); - } - - /* Enforce secureops, etc */ - chan_set_correct_modes(u, this, 0); - return; - } - /* Setting b/e/I etc */ - else if (cm->Type == MODE_LIST) - { - if (param.empty()) - { - Alog() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; - return; - } - - ChannelModeList *cml = dynamic_cast<ChannelModeList *>(cm); - cml->AddMask(this, param.c_str()); - return; - } - - modes.SetFlag(cm->Name); - - if (!param.empty()) - { - if (cm->Type != MODE_PARAM) - { - Alog() << "Channel::SetModeInternal() mode " << cm->ModeChar << " for " << this->name << " with a paramater, but its not a param mode"; - return; - } - - /* They could be resetting the mode to change its params */ - std::map<ChannelModeName, std::string>::iterator it = Params.find(cm->Name); - if (it != Params.end()) - { - Params.erase(it); - } - - Params.insert(std::make_pair(cm->Name, param)); - } - - /* Channel mode +P or so was set, mark this channel as persistant */ - if (cm->Name == CMODE_PERM) - { - this->SetFlag(CH_PERSIST); - if (ci) - ci->SetFlag(CI_PERSIST); - } - - /* Check if we should enforce mlock */ - if (!EnforceMLock || MOD_RESULT == EVENT_STOP) - return; - - /* Non registered channels can not be +r */ - if (!ci && HasMode(CMODE_REGISTERED)) - { - RemoveMode(NULL, CMODE_REGISTERED); - } - - /* Non registered channel has no mlock */ - if (!ci) - { - return; - } - - /* If this channel has this mode locked negative */ - if (ci->HasMLock(cm->Name, false)) - { - /* Remove the mode */ - if (cm->Type == MODE_PARAM) - { - std::string cparam; - GetParam(cm->Name, cparam); - RemoveMode(NULL, cm, cparam); - } - else if (cm->Type == MODE_REGULAR) - RemoveMode(NULL, cm); - } - /* If this is a param mode and its mlocked +, check to ensure someone didn't reset it with the wrong param */ - else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true)) - { - ChannelModeParam *cmp = dynamic_cast<ChannelModeParam *>(cm); - std::string cparam, ciparam; - /* Get the param currently set on this channel */ - GetParam(cmp->Name, cparam); - /* Get the param set in mlock */ - ci->GetParam(cmp->Name, ciparam); - - /* We have the wrong param set */ - if (cparam.empty() || ciparam.empty() || cparam != ciparam) - { - /* Reset the mode with the correct param */ - SetMode(NULL, cm, ciparam); - } - } -} - -/** Remove a mode internally on a channel, this is not sent out to the IRCd - * @param cm The mode - * @param param The param - * @param EnforceMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::RemoveModeInternal(ChannelMode *cm, const std::string ¶m, bool EnforceMLock) -{ - if (!cm) - return; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnChannelModeUnset, OnChannelModeUnset(this, cm->Name, param)); - - /* Setting v/h/o/a/q etc */ - if (cm->Type == MODE_STATUS) - { - if (param.empty()) - { - Alog() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; - return; - } - - /* Reset modes on bots if we're supposed to */ - BotInfo *bi = findbot(param); - if (bi) - { - if (std::find(BotModes.begin(), BotModes.end(), cm) != BotModes.end()) - { - this->SetMode(bi, cm, bi->nick); - } - /* We don't track bots */ - return; - } - - User *u = finduser(param); - if (!u) - { - Alog() << "Channel::RemoveModeInternal() MODE " << this->name << "-" << cm->ModeChar << " for nonexistant user " << param; - return; - } - - Alog(LOG_DEBUG) << "Setting -" << cm->ModeChar << " on " << this->name << " for " << u->nick; - - /* Remove the status on the user */ - ChannelContainer *cc = u->FindChannel(this); - if (cc) - { - cc->Status->UnsetFlag(cm->Name); - } - - return; - } - /* Setting b/e/I etc */ - else if (cm->Type == MODE_LIST) - { - if (param.empty()) - { - Alog() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; - return; - } - - ChannelModeList *cml = dynamic_cast<ChannelModeList *>(cm); - cml->DelMask(this, param.c_str()); - return; - } - - modes.UnsetFlag(cm->Name); - - if (cm->Type == MODE_PARAM) - { - std::map<ChannelModeName, std::string>::iterator it = Params.find(cm->Name); - if (it != Params.end()) - { - Params.erase(it); - } - } - - if (cm->Name == CMODE_PERM) - { - this->UnsetFlag(CH_PERSIST); - - if (ci) - { - ci->UnsetFlag(CI_PERSIST); - if (Config.s_BotServ && ci->bi && users.size() == Config.BSMinUsers - 1) - ircdproto->SendPart(ci->bi, this, NULL); - } - } - - /* We set -P in an empty channel, delete the channel */ - if (cm->Name == CMODE_PERM && users.empty()) - { - delete this; - return; - } - - /* Check for mlock */ - - /* Non registered channel, no mlock */ - if (!ci || !EnforceMLock || MOD_RESULT == EVENT_STOP) - return; - - /* This channel has this the mode locked on */ - if (ci->HasMLock(cm->Name, true)) - { - if (cm->Type == MODE_REGULAR) - { - /* Set the mode */ - SetMode(NULL, cm); - } - /* This is a param mode */ - else if (cm->Type == MODE_PARAM) - { - std::string cparam; - /* Get the param stored in mlock for this mode */ - if (ci->GetParam(cm->Name, cparam)) - SetMode(NULL, cm, cparam); - } - } -} - -/** Set a mode on a channel - * @param bi The client setting the modes - * @param cm The mode - * @param param Optional param arg for the mode - * @param EnforceMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const std::string ¶m, bool EnforceMLock) -{ - if (!cm) - return; - /* Don't set modes already set */ - if (cm->Type == MODE_REGULAR && HasMode(cm->Name)) - return; - else if (cm->Type == MODE_PARAM && HasMode(cm->Name)) - { - std::string cparam; - if (GetParam(cm->Name, cparam)) - { - if (cparam == param) - { - return; - } - } - } - else if (cm->Type == MODE_STATUS) - { - User *u = finduser(param); - if (u && HasUserStatus(u, dynamic_cast<ChannelModeStatus *>(cm))) - return; - } - else if (cm->Type == MODE_LIST) - { - // XXX this needs rewritten - } - - ModeManager::StackerAdd(bi, this, cm, true, param); - SetModeInternal(cm, param, EnforceMLock); -} - -/** - * Set a mode on a channel - * @param bi The client setting the modes - * @param Name The mode name - * @param param Optional param arg for the mode - * @param EnforceMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::SetMode(BotInfo *bi, ChannelModeName Name, const std::string ¶m, bool EnforceMLock) -{ - SetMode(bi, ModeManager::FindChannelModeByName(Name), param, EnforceMLock); -} - -/** - * Set a mode on a channel - * @param bi The client setting the modes - * @param Mode The mode - * @param param Optional param arg for the mode - * @param EnforceMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::SetMode(BotInfo *bi, char Mode, const std::string ¶m, bool EnforceMLock) -{ - SetMode(bi, ModeManager::FindChannelModeByChar(Mode), param, EnforceMLock); -} - -/** Remove a mode from a channel - * @param bi The client setting the modes - * @param cm The mode - * @param param Optional param arg for the mode - * @param EnforceMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const std::string ¶m, bool EnforceMLock) -{ - if (!cm) - return; - /* Don't unset modes that arent set */ - if ((cm->Type == MODE_REGULAR || cm->Type == MODE_PARAM) && !HasMode(cm->Name)) - return; - /* Don't unset status that aren't set */ - else if (cm->Type == MODE_STATUS) - { - User *u = finduser(param); - if (u && !HasUserStatus(u, dynamic_cast<ChannelModeStatus *>(cm))) - return; - } - else if (cm->Type == MODE_LIST) - { - // XXX this needs to be rewritten sometime - } - - /* If this mode needs no param when being unset, empty the param */ - bool SendParam = true; - if (cm->Type == MODE_PARAM) - { - ChannelModeParam *cmp = dynamic_cast<ChannelModeParam *>(cm); - if (cmp->MinusNoArg) - SendParam = false; - } - - ModeManager::StackerAdd(bi, this, cm, false, param); - RemoveModeInternal(cm, SendParam ? param : "", EnforceMLock); -} - -/** - * Remove a mode from a channel - * @param bi The client setting the modes - * @param Name The mode name - * @param param Optional param arg for the mode - * @param EnforceMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::RemoveMode(BotInfo *bi, ChannelModeName Name, const std::string ¶m, bool EnforceMLock) -{ - RemoveMode(bi, ModeManager::FindChannelModeByName(Name), param, EnforceMLock); -} - -/** - * Remove a mode from a channel - * @param bi The client setting the modes - * @param Mode The mode - * @param param Optional param arg for the mode - * @param EnforceMLock true if mlocks should be enforced, false to override mlock - */ -void Channel::RemoveMode(BotInfo *bi, char Mode, const std::string ¶m, bool EnforceMLock) -{ - RemoveMode(bi, ModeManager::FindChannelModeByChar(Mode), param, EnforceMLock); -} - -/** Get a param from the channel - * @param Name The mode - * @param Target a string to put the param into - * @return true on success - */ -const bool Channel::GetParam(ChannelModeName Name, std::string &Target) -{ - std::map<ChannelModeName, std::string>::iterator it = Params.find(Name); - - Target.clear(); - - if (it != Params.end()) - { - Target = it->second; - return true; - } - - return false; -} - -/** Check if a mode is set and has a param - * @param Name The mode - */ -const bool Channel::HasParam(ChannelModeName Name) -{ - std::map<ChannelModeName, std::string>::iterator it = Params.find(Name); - - if (it != Params.end()) - { - return true; - } - - return false; -} - -/*************************************************************************/ - -/** Clear all the modes from the channel - * @param bi The client setting the modes - */ -void Channel::ClearModes(BotInfo *bi) -{ - ChannelMode *cm; - - for (size_t n = CMODE_BEGIN + 1; n != CMODE_END; ++n) - { - cm = ModeManager::FindChannelModeByName(static_cast<ChannelModeName>(n)); - - if (cm && this->HasMode(cm->Name)) - { - if (cm->Type == MODE_REGULAR) - { - this->RemoveMode(NULL, cm); - } - else if (cm->Type == MODE_PARAM) - { - std::string param; - this->GetParam(cm->Name, param); - this->RemoveMode(NULL, cm, param); - } - } - } - - modes.ClearFlags(); -} - -/** Clear all the bans from the channel - * @param bi The client setting the modes - */ -void Channel::ClearBans(BotInfo *bi) -{ - Entry *entry, *nexte; - ChannelModeList *cml; - - cml = dynamic_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_BAN)); - - if (cml && this->bans && this->bans->count) - { - for (entry = this->bans->entries; entry; entry = nexte) - { - nexte = entry->next; - - this->RemoveMode(bi, CMODE_BAN, entry->mask); - } - } -} - -/** Clear all the excepts from the channel - * @param bi The client setting the modes - */ -void Channel::ClearExcepts(BotInfo *bi) -{ - Entry *entry, *nexte; - ChannelModeList *cml; - - cml = dynamic_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_EXCEPT)); - - if (cml && this->excepts && this->excepts->count) - { - for (entry = this->excepts->entries; entry; entry = nexte) - { - nexte = entry->next; - - this->RemoveMode(bi, CMODE_EXCEPT, entry->mask); - } - } -} - -/** Clear all the invites from the channel - * @param bi The client setting the modes - */ -void Channel::ClearInvites(BotInfo *bi) -{ - Entry *entry, *nexte; - ChannelModeList *cml; - - cml = dynamic_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)); - - if (cml && this->invites && this->invites->count) - { - for (entry = this->invites->entries; entry; entry = nexte) - { - nexte = entry->next; - - this->RemoveMode(bi, CMODE_INVITEOVERRIDE, entry->mask); - } - } -} - -/** Set a string of modes on the channel - * @param bi The client setting the modes - * @param EnforceMLock Should mlock be enforced on this mode change - * @param cmodes The modes to set - */ -void Channel::SetModes(BotInfo *bi, bool EnforceMLock, const char *cmodes, ...) -{ - char buf[BUFSIZE] = ""; - va_list args; - std::string modebuf, sbuf; - int add = -1; - va_start(args, cmodes); - vsnprintf(buf, BUFSIZE - 1, cmodes, args); - va_end(args); - - spacesepstream sep(buf); - sep.GetToken(modebuf); - for (unsigned i = 0; i < modebuf.size(); ++i) - { - ChannelMode *cm; - - switch (modebuf[i]) - { - case '+': - add = 1; - continue; - case '-': - add = 0; - continue; - default: - if (add == -1) - continue; - cm = ModeManager::FindChannelModeByChar(modebuf[i]); - if (!cm) - continue; - } - - if (add) - { - if (cm->Type != MODE_REGULAR && sep.GetToken(sbuf)) - this->SetMode(bi, cm, sbuf, EnforceMLock); - else - this->SetMode(bi, cm, "", EnforceMLock); - } - else if (add == 0) - { - if (cm->Type != MODE_REGULAR && sep.GetToken(sbuf)) - this->RemoveMode(bi, cm, sbuf, EnforceMLock); - else - this->RemoveMode(bi, cm, "", EnforceMLock); - } - } -} - -/*************************************************************************/ - -/** Set modes internally on the channel - * @param c The channel - * @param ac Number of args - * @param av args - */ -void ChanSetInternalModes(Channel *c, int ac, const char **av) -{ - if (!ac) - return; - - int k = 0, j = 0, add = -1; - for (unsigned int i = 0; i < strlen(av[0]); ++i) - { - ChannelMode *cm; - - switch (av[0][i]) - { - case '+': - add = 1; - continue; - case '-': - add = 0; - continue; - default: - if (add == -1) - continue; - cm = ModeManager::FindChannelModeByChar(av[0][i]); - if (!cm) - continue; - } - - if (cm->Type == MODE_REGULAR) - { - if (add) - c->SetModeInternal(cm); - else - c->RemoveModeInternal(cm); - continue; - } - else if (cm->Type == MODE_PARAM) - { - ChannelModeParam *cmp = dynamic_cast<ChannelModeParam *>(cm); - - if (!add && cmp->MinusNoArg) - { - c->RemoveModeInternal(cm); - ++k; - continue; - } - } - if (++j < ac) - { - if (add) - c->SetModeInternal(cm, av[j]); - else - c->RemoveModeInternal(cm, av[j]); - } - else - { - Alog() << "warning: ChanSetInternalModes() recieved more modes requiring params than params, modes: " << merge_args(ac, av) << ", ac: " << ac << ", j: " << j; - } - } - - if (j + k + 1 < ac) - { - Alog() << "warning: ChanSetInternalModes() recieved more params than modes requiring them, modes: " << merge_args(ac, av) << ", ac: " << ac << ", j: " << j << " k: " << k; - } -} - -/** Kick a user from a channel internally - * @param source The sender of the kick - * @param nick The nick being kicked - * @param reason The reason for the kick - */ -void Channel::KickInternal(const std::string &source, const std::string &nick, const std::string &reason) -{ - /* If it is the bot that is being kicked, we make it rejoin the - * channel and stop immediately. - * --lara - */ - if (Config.s_BotServ && this->ci && findbot(nick)) - { - bot_join(this->ci); - return; - } - - User *user = finduser(nick); - if (!user) - { - Alog(LOG_DEBUG) << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason; - return; - } - - Alog(LOG_DEBUG) << "Channel::KickInternal kicking " << user->nick << " from " << this->name; - - if (user->FindChannel(this)) - { - FOREACH_MOD(I_OnUserKicked, OnUserKicked(this, user, source, reason)); - this->DeleteUser(user); - } - else - Alog(LOG_DEBUG) << "Channel::KickInternal got kick for user " << user->nick << " who isn't on channel " << this->name << " ?"; -} - -/** Kick a user from the channel - * @param bi The sender, can be NULL for the service bot for this channel - * @param u The user being kicked - * @param reason The reason for the kick - * @return true if the kick was scucessful, false if a module blocked the kick - */ -bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) -{ - va_list args; - char buf[BUFSIZE] = ""; - va_start(args, reason); - vsnprintf(buf, BUFSIZE - 1, reason, args); - va_end(args); - - /* May not kick ulines */ - if (u->server->IsULined()) - return false; - - /* Do not kick protected clients */ - if (u->IsProtected()) - return false; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnBotKick, OnBotKick(bi, this, u, buf)); - if (MOD_RESULT == EVENT_STOP) - return false; - ircdproto->SendKick(bi ? bi : whosends(this->ci), this, u, "%s", buf); - this->KickInternal(bi ? bi->nick : whosends(this->ci)->nick, u->nick, buf); - return true; -} - -/* Returns a fully featured binary modes string. If complete is 0, the - * eventual parameters won't be added to the string. - */ - -char *chan_get_modes(Channel * chan, int complete, int plus) -{ - static char res[BUFSIZE]; - char params[BUFSIZE]; - char *end = res, *value, *pend = params, *pend2 = params; - std::string param; - - if (chan->HasModes()) - { - for (std::list<Mode *>::iterator it = ModeManager::Modes.begin(); it != ModeManager::Modes.end(); ++it) - { - if ((*it)->Class != MC_CHANNEL) - continue; - - ChannelMode *cm = dynamic_cast<ChannelMode *>(*it); - - if (chan->HasMode(cm->Name)) - { - *end++ = cm->ModeChar; - - if (complete) - { - if (cm->Type == MODE_PARAM) - { - ChannelModeParam *cmp = dynamic_cast<ChannelModeParam *>(cm); - - if (plus || !cmp->MinusNoArg) - { - chan->GetParam(cmp->Name, param); - - if (!param.empty()) - { - value = const_cast<char *>(param.c_str()); - - *pend++ = ' '; - - while (*value) - *pend++ = *value++; - } - } - } - } - } - } - - while (*pend2) - *end++ = *pend2++; - } - - *end = 0; - - return res; -} - -/*************************************************************************/ - -Channel *findchan(const char *chan) -{ - return findchan(ci::string(chan)); -} - -Channel *findchan(const std::string &chan) -{ - return findchan(ci::string(chan.c_str())); -} - -Channel *findchan(const ci::string &chan) -{ - channel_map::const_iterator it = ChannelList.find(chan); - - if (it != ChannelList.end()) - return it->second; - return NULL; -} - -/*************************************************************************/ - -/* Return statistics. Pointers are assumed to be valid. */ - -void get_channel_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - BanData *bd; - std::string buf; - - for (channel_map::const_iterator cit = ChannelList.begin(); cit != ChannelList.end(); ++cit) - { - Channel *chan = cit->second; - - count++; - mem += sizeof(*chan); - if (chan->topic) - mem += strlen(chan->topic) + 1; - if (chan->GetParam(CMODE_KEY, buf)) - mem += buf.length() + 1; - if (chan->GetParam(CMODE_FLOOD, buf)) - mem += buf.length() + 1; - if (chan->GetParam(CMODE_REDIRECT, buf)) - mem += buf.length() + 1; - mem += get_memuse(chan->bans); - if (ModeManager::FindChannelModeByName(CMODE_EXCEPT)) - mem += get_memuse(chan->excepts); - if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)) - mem += get_memuse(chan->invites); - for (CUserList::iterator it = chan->users.begin(); it != chan->users.end(); ++it) - { - mem += sizeof(*it); - mem += sizeof((*it)->ud); - if ((*it)->ud.lastline) - mem += strlen((*it)->ud.lastline) + 1; - } - for (bd = chan->bd; bd; bd = bd->next) { - if (bd->mask) - mem += strlen(bd->mask) + 1; - mem += sizeof(*bd); - } - } - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ - -/* Is the given nick on the given channel? - This function supports links. */ - -User *nc_on_chan(Channel * c, NickCore * nc) -{ - if (!c || !nc) - return NULL; - - for (CUserList::iterator it = c->users.begin(); it != c->users.end(); ++it) - { - UserContainer *uc = *it; - - if (uc->user->Account() == nc) - return uc->user; - } - return NULL; -} - -/*************************************************************************/ -/*************************** Message Handling ****************************/ -/*************************************************************************/ - -/* Handle a JOIN command. - * av[0] = channels to join - */ - -void do_join(const char *source, int ac, const char **av) -{ - User *user; - Channel *chan; - time_t ctime = time(NULL); - - user = finduser(source); - if (!user) - { - Alog(LOG_DEBUG) << "JOIN from nonexistent user " << source << ": " << merge_args(ac, av); - return; - } - - commasepstream sep(av[0]); - ci::string buf; - while (sep.GetToken(buf)) - { - if (buf[0] == '0') - { - for (UChannelList::iterator it = user->chans.begin(); it != user->chans.end();) - { - ChannelContainer *cc = *it++; - - std::string channame = cc->chan->name; - FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, cc->chan)); - cc->chan->DeleteUser(user); - FOREACH_MOD(I_OnPartChannel, OnPartChannel(user, findchan(channame.c_str()), channame, "")); - } - user->chans.clear(); - continue; - } - - chan = findchan(buf.c_str()); - - /* Channel doesn't exist, create it */ - if (!chan) - { - chan = new Channel(av[0], ctime); - } - - /* Join came with a TS */ - if (ac == 2) - { - time_t ts = atol(av[1]); - - /* Their time is older, we |
