summaryrefslogtreecommitdiff
path: root/src/channels.c
diff options
context:
space:
mode:
authorAdam <Adam@Anope.org>2010-05-25 00:57:25 -0500
committerAdam <Adam@anope.org>2010-06-18 21:04:07 -0400
commit4a2b9ebcf38d6c0a2860b966421b3af125438488 (patch)
treee4af4e59fd29352138db0fb0ff614d50233850b8 /src/channels.c
parent2fba686904e6f78ebab35df171c5757afeebf05d (diff)
Renamed all of source files from .c to .cpp
Diffstat (limited to 'src/channels.c')
-rw-r--r--src/channels.c1929
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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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 &param, 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