Ejemplo n.º 1
0
	void init() override
	{
		ConfigTagList tags = ServerInstance->Config->ConfTags("customprefix");
		for (ConfigIter iter = tags.first; iter != tags.second; ++iter)
		{
			ConfigTag* tag = iter->second;

			const std::string name = tag->getString("name");
			if (name.empty())
				throw ModuleException("<customprefix:name> must be specified at " + tag->getTagLocation());

			if (tag->getBool("change"))
			{
				ModeHandler* mh = ServerInstance->Modes.FindMode(name, MODETYPE_CHANNEL);
				if (!mh)
					throw ModuleException("<customprefix:change> specified for a non-existent mode at " + tag->getTagLocation());

				PrefixMode* pm = mh->IsPrefixMode();
				if (!pm)
					throw ModuleException("<customprefix:change> specified for a non-prefix mode at " + tag->getTagLocation());

				unsigned long rank = tag->getUInt("rank", pm->GetPrefixRank(), 0, UINT_MAX);
				unsigned long setrank = tag->getUInt("ranktoset", pm->GetLevelRequired(true), rank, UINT_MAX);
				unsigned long unsetrank = tag->getUInt("ranktounset", pm->GetLevelRequired(false), setrank, UINT_MAX);
				bool depriv = tag->getBool("depriv", pm->CanSelfRemove());
				pm->Update(rank, setrank, unsetrank, depriv);

				ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Changed the %s prefix: depriv=%u rank=%u ranktoset=%u ranktounset=%u",
					pm->name.c_str(), pm->CanSelfRemove(), pm->GetPrefixRank(), pm->GetLevelRequired(true), pm->GetLevelRequired(false));
				continue;
			}

			const std::string letter = tag->getString("letter");
			if (letter.length() != 1)
				throw ModuleException("<customprefix:letter> must be set to a mode character at " + tag->getTagLocation());

			const std::string prefix = tag->getString("prefix");
			if (prefix.length() != 1)
				throw ModuleException("<customprefix:prefix> must be set to a mode prefix at " + tag->getTagLocation());

			try
			{
				CustomPrefixMode* mh = new CustomPrefixMode(this, name, letter[0], prefix[0], tag);
				modes.push_back(mh);
				ServerInstance->Modules.AddService(*mh);
			}
			catch (ModuleException& e)
			{
				throw ModuleException(e.GetReason() + " (while creating mode from " + tag->getTagLocation() + ")");
			}
		}
	}
Ejemplo n.º 2
0
	ModResult Call(User* user, Channel* chan, const std::string& restriction)
	{
		unsigned int mypfx = chan->GetPrefixValue(user);
		std::string minmode;

		ListModeBase::ModeList* list = ec.GetList(chan);

		if (list)
		{
			for (ListModeBase::ModeList::iterator i = list->begin(); i != list->end(); ++i)
			{
				std::string::size_type pos = (*i).mask.find(':');
				if (pos == std::string::npos)
					continue;
				if ((*i).mask.substr(0,pos) == restriction)
					minmode = (*i).mask.substr(pos + 1);
			}
		}

		PrefixMode* mh = FindMode(minmode);
		if (mh && mypfx >= mh->GetPrefixRank())
			return MOD_RES_ALLOW;
		if (mh || minmode == "*")
			return MOD_RES_DENY;

		return ServerInstance->HandleOnCheckExemption.Call(user, chan, restriction);
	}
Ejemplo n.º 3
0
/* returns a list of DIRECT servernames for a specific channel */
void SpanningTreeUtilities::GetListOfServersForChannel(Channel* c, TreeSocketSet& list, char status, const CUList& exempt_list)
{
	unsigned int minrank = 0;
	if (status)
	{
		PrefixMode* mh = ServerInstance->Modes->FindPrefix(status);
		if (mh)
			minrank = mh->GetPrefixRank();
	}

	const UserMembList *ulist = c->GetUsers();

	for (UserMembCIter i = ulist->begin(); i != ulist->end(); i++)
	{
		if (IS_LOCAL(i->first))
			continue;

		if (minrank && i->second->getRank() < minrank)
			continue;

		if (exempt_list.find(i->first) == exempt_list.end())
		{
			TreeServer* best = TreeServer::Get(i->first);
			list.insert(best->GetSocket());
		}
	}
	return;
}
Ejemplo n.º 4
0
std::string ModeParser::BuildPrefixes(bool lettersAndModes)
{
	std::string mletters;
	std::string mprefixes;
	std::map<int,std::pair<char,char> > prefixes;

	const PrefixModeList& list = GetPrefixModes();
	for (PrefixModeList::const_iterator i = list.begin(); i != list.end(); ++i)
	{
		PrefixMode* pm = *i;
		if (pm->GetPrefix())
			prefixes[pm->GetPrefixRank()] = std::make_pair(pm->GetPrefix(), pm->GetModeChar());
	}

	for(std::map<int,std::pair<char,char> >::reverse_iterator n = prefixes.rbegin(); n != prefixes.rend(); n++)
	{
		mletters = mletters + n->second.first;
		mprefixes = mprefixes + n->second.second;
	}

	return lettersAndModes ? "(" + mprefixes + ")" + mletters : mletters;
}
Ejemplo n.º 5
0
ModResult OnCheckExemptionHandler::Call(User* user, Channel* chan, const std::string& restriction)
{
	unsigned int mypfx = chan->GetPrefixValue(user);
	char minmode = 0;
	std::string current;

	irc::spacesepstream defaultstream(ServerInstance->Config->ConfValue("options")->getString("exemptchanops"));

	while (defaultstream.GetToken(current))
	{
		std::string::size_type pos = current.find(':');
		if (pos == std::string::npos)
			continue;
		if (!current.compare(0, pos, restriction))
			minmode = current[pos+1];
	}

	PrefixMode* mh = ServerInstance->Modes->FindPrefixMode(minmode);
	if (mh && mypfx >= mh->GetPrefixRank())
		return MOD_RES_ALLOW;
	if (mh || minmode == '*')
		return MOD_RES_DENY;
	return MOD_RES_PASSTHRU;
}
Ejemplo n.º 6
0
	CmdResult Handle(User* user, const Params& parameters) override
	{
		ModeHandler* mh;
		Channel* chan = ServerInstance->FindChan(parameters[0]);
		char modeletter = parameters[1][0];

		if (chan == NULL)
		{
			user->WriteNotice("The channel " + parameters[0] + " does not exist.");
			return CMD_FAILURE;
		}

		mh = ServerInstance->Modes.FindMode(modeletter, MODETYPE_CHANNEL);
		if (mh == NULL || parameters[1].size() > 1)
		{
			user->WriteNotice(parameters[1] + " is not a valid channel mode.");
			return CMD_FAILURE;
		}

		if (chan->GetPrefixValue(user) < mh->GetLevelRequired(false))
		{
			user->WriteNotice("You do not have access to unset " + ConvToStr(modeletter) + " on " +  chan->name + ".");
			return CMD_FAILURE;
		}

		std::string pattern = parameters.size() > 2 ? parameters[2] : "*";
		PrefixMode* pm;
		ListModeBase* lm;
		ListModeBase::ModeList* ml;
		Modes::ChangeList changelist;

		if ((pm = mh->IsPrefixMode()))
		{
			// As user prefix modes don't have a GetList() method, let's iterate through the channel's users.
			const Channel::MemberMap& users = chan->GetUsers();
			for (Channel::MemberMap::const_iterator it = users.begin(); it != users.end(); ++it)
			{
				if (!InspIRCd::Match(it->first->nick, pattern))
					continue;
				if (it->second->HasMode(pm) && !((it->first == user) && (pm->GetPrefixRank() > VOICE_VALUE)))
					changelist.push_remove(mh, it->first->nick);
			}
		}
		else if ((lm = mh->IsListModeBase()) && ((ml = lm->GetList(chan)) != NULL))
		{
			for (ListModeBase::ModeList::iterator it = ml->begin(); it != ml->end(); ++it)
			{
				if (!InspIRCd::Match(it->mask, pattern))
					continue;
				changelist.push_remove(mh, it->mask);
			}
		}
		else
		{
			if (chan->IsModeSet(mh))
				changelist.push_remove(mh);
		}

		ServerInstance->Modes.Process(user, chan, NULL, changelist);
		return CMD_SUCCESS;
	}
Ejemplo n.º 7
0
ModeAction ModeParser::TryMode(User* user, User* targetuser, Channel* chan, bool adding, const unsigned char modechar,
		std::string &parameter, bool SkipACL)
{
	ModeType type = chan ? MODETYPE_CHANNEL : MODETYPE_USER;

	ModeHandler *mh = FindMode(modechar, type);
	int pcnt = mh->GetNumParams(adding);

	// crop mode parameter size to 250 characters
	if (parameter.length() > 250 && adding)
		parameter = parameter.substr(0, 250);

	ModResult MOD_RESULT;
	FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, modechar, parameter, adding, pcnt));

	if (IS_LOCAL(user) && (MOD_RESULT == MOD_RES_DENY))
		return MODEACTION_DENY;

	if (chan && !SkipACL && (MOD_RESULT != MOD_RES_ALLOW))
	{
		MOD_RESULT = mh->AccessCheck(user, chan, parameter, adding);

		if (MOD_RESULT == MOD_RES_DENY)
			return MODEACTION_DENY;
		if (MOD_RESULT == MOD_RES_PASSTHRU)
		{
			unsigned int neededrank = mh->GetLevelRequired();
			/* Compare our rank on the channel against the rank of the required prefix,
			 * allow if >= ours. Because mIRC and xchat throw a tizz if the modes shown
			 * in NAMES(X) are not in rank order, we know the most powerful mode is listed
			 * first, so we don't need to iterate, we just look up the first instead.
			 */
			unsigned int ourrank = chan->GetPrefixValue(user);
			if (ourrank < neededrank)
			{
				PrefixMode* neededmh = NULL;
				for(char c='A'; c <= 'z'; c++)
				{
					PrefixMode* privmh = FindPrefixMode(c);
					if (privmh && privmh->GetPrefixRank() >= neededrank)
					{
						// this mode is sufficient to allow this action
						if (!neededmh || privmh->GetPrefixRank() < neededmh->GetPrefixRank())
							neededmh = privmh;
					}
				}
				if (neededmh)
					user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must have channel %s access or above to %sset channel mode %c",
						user->nick.c_str(), chan->name.c_str(), neededmh->name.c_str(), adding ? "" : "un", modechar);
				else
					user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You cannot %sset channel mode %c",
						user->nick.c_str(), chan->name.c_str(), adding ? "" : "un", modechar);
				return MODEACTION_DENY;
			}
		}
	}

	// Ask mode watchers whether this mode change is OK
	std::pair<ModeWatchIter, ModeWatchIter> itpair = modewatchermap.equal_range(mh->name);
	for (ModeWatchIter i = itpair.first; i != itpair.second; ++i)
	{
		ModeWatcher* mw = i->second;
		if (mw->GetModeType() == type)
		{
			if (!mw->BeforeMode(user, targetuser, chan, parameter, adding))
				return MODEACTION_DENY;

			// A module whacked the parameter completely, and there was one. Abort.
			if (pcnt && parameter.empty())
				return MODEACTION_DENY;
		}
	}

	if (IS_LOCAL(user) && !user->IsOper())
	{
		char* disabled = (type == MODETYPE_CHANNEL) ? ServerInstance->Config->DisabledCModes : ServerInstance->Config->DisabledUModes;
		if (disabled[modechar - 'A'])
		{
			user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - %s mode %c has been locked by the administrator",
				user->nick.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
			return MODEACTION_DENY;
		}
	}

	if (adding && IS_LOCAL(user) && mh->NeedsOper() && !user->HasModePermission(modechar, type))
	{
		/* It's an oper only mode, and they don't have access to it. */
		if (user->IsOper())
		{
			user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Oper type %s does not have access to set %s mode %c",
					user->nick.c_str(), user->oper->name.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
		}
		else
		{
			user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Permission Denied - Only operators may set %s mode %c",
					user->nick.c_str(), type == MODETYPE_CHANNEL ? "channel" : "user", modechar);
		}
		return MODEACTION_DENY;
	}

	/* Call the handler for the mode */
	ModeAction ma = mh->OnModeChange(user, targetuser, chan, parameter, adding);

	if (pcnt && parameter.empty())
		return MODEACTION_DENY;

	if (ma != MODEACTION_ALLOW)
		return ma;

	if ((!mh->IsListMode()) && (mh->GetNumParams(true)) && (chan))
		chan->SetModeParam(mh, (adding ? parameter : ""));

	itpair = modewatchermap.equal_range(mh->name);
	for (ModeWatchIter i = itpair.first; i != itpair.second; ++i)
	{
		ModeWatcher* mw = i->second;
		if (mw->GetModeType() == type)
			mw->AfterMode(user, targetuser, chan, parameter, adding);
	}

	return MODEACTION_ALLOW;
}
Ejemplo n.º 8
0
	CmdResult Handle(const std::vector<std::string> &parameters, User *user)
	{
		ModeHandler* mh;
		Channel* chan = ServerInstance->FindChan(parameters[0]);
		char modeletter = parameters[1][0];

		if (chan == NULL)
		{
			user->WriteNotice("The channel " + parameters[0] + " does not exist.");
			return CMD_FAILURE;
		}

		mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
		if (mh == NULL || parameters[1].size() > 1)
		{
			user->WriteNotice(parameters[1] + " is not a valid channel mode.");
			return CMD_FAILURE;
		}

		if (chan->GetPrefixValue(user) < mh->GetLevelRequired())
		{
			user->WriteNotice("You do not have access to unset " + ConvToStr(modeletter) + " on " +  chan->name + ".");
			return CMD_FAILURE;
		}

		std::string pattern = parameters.size() > 2 ? parameters[2] : "*";
		PrefixMode* pm;
		ListModeBase* lm;
		ListModeBase::ModeList* ml;
		irc::modestacker modestack(false);

		if ((pm = mh->IsPrefixMode()))
		{
			// As user prefix modes don't have a GetList() method, let's iterate through the channel's users.
			const Channel::MemberMap& users = chan->GetUsers();
			for (Channel::MemberMap::const_iterator it = users.begin(); it != users.end(); ++it)
			{
				if (!InspIRCd::Match(it->first->nick, pattern))
					continue;
				if (it->second->hasMode(modeletter) && !((it->first == user) && (pm->GetPrefixRank() > VOICE_VALUE)))
					modestack.Push(modeletter, it->first->nick);
			}
		}
		else if ((lm = mh->IsListModeBase()) && ((ml = lm->GetList(chan)) != NULL))
		{
			for (ListModeBase::ModeList::iterator it = ml->begin(); it != ml->end(); ++it)
			{
				if (!InspIRCd::Match(it->mask, pattern))
					continue;
				modestack.Push(modeletter, it->mask);
			}
		}
		else
		{
			if (chan->IsModeSet(mh))
				modestack.Push(modeletter);
		}

		parameterlist stackresult;
		stackresult.push_back(chan->name);
		while (modestack.GetStackedLine(stackresult))
		{
			ServerInstance->Modes->Process(stackresult, user);
			stackresult.erase(stackresult.begin() + 1, stackresult.end());
		}

		return CMD_SUCCESS;
	}