Beispiel #1
0
void Channel::SetDefaultModes()
{
	ServerInstance->Logs->Log("CHANNELS", LOG_DEBUG, "SetDefaultModes %s",
		ServerInstance->Config->DefaultModes.c_str());
	irc::spacesepstream list(ServerInstance->Config->DefaultModes);
	std::string modeseq;
	std::string parameter;

	list.GetToken(modeseq);

	for (std::string::iterator n = modeseq.begin(); n != modeseq.end(); ++n)
	{
		ModeHandler* mode = ServerInstance->Modes->FindMode(*n, MODETYPE_CHANNEL);
		if (mode)
		{
			if (mode->IsPrefixMode())
				continue;

			if (mode->NeedsParam(true))
			{
				list.GetToken(parameter);
				// If the parameter begins with a ':' then it's invalid
				if (parameter.c_str()[0] == ':')
					continue;
			}
			else
				parameter.clear();

			if ((mode->NeedsParam(true)) && (parameter.empty()))
				continue;

			mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, parameter, true);
		}
	}
}
Beispiel #2
0
	CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* src)
	{
		Channel* const chan = ServerInstance->FindChan(parameters[0]);
		if (!chan)
		{
			src->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
			return CMD_FAILURE;
		}

		if (parameters.size() == 1)
		{
			DisplayList(src, chan);
			return CMD_SUCCESS;
		}
		unsigned int i = 1;
		Modes::ChangeList modes;
		while (i < parameters.size())
		{
			std::string prop = parameters[i++];
			if (prop.empty())
				continue;
			bool plus = prop[0] != '-';
			if (prop[0] == '+' || prop[0] == '-')
				prop.erase(prop.begin());

			ModeHandler* mh = ServerInstance->Modes->FindMode(prop, MODETYPE_CHANNEL);
			if (mh)
			{
				if (mh->NeedsParam(plus))
				{
					if (i != parameters.size())
						modes.push(mh, plus, parameters[i++]);
				}
				else
					modes.push(mh, plus);
			}
		}
		ServerInstance->Modes->ProcessSingle(src, chan, NULL, modes, ModeParser::MODE_CHECKACCESS);
		return CMD_SUCCESS;
	}
Beispiel #3
0
static void DisplayList(LocalUser* user, Channel* channel)
{
	Numeric::ParamBuilder<1> numeric(user, 961);
	numeric.AddStatic(channel->name);

	const ModeParser::ModeHandlerMap& mhs = ServerInstance->Modes->GetModes(MODETYPE_CHANNEL);
	for (ModeParser::ModeHandlerMap::const_iterator i = mhs.begin(); i != mhs.end(); ++i)
	{
		ModeHandler* mh = i->second;
		if (!channel->IsModeSet(mh))
			continue;
		numeric.Add("+" + mh->name);
		if (mh->NeedsParam(true))
		{
			if ((mh->name == "key") && (!channel->HasUser(user)) && (!user->HasPrivPermission("channels/auspex")))
				numeric.Add("<key>");
			else
				numeric.Add(channel->GetModeParameter(mh));
		}
	}
	numeric.Flush();
	user->WriteNumeric(960, channel->name, "End of mode list");
}
Beispiel #4
0
CmdResult CommandUID::HandleServer(TreeServer* remoteserver, std::vector<std::string>& params)
{
	/**
	 *      0    1    2    3    4    5        6        7     8        9       (n-1)
	 * UID uuid age nick host dhost ident ip.string signon +modes (modepara) :gecos
	 */
	time_t age_t = ServerCommand::ExtractTS(params[1]);
	time_t signon = ServerCommand::ExtractTS(params[7]);
	std::string empty;
	const std::string& modestr = params[8];

	// Check if the length of the uuid is correct and confirm the sid portion of the uuid matches the sid of the server introducing the user
	if (params[0].length() != UIDGenerator::UUID_LENGTH || params[0].compare(0, 3, remoteserver->GetID()))
		throw ProtocolException("Bogus UUID");
	// Sanity check on mode string: must begin with '+'
	if (modestr[0] != '+')
		throw ProtocolException("Invalid mode string");

	// See if there is a nick collision
	User* collideswith = ServerInstance->FindNickOnly(params[2]);
	if ((collideswith) && (collideswith->registered != REG_ALL))
	{
		// User that the incoming user is colliding with is not fully registered, we force nick change the
		// unregistered user to their uuid and tell them what happened
		collideswith->WriteFrom(collideswith, "NICK %s", collideswith->uuid.c_str());
		collideswith->WriteNumeric(ERR_NICKNAMEINUSE, collideswith->nick, "Nickname overruled.");

		// Clear the bit before calling User::ChangeNick() to make it NOT run the OnUserPostNick() hook
		collideswith->registered &= ~REG_NICK;
		collideswith->ChangeNick(collideswith->uuid);
	}
	else if (collideswith)
	{
		// The user on this side is registered, handle the collision
		bool they_change = Utils->DoCollision(collideswith, remoteserver, age_t, params[5], params[6], params[0], "UID");
		if (they_change)
		{
			// The client being introduced needs to change nick to uuid, change the nick in the message before
			// processing/forwarding it. Also change the nick TS to CommandSave::SavedTimestamp.
			age_t = CommandSave::SavedTimestamp;
			params[1] = ConvToStr(CommandSave::SavedTimestamp);
			params[2] = params[0];
		}
	}

	/* For remote users, we pass the UUID they sent to the constructor.
	 * If the UUID already exists User::User() throws an exception which causes this connection to be closed.
	 */
	RemoteUser* _new = new SpanningTree::RemoteUser(params[0], remoteserver);
	ServerInstance->Users->clientlist[params[2]] = _new;
	_new->nick = params[2];
	_new->host = params[3];
	_new->dhost = params[4];
	_new->ident = params[5];
	_new->fullname = params.back();
	_new->registered = REG_ALL;
	_new->signon = signon;
	_new->age = age_t;

	unsigned int paramptr = 9;

	for (std::string::const_iterator v = modestr.begin(); v != modestr.end(); ++v)
	{
		// Accept more '+' chars, for now
		if (*v == '+')
			continue;

		/* For each mode thats set, find the mode handler and set it on the new user */
		ModeHandler* mh = ServerInstance->Modes->FindMode(*v, MODETYPE_USER);
		if (!mh)
			throw ProtocolException("Unrecognised mode '" + std::string(1, *v) + "'");

		if (mh->NeedsParam(true))
		{
			if (paramptr >= params.size() - 1)
				throw ProtocolException("Out of parameters while processing modes");
			std::string mp = params[paramptr++];
			/* IMPORTANT NOTE:
			 * All modes are assumed to succeed here as they are being set by a remote server.
			 * Modes CANNOT FAIL here. If they DO fail, then the failure is ignored. This is important
			 * to note as all but one modules currently cannot ever fail in this situation, except for
			 * m_servprotect which specifically works this way to prevent the mode being set ANYWHERE
			 * but here, at client introduction. You may safely assume this behaviour is standard and
			 * will not change in future versions if you want to make use of this protective behaviour
			 * yourself.
			 */
			mh->OnModeChange(_new, _new, NULL, mp, true);
		}
		else
			mh->OnModeChange(_new, _new, NULL, empty, true);
		_new->SetMode(mh, true);
	}

	_new->SetClientIP(params[6].c_str());

	ServerInstance->Users->AddClone(_new);
	remoteserver->UserCount++;

	bool dosend = true;

	if ((Utils->quiet_bursts && remoteserver->IsBehindBursting()) || _new->server->IsSilentULine())
		dosend = false;

	if (dosend)
		ServerInstance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s (%s) [%s]", remoteserver->GetName().c_str(), _new->GetFullRealHost().c_str(), _new->GetIPString().c_str(), _new->fullname.c_str());

	FOREACH_MOD(OnPostConnect, (_new));

	return CMD_SUCCESS;
}