namespace
{
ChanModeReference ban(NULL, "ban");
- ChanModeReference inviteonlymode(NULL, "inviteonly");
- ChanModeReference keymode(NULL, "key");
- ChanModeReference limitmode(NULL, "limit");
}
Channel::Channel(const std::string &cname, time_t ts)
modes[mh->GetId()] = on;
}
-void Channel::SetTopic(User* u, const std::string& ntopic)
+void Channel::SetTopic(User* u, const std::string& ntopic, time_t topicts, const std::string* setter)
{
- this->topic.assign(ntopic, 0, ServerInstance->Config->Limits.MaxTopic);
- this->setby.assign(ServerInstance->Config->FullHostInTopic ? u->GetFullHost() : u->nick, 0, 128);
- this->WriteChannel(u, "TOPIC %s :%s", this->name.c_str(), this->topic.c_str());
- this->topicset = ServerInstance->Time();
+ // Send a TOPIC message to the channel only if the new topic text differs
+ if (this->topic != ntopic)
+ {
+ this->topic = ntopic;
+ ClientProtocol::Messages::Topic topicmsg(u, this, this->topic);
+ Write(ServerInstance->GetRFCEvents().topic, topicmsg);
+ }
+
+ // Always update setter and set time
+ if (!setter)
+ setter = ServerInstance->Config->FullHostInTopic ? &u->GetFullHost() : &u->nick;
+ this->setby.assign(*setter, 0, ServerInstance->Config->Limits.GetMaxMask());
+ this->topicset = topicts;
FOREACH_MOD(OnPostTopicChange, (u, this, this->topic));
}
if (mode->IsPrefixMode())
continue;
- if (mode->GetNumParams(true))
+ if (mode->NeedsParam(true))
{
list.GetToken(parameter);
// If the parameter begins with a ':' then it's invalid
else
parameter.clear();
- if ((mode->GetNumParams(true)) && (parameter.empty()))
+ if ((mode->NeedsParam(true)) && (parameter.empty()))
continue;
mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, parameter, true);
{
unsigned int opermaxchans = ConvToInt(user->oper->getConfig("maxchans"));
// If not set, use 2.0's <channels:opers>, if that's not set either, use limit from CC
- if (!opermaxchans)
+ if (!opermaxchans && user->HasPrivPermission("channels/high-join-limit"))
opermaxchans = ServerInstance->Config->OperMaxChans;
if (opermaxchans)
maxchans = opermaxchans;
}
if (user->chans.size() >= maxchans)
{
- user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s :You are on too many channels", cname.c_str());
+ user->WriteNumeric(ERR_TOOMANYCHANNELS, cname, "You are on too many channels");
return NULL;
}
}
return NULL;
// If no module returned MOD_RES_DENY or MOD_RES_ALLOW (which is the case
- // most of the time) then proceed to check channel modes +k, +i, +l and bans,
- // in this order.
+ // most of the time) then proceed to check channel bans.
+ //
// If a module explicitly allowed the join (by returning MOD_RES_ALLOW),
// then this entire section is skipped
if (MOD_RESULT == MOD_RES_PASSTHRU)
{
- std::string ckey = chan->GetModeParameter(keymode);
- if (!ckey.empty())
- {
- FIRST_MOD_RESULT(OnCheckKey, MOD_RESULT, (user, chan, key));
- if (!MOD_RESULT.check(InspIRCd::TimingSafeCompare(ckey, key)))
- {
- // If no key provided, or key is not the right one, and can't bypass +k (not invited or option not enabled)
- user->WriteNumeric(ERR_BADCHANNELKEY, "%s :Cannot join channel (Incorrect channel key)", chan->name.c_str());
- return NULL;
- }
- }
-
- if (chan->IsModeSet(inviteonlymode))
- {
- FIRST_MOD_RESULT(OnCheckInvite, MOD_RESULT, (user, chan));
- if (MOD_RESULT != MOD_RES_ALLOW)
- {
- user->WriteNumeric(ERR_INVITEONLYCHAN, "%s :Cannot join channel (Invite only)", chan->name.c_str());
- return NULL;
- }
- }
-
- std::string limit = chan->GetModeParameter(limitmode);
- if (!limit.empty())
- {
- FIRST_MOD_RESULT(OnCheckLimit, MOD_RESULT, (user, chan));
- if (!MOD_RESULT.check((chan->GetUserCounter() < atol(limit.c_str()))))
- {
- user->WriteNumeric(ERR_CHANNELISFULL, "%s :Cannot join channel (Channel is full)", chan->name.c_str());
- return NULL;
- }
- }
-
if (chan->IsBanned(user))
{
- user->WriteNumeric(ERR_BANNEDFROMCHAN, "%s :Cannot join channel (You're banned)", chan->name.c_str());
+ user->WriteNumeric(ERR_BANNEDFROMCHAN, chan->name, "Cannot join channel (You're banned)");
return NULL;
}
}
CUList except_list;
FOREACH_MOD(OnUserJoin, (memb, bursting, created_by_local, except_list));
- this->WriteAllExcept(user, false, 0, except_list, "JOIN :%s", this->name.c_str());
-
- /* Theyre not the first ones in here, make sure everyone else sees the modes we gave the user */
- if ((GetUserCounter() > 1) && (!memb->modes.empty()))
- {
- std::string ms = memb->modes;
- for(unsigned int i=0; i < memb->modes.length(); i++)
- ms.append(" ").append(user->nick);
-
- except_list.insert(user);
- this->WriteAllExcept(user, !ServerInstance->Config->CycleHostsFromUser, 0, except_list, "MODE %s +%s", this->name.c_str(), ms.c_str());
- }
+ ClientProtocol::Events::Join joinevent(memb);
+ this->Write(joinevent, 0, except_list);
FOREACH_MOD(OnPostJoin, (memb));
return memb;
return (result == MOD_RES_DENY);
ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
+ if (!banlm)
+ return false;
+
const ListModeBase::ModeList* bans = banlm->GetList(this);
if (bans)
{
if (InspIRCd::Match(nickIdent, prefix, NULL))
{
std::string suffix(mask, at + 1);
- if (InspIRCd::Match(user->host, suffix, NULL) ||
- InspIRCd::Match(user->dhost, suffix, NULL) ||
+ if (InspIRCd::Match(user->GetRealHost(), suffix, NULL) ||
+ InspIRCd::Match(user->GetDisplayedHost(), suffix, NULL) ||
InspIRCd::MatchCIDR(user->GetIPString(), suffix, NULL))
return true;
}
return rv;
ListModeBase* banlm = static_cast<ListModeBase*>(*ban);
+ if (!banlm)
+ return MOD_RES_PASSTHRU;
+
const ListModeBase::ModeList* bans = banlm->GetList(this);
if (bans)
{
for (ListModeBase::ModeList::const_iterator it = bans->begin(); it != bans->end(); ++it)
{
- if (CheckBan(user, it->mask))
+ if (it->mask.length() <= 2 || it->mask[0] != type || it->mask[1] != ':')
+ continue;
+
+ if (CheckBan(user, it->mask.substr(2)))
return MOD_RES_DENY;
}
}
CUList except_list;
FOREACH_MOD(OnUserPart, (memb, reason, except_list));
- WriteAllExcept(user, false, 0, except_list, "PART %s%s%s", this->name.c_str(), reason.empty() ? "" : " :", reason.c_str());
+ ClientProtocol::Messages::Part partmsg(memb, reason);
+ Write(ServerInstance->GetRFCEvents().part, partmsg, 0, except_list);
// Remove this channel from the user's chanlist
user->chans.erase(memb);
CUList except_list;
FOREACH_MOD(OnUserKick, (src, memb, reason, except_list));
- User* victim = memb->user;
- WriteAllExcept(src, false, 0, except_list, "KICK %s %s :%s", name.c_str(), victim->nick.c_str(), reason.c_str());
+ ClientProtocol::Messages::Kick kickmsg(src, memb, reason);
+ Write(ServerInstance->GetRFCEvents().kick, kickmsg, 0, except_list);
- victim->chans.erase(memb);
+ memb->user->chans.erase(memb);
this->DelUser(victimiter);
}
-void Channel::WriteChannel(User* user, const char* text, ...)
-{
- std::string textbuffer;
- VAFORMAT(textbuffer, text, text);
- this->WriteChannel(user, textbuffer);
-}
-
-void Channel::WriteChannel(User* user, const std::string &text)
-{
- const std::string message = ":" + user->GetFullHost() + " " + text;
-
- for (MemberMap::iterator i = userlist.begin(); i != userlist.end(); i++)
- {
- if (IS_LOCAL(i->first))
- i->first->Write(message);
- }
-}
-
-void Channel::WriteChannelWithServ(const std::string& ServName, const char* text, ...)
-{
- std::string textbuffer;
- VAFORMAT(textbuffer, text, text);
- this->WriteChannelWithServ(ServName, textbuffer);
-}
-
-void Channel::WriteChannelWithServ(const std::string& ServName, const std::string &text)
-{
- const std::string message = ":" + (ServName.empty() ? ServerInstance->Config->ServerName : ServName) + " " + text;
-
- for (MemberMap::iterator i = userlist.begin(); i != userlist.end(); i++)
- {
- if (IS_LOCAL(i->first))
- i->first->Write(message);
- }
-}
-
-/* write formatted text from a source user to all users on a channel except
- * for the sender (for privmsg etc) */
-void Channel::WriteAllExceptSender(User* user, bool serversource, char status, const char* text, ...)
-{
- std::string textbuffer;
- VAFORMAT(textbuffer, text, text);
- this->WriteAllExceptSender(user, serversource, status, textbuffer);
-}
-
-void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const char* text, ...)
-{
- std::string textbuffer;
- VAFORMAT(textbuffer, text, text);
- textbuffer = ":" + (serversource ? ServerInstance->Config->ServerName : user->GetFullHost()) + " " + textbuffer;
- this->RawWriteAllExcept(user, serversource, status, except_list, textbuffer);
-}
-
-void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &text)
-{
- const std::string message = ":" + (serversource ? ServerInstance->Config->ServerName : user->GetFullHost()) + " " + text;
- this->RawWriteAllExcept(user, serversource, status, except_list, message);
-}
-
-void Channel::RawWriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &out)
+void Channel::Write(ClientProtocol::Event& protoev, char status, const CUList& except_list)
{
unsigned int minrank = 0;
if (status)
}
for (MemberMap::iterator i = userlist.begin(); i != userlist.end(); i++)
{
- if (IS_LOCAL(i->first) && (except_list.find(i->first) == except_list.end()))
+ LocalUser* user = IS_LOCAL(i->first);
+ if ((user) && (!except_list.count(user)))
{
/* User doesn't have the status we're after */
if (minrank && i->second->getRank() < minrank)
continue;
- i->first->Write(out);
+ user->Send(protoev);
}
}
}
-void Channel::WriteAllExceptSender(User* user, bool serversource, char status, const std::string& text)
-{
- CUList except_list;
- except_list.insert(user);
- this->WriteAllExcept(user, serversource, status, except_list, std::string(text));
-}
-
const char* Channel::ChanModes(bool showkey)
{
static std::string scratch;
return scratch.c_str();
}
+void Channel::WriteNotice(const std::string& text)
+{
+ ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, this, text, MSG_NOTICE);
+ Write(ServerInstance->GetRFCEvents().privmsg, privmsg);
+}
+
/* returns the status character for a given user on a channel, e.g. @ for op,
* % for halfop etc. If the user has several modes set, the highest mode
* the user has must be returned.
return rv;
}
-const char* Membership::GetAllPrefixChars() const
+std::string Membership::GetAllPrefixChars() const
{
- static char prefix[64];
- int ctr = 0;
-
+ std::string ret;
for (std::string::const_iterator i = modes.begin(); i != modes.end(); ++i)
{
PrefixMode* mh = ServerInstance->Modes->FindPrefixMode(*i);
if (mh && mh->GetPrefix())
- prefix[ctr++] = mh->GetPrefix();
+ ret.push_back(mh->GetPrefix());
}
- prefix[ctr] = 0;
- return prefix;
+ return ret;
}
unsigned int Channel::GetPrefixValue(User* user)
modes.push_back(prefix);
return adding;
}
+
+
+void Membership::WriteNotice(const std::string& text) const
+{
+ LocalUser* const localuser = IS_LOCAL(user);
+ if (!localuser)
+ return;
+
+ ClientProtocol::Messages::Privmsg privmsg(ClientProtocol::Messages::Privmsg::nocopy, ServerInstance->FakeClient, this->chan, text, MSG_NOTICE);
+ localuser->Send(ServerInstance->GetRFCEvents().privmsg, privmsg);
+}