Exemple #1
0
	/*
	 * <@po||ux> DukeP: RFC 2813, 4.2.1: the JOIN command on server-server links
	 * separates the modes ("o") with ASCII 7, not space. And you can't see ASCII 7.
	 *
	 * if a user joins a new channel, the ircd sends <channelname>\7<umode>
	 */
	void Run(MessageSource &source, const std::vector<Anope::string> &params) override
	{
		User *user = source.GetUser();
		size_t pos = params[0].find('\7');
		Anope::string channel, modes;

		if (pos != Anope::string::npos)
		{
			channel = params[0].substr(0, pos);
			modes = '+' + params[0].substr(pos+1, params[0].length()) + " " + user->nick;
		}
		else
		{
			channel = params[0];
		}

		std::vector<Anope::string> new_params;
		new_params.push_back(channel);

		Message::Join::Run(source, new_params);

		if (!modes.empty())
		{
			Channel *c = Channel::Find(channel);
			if (c)
				c->SetModesInternal(source, modes);
		}
	}
Exemple #2
0
	/*
	 * CHANINFO is used by servers to inform each other about a channel: its
	 * modes, channel key, user limits and its topic. The parameter combination
	 * <key> and <limit> is optional, as well as the <topic> parameter, so that
	 * there are three possible forms of this command:
	 *
	 * CHANINFO <chan> +<modes>
	 * CHANINFO <chan> +<modes> :<topic>
	 * CHANINFO <chan> +<modes> <key> <limit> :<topic>
	 *
	 * The parameter <key> must be ignored if a channel has no key (the parameter
	 * <modes> doesn't list the "k" channel mode). In this case <key> should
	 * contain "*" because the parameter <key> is required by the CHANINFO syntax
	 * and therefore can't be omitted. The parameter <limit> must be ignored when
	 * a channel has no user limit (the parameter <modes> doesn't list the "l"
	 * channel mode). In this case <limit> should be "0".
	 */
	void Run(MessageSource &source, const std::vector<Anope::string> &params) override
	{
		bool created;
		Channel *c = Channel::FindOrCreate(params[0], created);

		Anope::string modes = params[1];

		if (params.size() == 3)
		{
			c->ChangeTopicInternal(NULL, source.GetName(), params[2], Anope::CurTime);
		}
		else if (params.size() == 5)
		{
			for (size_t i = 0, end = params[1].length(); i < end; ++i)
			{
				switch(params[1][i])
				{
					case 'k':
						modes += " " + params[2];
						continue;
					case 'l':
						modes += " " + params[3];
						continue;
				}
			}
			c->ChangeTopicInternal(NULL, source.GetName(), params[4], Anope::CurTime);
		}

		c->SetModesInternal(source, modes);
	}
Exemple #3
0
void bahamut::Mode::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
	if (params.size() > 2 && IRCD->IsChannelValid(params[0]))
	{
		Channel *c = Channel::Find(params[0]);
		time_t ts = 0;

		try
		{
			ts = convertTo<time_t>(params[1]);
		}
		catch (const ConvertException &) { }

		Anope::string modes = params[2];
		for (unsigned int i = 3; i < params.size(); ++i)
			modes += " " + params[i];

		if (c)
			c->SetModesInternal(source, modes, ts);
	}
	else
	{
		User *u = User::Find(params[0]);
		if (u)
			u->SetModesInternal(source, "%s", params[1].c_str());
	}
}
Exemple #4
0
void hybrid::TMode::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
	time_t ts = 0;

	try
	{
		ts = convertTo<time_t>(params[0]);
	}
	catch (const ConvertException &) { }

	Channel *c = Channel::Find(params[1]);
	Anope::string modes = params[2];

	for (unsigned i = 3; i < params.size(); ++i)
		modes += " " + params[i];

	if (c)
		c->SetModesInternal(source, modes, ts);
}
Exemple #5
0
void Message::Mode::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
	Anope::string buf;
	for (unsigned i = 1; i < params.size(); ++i)
		buf += " " + params[i];

	if (IRCD->IsChannelValid(params[0]))
	{
		Channel *c = Channel::Find(params[0]);

		if (c)
			c->SetModesInternal(source, buf.substr(1), 0);
	}
	else
	{
		User *u = User::Find(params[0]);

		if (u)
			u->SetModesInternal(source, "%s", buf.substr(1).c_str());
	}
}
Exemple #6
0
	void Run(MessageSource &source, const std::vector<Anope::string> &params) override
	{
		Anope::string modes = params[1];

		for (size_t i = 2; i < params.size(); ++i)
			modes += " " + params[i];

		if (IRCD->IsChannelValid(params[0]))
		{
			Channel *c = Channel::Find(params[0]);

			if (c)
				c->SetModesInternal(source, modes);
		}
		else
		{
			User *u = User::Find(params[0]);

			if (u)
				u->SetModesInternal(source, "%s", params[1].c_str());
		}
	}
Exemple #7
0
	bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> &params)
	{
		Channel *c = findchan(params[1]);
		time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0;
		bool keep_their_modes = true;

		if (!c)
		{
			c = new Channel(params[1], ts);
			c->SetFlag(CH_SYNCING);
		}
		/* Our creation time is newer than what the server gave us */
		else if (c->creation_time > ts)
		{
			c->creation_time = ts;
			c->Reset();
		}
		/* Their TS is newer than ours, our modes > theirs, unset their modes if need be */
		else if (ts > c->creation_time)
			keep_their_modes = false;

		/* If we need to keep their modes, and this SJOIN string contains modes */
		if (keep_their_modes && params.size() >= 4)
		{
			/* Set the modes internally */
			Anope::string modes;
			for (unsigned i = 2; i < params.size(); ++i)
				modes += " " + params[i];
			if (!modes.empty())
				modes.erase(modes.begin());
			c->SetModesInternal(NULL, modes);
		}

		/* For some reason, bahamut will send a SJOIN from the user joining a channel
		 * if the channel already existed
		 */
		if (!c->HasFlag(CH_SYNCING) && params.size() == 2)
		{
			User *u = finduser(source);
			if (!u)
				Log(LOG_DEBUG) << "SJOIN for nonexistant user " << source << " on " << c->name;
			else
			{
				EventReturn MOD_RESULT;
				FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));

				/* Add the user to the channel */
				c->JoinUser(u);

				/* Now set whatever modes this user is allowed to have on the channel */
				chan_set_correct_modes(u, c, 1);

				/* Check to see if modules want the user to join, if they do
				 * check to see if they are allowed to join (CheckKick will kick/ban them)
				 * Don't trigger OnJoinChannel event then as the user will be destroyed
				 */
				if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u)))
				{
					FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
				}
			}
		}
		else
		{
			spacesepstream sep(params[params.size() - 1]);
			Anope::string buf;
			while (sep.GetToken(buf))
			{
				std::list<ChannelMode *> Status;
				char ch;

				/* Get prefixes from the nick */
				while ((ch = ModeManager::GetStatusChar(buf[0])))
				{
					buf.erase(buf.begin());
					ChannelMode *cm = ModeManager::FindChannelModeByChar(ch);
					if (!cm)
					{
						Log() << "Received unknown mode prefix " << cm << " in SJOIN string";
						continue;
					}

					if (keep_their_modes)
						Status.push_back(cm);
				}

				User *u = finduser(buf);
				if (!u)
				{
					Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name;
					continue;
				}

				EventReturn MOD_RESULT;
				FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));

				/* Add the user to the channel */
				c->JoinUser(u);

				/* Update their status internally on the channel
				 * This will enforce secureops etc on the user
				 */
				for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it)
					c->SetModeInternal(*it, buf);

				/* Now set whatever modes this user is allowed to have on the channel */
				chan_set_correct_modes(u, c, 1);

				/* Check to see if modules want the user to join, if they do
				 * check to see if they are allowed to join (CheckKick will kick/ban them)
				 * Don't trigger OnJoinChannel event then as the user will be destroyed
				 */
				if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u))
					continue;

				FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
			}
		}

		/* Channel is done syncing */
		if (c->HasFlag(CH_SYNCING))
		{
			/* Unset the syncing flag */
			c->UnsetFlag(CH_SYNCING);
			c->Sync();
		}

		return true;
	}
Exemple #8
0
void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, const Anope::string &modes, const std::list<SJoinUser> &users)
{
	bool created;
	Channel *c = Channel::FindOrCreate(chan, created, ts ? ts : Anope::CurTime);
	bool keep_their_modes = true;

	if (created)
		c->syncing = true;
	/* Some IRCds do not include a TS */
	else if (!ts)
		;
	/* Our creation time is newer than what the server gave us, so reset the channel to the older time */
	else if (c->creation_time > ts)
	{
		c->creation_time = ts;
		c->Reset();
	}
	/* Their TS is newer, don't accept any modes from them */
	else if (ts > c->creation_time)
		keep_their_modes = false;

	/* Update the modes for the channel */
	if (keep_their_modes && !modes.empty())
		/* If we are syncing, mlock is checked later in Channel::Sync. It is important to not check it here
		 * so that Channel::SetCorrectModes can correctly detect the presence of channel mode +r.
		 */
		c->SetModesInternal(source, modes, ts, !c->syncing);

	for (std::list<SJoinUser>::const_iterator it = users.begin(), it_end = users.end(); it != it_end; ++it)
	{
		const ChannelStatus &status = it->first;
		User *u = it->second;
		keep_their_modes = ts <= c->creation_time; // OnJoinChannel can call modules which can modify this channel's ts

		if (c->FindUser(u))
			continue;

		/* Add the user to the channel */
		c->JoinUser(u, keep_their_modes ? &status : NULL);

		/* Check if the user is allowed to join */
		if (c->CheckKick(u))
			continue;

		/* Set whatever modes the user should have, and remove any that
		 * they aren't allowed to have (secureops etc).
		 */
		c->SetCorrectModes(u, true);

		EventManager::Get()->Dispatch(&Event::JoinChannel::OnJoinChannel, u, c);
	}

	/* Channel is done syncing */
	if (c->syncing)
	{
		/* Sync the channel (mode lock, topic, etc) */
		/* the channel is synced when the netmerge is complete */
		Server *src = source.GetServer() ? source.GetServer() : Me;
		if (src && src->IsSynced())
		{
			c->Sync();

			if (c->CheckDelete())
				delete c;
		}
	}
}