Пример #1
0
	CmdResult Handle (const std::vector<std::string>& parameters, User *user)
	{
		
		User* target = ServerInstance->FindNick(parameters[0]);
		Channel* channel = ServerInstance->FindChan(parameters[1]);
		std::string message = parameters[2];
		
		if ((target) && (target->registered == REG_ALL) && (channel))
		{
			if (ServerInstance->ULine(target->server))
			{
				user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an SA command on a u-lined client", user->nick.c_str());
				return CMD_FAILURE;
			}
		
			if(!channel->HasUser(target))
			{
				user->WriteServ("NOTICE %s :*** %s is not on the channel %s", user->nick.c_str(), target->nick.c_str(), channel->name.c_str());
				return CMD_FAILURE;
			}
				
			channel->WriteChannel(target, "PRIVMSG %s :%s", channel->name.c_str(), message.c_str());
			ServerInstance->SNO->WriteGlobalSno('a', user->nick + " used SASAY to make " + target->nick.c_str() + " say in " + channel->name.c_str() + ": \"" + message + "\"");
			
			return CMD_SUCCESS;
		}
		else
		{
			user->WriteServ("NOTICE %s :*** Invalid nickname or channel", user->nick.c_str());
		}
		return CMD_FAILURE;
	}
Пример #2
0
/** Handle /NAMES
 */
CmdResult CommandNames::Handle (const std::vector<std::string>& parameters, User *user)
{
	Channel* c;

	if (!parameters.size())
	{
		user->WriteNumeric(366, "%s * :End of /NAMES list.",user->nick.c_str());
		return CMD_SUCCESS;
	}

	if (CommandParser::LoopCall(user, this, parameters, 0))
		return CMD_SUCCESS;

	c = ServerInstance->FindChan(parameters[0]);
	if (c)
	{
		if ((c->IsModeSet(secretmode)) && (!c->HasUser(user)))
		{
		      user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), c->name.c_str());
		      return CMD_FAILURE;
		}
		c->UserList(user);
	}
	else
	{
		user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
	}

	return CMD_SUCCESS;
}
Пример #3
0
	CmdResult Handle (const std::vector<std::string>& parameters, User *user)
	{
		User* dest = ServerInstance->FindNick(parameters[0]);
		if (dest)
		{
			if (ServerInstance->ULine(dest->server))
			{
				user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an SA command on a u-lined client",user->nick.c_str());
				return CMD_FAILURE;
			}
			if (IS_LOCAL(user) && !ServerInstance->IsChannel(parameters[1].c_str(), ServerInstance->Config->Limits.ChanMax))
			{
				/* we didn't need to check this for each character ;) */
				user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Invalid characters in channel name or name too long");
				return CMD_FAILURE;
			}

			/* For local users, we send the JoinUser which may create a channel and set its TS.
			 * For non-local users, we just return CMD_SUCCESS, knowing this will propagate it where it needs to be
			 * and then that server will generate the users JOIN or FJOIN instead.
			 */
			if (IS_LOCAL(dest))
			{
				Channel::JoinUser(ServerInstance, dest, parameters[1].c_str(), true, "", false, ServerInstance->Time());
				/* Fix for dotslasher and w00t - if the join didnt succeed, return CMD_FAILURE so that it doesnt propagate */
				Channel* n = ServerInstance->FindChan(parameters[1]);
				if (n)
				{
					if (n->HasUser(dest))
					{
						ServerInstance->SNO->WriteToSnoMask('a', std::string(user->nick)+" used SAJOIN to make "+std::string(dest->nick)+" join "+parameters[1]);
						return CMD_SUCCESS;
					}
					else
					{
						user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Could not join "+std::string(dest->nick)+" to "+parameters[1]+" (User is probably banned, or blocking modes)");
						return CMD_FAILURE;
					}
				}
				else
				{
					user->WriteServ("NOTICE "+std::string(user->nick)+" :*** Could not join "+std::string(dest->nick)+" to "+parameters[1]);
					return CMD_FAILURE;
				}
			}
			else
			{
				ServerInstance->SNO->WriteToSnoMask('a', std::string(user->nick)+" sent remote SAJOIN to make "+std::string(dest->nick)+" join "+parameters[1]);
				return CMD_SUCCESS;
			}
		}
		else
		{
			user->WriteServ("NOTICE "+std::string(user->nick)+" :*** No such nickname "+parameters[0]);
			return CMD_FAILURE;
		}
	}
Пример #4
0
	CmdResult Handle (const std::vector<std::string>& parameters, User *user)
	{
		User* dest = ServerInstance->FindNick(parameters[0]);
		if ((dest) && (dest->registered == REG_ALL))
		{
			if (ServerInstance->ULine(dest->server))
			{
				user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an SA command on a u-lined client",user->nick.c_str());
				return CMD_FAILURE;
			}
			if (IS_LOCAL(user) && !ServerInstance->IsChannel(parameters[1].c_str(), ServerInstance->Config->Limits.ChanMax))
			{
				/* we didn't need to check this for each character ;) */
				user->WriteNotice("*** Invalid characters in channel name or name too long");
				return CMD_FAILURE;
			}

			/* For local users, we call Channel::JoinUser which may create a channel and set its TS.
			 * For non-local users, we just return CMD_SUCCESS, knowing this will propagate it where it needs to be
			 * and then that server will handle the command.
			 */
			LocalUser* localuser = IS_LOCAL(dest);
			if (localuser)
			{
				Channel* n = Channel::JoinUser(localuser, parameters[1], true);
				if (n)
				{
					if (n->HasUser(dest))
					{
						ServerInstance->SNO->WriteToSnoMask('a', user->nick+" used SAJOIN to make "+dest->nick+" join "+parameters[1]);
						return CMD_SUCCESS;
					}
					else
					{
						user->WriteNotice("*** Could not join "+dest->nick+" to "+parameters[1]+" (User is probably banned, or blocking modes)");
						return CMD_FAILURE;
					}
				}
				else
				{
					user->WriteNotice("*** Could not join "+dest->nick+" to "+parameters[1]);
					return CMD_FAILURE;
				}
			}
			else
			{
				ServerInstance->SNO->WriteToSnoMask('a', user->nick+" sent remote SAJOIN to make "+dest->nick+" join "+parameters[1]);
				return CMD_SUCCESS;
			}
		}
		else
		{
			user->WriteNotice("*** No such nickname "+parameters[0]);
			return CMD_FAILURE;
		}
	}
Пример #5
0
	CmdResult Handle (const std::vector<std::string>& parameters, User *user)
	{
		User* dest = ServerInstance->FindNick(parameters[1]);
		Channel* channel = ServerInstance->FindChan(parameters[0]);
		const char* reason = "";

		if ((dest) && (dest->registered == REG_ALL) && (channel))
		{
			if (parameters.size() > 2)
			{
				reason = parameters[2].c_str();
			}
			else
			{
				reason = dest->nick.c_str();
			}

			if (ServerInstance->ULine(dest->server))
			{
				user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an SA command on a u-lined client", user->nick.c_str());
				return CMD_FAILURE;
			}

			/* For local clients, directly kick them. For remote clients,
			 * just return CMD_SUCCESS knowing the protocol module will route the SAKICK to the user's
			 * local server and that will kick them instead.
			 */
			if (IS_LOCAL(dest))
			{
				channel->KickUser(ServerInstance->FakeClient, dest, reason);

				Channel *n = ServerInstance->FindChan(parameters[1]);
				if (n && n->HasUser(dest))
				{
					/* Sort-of-bug: If the command was issued remotely, this message won't be sent */
					user->WriteNotice("*** Unable to kick " + dest->nick + " from " + parameters[0]);
					return CMD_FAILURE;
				}
			}

			if (IS_LOCAL(user))
			{
				/* Locally issued command; send the snomasks */
				ServerInstance->SNO->WriteGlobalSno('a', user->nick + " SAKICKed " + dest->nick + " on " + parameters[0]);
			}

			return CMD_SUCCESS;
		}
		else
		{
			user->WriteNotice("*** Invalid nickname or channel");
		}

		return CMD_FAILURE;
	}
Пример #6
0
	CmdResult Handle (const std::vector<std::string>& parameters, User *user)
	{
		User* dest = ServerInstance->FindNick(parameters[0]);
		Channel* channel = ServerInstance->FindChan(parameters[1]);
		std::string reason;

		if ((dest) && (dest->registered == REG_ALL) && (channel))
		{
			if (parameters.size() > 2)
				reason = parameters[2];

			if (ServerInstance->ULine(dest->server))
			{
				user->WriteNumeric(ERR_NOPRIVILEGES, "%s :Cannot use an SA command on a u-lined client",user->nick.c_str());
				return CMD_FAILURE;
			}

			/* For local clients, directly part them generating a PART message. For remote clients,
			 * just return CMD_SUCCESS knowing the protocol module will route the SAPART to the users
			 * local server and that will generate the PART instead
			 */
			if (IS_LOCAL(dest))
			{
				channel->PartUser(dest, reason);

				Channel* n = ServerInstance->FindChan(parameters[1]);
				if (!n)
				{
					ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAPART to make "+dest->nick+" part "+parameters[1]);
					return CMD_SUCCESS;
				}
				else
				{
					if (!n->HasUser(dest))
					{
						ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAPART to make "+dest->nick+" part "+parameters[1]);
						return CMD_SUCCESS;
					}
					else
					{
						user->WriteServ("NOTICE %s :*** Unable to make %s part %s",user->nick.c_str(), dest->nick.c_str(), parameters[1].c_str());
						return CMD_FAILURE;
					}
				}
			}

			return CMD_SUCCESS;
		}
		else
		{
			user->WriteServ("NOTICE %s :*** Invalid nickname or channel", user->nick.c_str());
		}

		return CMD_FAILURE;
	}
Пример #7
0
std::string User::ChannelList(User* source, bool spy)
{
	std::string list;

	for (UCListIter i = this->chans.begin(); i != this->chans.end(); i++)
	{
		Channel* c = *i;
		/* If the target is the sender, neither +p nor +s is set, or
		 * the channel contains the user, it is not a spy channel
		 */
		if (spy != (source == this || !(c->IsModeSet('p') || c->IsModeSet('s')) || c->HasUser(source)))
			list.append(c->GetPrefixChar(this)).append(c->name).append(" ");
	}

	return list;
}
Пример #8
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		Channel* channel = ServerInstance->FindChan(parameters[0]);
		std::string reason = ConvToStr("Cycling");

		if (parameters.size() > 1)
		{
			/* reason provided, use it */
			reason = reason + ": " + parameters[1];
		}

		if (!channel)
		{
			user->WriteNumeric(403, "%s %s :No such channel", user->nick.c_str(), parameters[0].c_str());
			return CMD_FAILURE;
		}

		if (channel->HasUser(user))
		{
			/*
			 * technically, this is only ever sent locally, but pays to be safe ;p
			 */
			if (IS_LOCAL(user))
			{
				if (channel->GetPrefixValue(user) < VOICE_VALUE && channel->IsBanned(user))
				{
					/* banned, boned. drop the message. */
					user->WriteServ("NOTICE "+user->nick+" :*** You may not cycle, as you are banned on channel " + channel->name);
					return CMD_FAILURE;
				}

				channel->PartUser(user, reason);

				Channel::JoinUser(user, parameters[0], true, "", false, ServerInstance->Time());
			}

			return CMD_SUCCESS;
		}
		else
		{
			user->WriteNumeric(442, "%s %s :You're not on that channel", user->nick.c_str(), channel->name.c_str());
		}

		return CMD_FAILURE;
	}
Пример #9
0
    CmdResult Handle (const std::vector<std::string>& parameters, User *user)
    {
        if (CommandParser::LoopCall(user, this, parameters, 1))
            return CMD_FAILURE;

        User* dest = ServerInstance->FindNick(parameters[0]);
        Channel* channel = ServerInstance->FindChan(parameters[1]);
        std::string reason;

        if ((dest) && (dest->registered == REG_ALL) && (channel))
        {
            if (parameters.size() > 2)
                reason = parameters[2];

            if (dest->server->IsULine())
            {
                user->WriteNumeric(ERR_NOPRIVILEGES, ":Cannot use an SA command on a u-lined client");
                return CMD_FAILURE;
            }

            if (!channel->HasUser(dest))
            {
                user->WriteNotice("*** " + dest->nick + " is not on " + channel->name);
                return CMD_FAILURE;
            }

            /* For local clients, directly part them generating a PART message. For remote clients,
             * just return CMD_SUCCESS knowing the protocol module will route the SAPART to the users
             * local server and that will generate the PART instead
             */
            if (IS_LOCAL(dest))
            {
                channel->PartUser(dest, reason);
                ServerInstance->SNO->WriteGlobalSno('a', user->nick+" used SAPART to make "+dest->nick+" part "+channel->name);
            }

            return CMD_SUCCESS;
        }
        else
        {
            user->WriteNotice("*** Invalid nickname or channel");
        }

        return CMD_FAILURE;
    }
Пример #10
0
	CmdResult Handle(User* user, const Params& parameters) override
	{
		User* dest = ServerInstance->FindNick(parameters[1]);
		Channel* channel = ServerInstance->FindChan(parameters[0]);

		if ((dest) && (dest->registered == REG_ALL) && (channel))
		{
			const std::string& reason = (parameters.size() > 2) ? parameters[2] : dest->nick;

			if (dest->server->IsULine())
			{
				user->WriteNumeric(ERR_NOPRIVILEGES, "Cannot use an SA command on a U-lined client");
				return CMD_FAILURE;
			}

			if (!channel->HasUser(dest))
			{
				user->WriteNotice("*** " + dest->nick + " is not on " + channel->name);
				return CMD_FAILURE;
			}

			/* For local clients, directly kick them. For remote clients,
			 * just return CMD_SUCCESS knowing the protocol module will route the SAKICK to the user's
			 * local server and that will kick them instead.
			 */
			if (IS_LOCAL(dest))
			{
				// Target is on this server, kick them and send the snotice
				channel->KickUser(ServerInstance->FakeClient, dest, reason);
				ServerInstance->SNO.WriteGlobalSno('a', user->nick + " SAKICKed " + dest->nick + " on " + channel->name);
			}

			return CMD_SUCCESS;
		}
		else
		{
			user->WriteNotice("*** Invalid nickname or channel");
		}

		return CMD_FAILURE;
	}
Пример #11
0
/** Handle /KICK
 */
CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User *user)
{
	std::string reason;
	Channel* c = ServerInstance->FindChan(parameters[0]);
	User* u;

	if (ServerInstance->Parser->LoopCall(user, this, parameters, 1))
		return CMD_SUCCESS;

	if (IS_LOCAL(user))
		u = ServerInstance->FindNickOnly(parameters[1]);
	else
		u = ServerInstance->FindNick(parameters[1]);

	if (!u || !c)
	{
		user->WriteServ( "401 %s %s :No such nick/channel", user->nick.c_str(), u ? parameters[0].c_str() : parameters[1].c_str());
		return CMD_FAILURE;
	}

	if ((IS_LOCAL(user)) && (!c->HasUser(user)) && (!ServerInstance->ULine(user->server)))
	{
		user->WriteServ( "442 %s %s :You're not on that channel!", user->nick.c_str(), parameters[0].c_str());
		return CMD_FAILURE;
	}

	if (parameters.size() > 2)
	{
		reason.assign(parameters[2], 0, ServerInstance->Config->Limits.MaxKick);
	}
	else
	{
		reason.assign(user->nick, 0, ServerInstance->Config->Limits.MaxKick);
	}

	c->KickUser(user, u, reason);

	return CMD_SUCCESS;
}
Пример #12
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		Channel* c = ServerInstance->FindChan(parameters[0]);
		if (!c)
		{
			user->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
			return CMD_FAILURE;
		}

		if (c->HasUser(user))
		{
			user->WriteNumeric(ERR_KNOCKONCHAN, c->name, InspIRCd::Format("Can't KNOCK on %s, you are already on that channel.", c->name.c_str()));
			return CMD_FAILURE;
		}

		if (c->IsModeSet(noknockmode))
		{
			user->WriteNumeric(480, InspIRCd::Format("Can't KNOCK on %s, +K is set.", c->name.c_str()));
			return CMD_FAILURE;
		}

		if (!c->IsModeSet(inviteonlymode))
		{
			user->WriteNumeric(ERR_CHANOPEN, c->name, InspIRCd::Format("Can't KNOCK on %s, channel is not invite only so knocking is pointless!", c->name.c_str()));
			return CMD_FAILURE;
		}

		if (sendnotice)
			c->WriteNotice(InspIRCd::Format("User %s is KNOCKing on %s (%s)", user->nick.c_str(), c->name.c_str(), parameters[1].c_str()));

		if (sendnumeric)
			c->WriteChannelWithServ(ServerInstance->Config->ServerName, "710 %s %s %s :is KNOCKing: %s", c->name.c_str(), c->name.c_str(), user->GetFullHost().c_str(), parameters[1].c_str());

		user->WriteNotice("KNOCKing on " + c->name);
		return CMD_SUCCESS;
	}
Пример #13
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		Channel* c = ServerInstance->FindChan(parameters[0]);
		if (!c)
		{
			user->WriteNumeric(401, "%s %s :No such channel",user->nick.c_str(), parameters[0].c_str());
			return CMD_FAILURE;
		}

		if (c->HasUser(user))
		{
			user->WriteNumeric(480, "%s :Can't KNOCK on %s, you are already on that channel.", user->nick.c_str(), c->name.c_str());
			return CMD_FAILURE;
		}

		if (c->IsModeSet('K'))
		{
			user->WriteNumeric(480, "%s :Can't KNOCK on %s, +K is set.",user->nick.c_str(), c->name.c_str());
			return CMD_FAILURE;
		}

		if (!c->IsModeSet('i'))
		{
			user->WriteNumeric(480, "%s :Can't KNOCK on %s, channel is not invite only so knocking is pointless!",user->nick.c_str(), c->name.c_str());
			return CMD_FAILURE;
		}

		if (sendnotice)
			c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :User %s is KNOCKing on %s (%s)", c->name.c_str(), user->nick.c_str(), c->name.c_str(), parameters[1].c_str());

		if (sendnumeric)
			c->WriteChannelWithServ(ServerInstance->Config->ServerName, "710 %s %s %s :is KNOCKing: %s", c->name.c_str(), c->name.c_str(), user->GetFullHost().c_str(), parameters[1].c_str());

		user->WriteNotice("KNOCKing on " + c->name);
		return CMD_SUCCESS;
	}
Пример #14
0
CmdResult CommandPrivmsg::Handle (const std::vector<std::string>& parameters, User *user)
{
	User *dest;
	Channel *chan;
	CUList except_list;

	LocalUser* localuser = IS_LOCAL(user);
	if (localuser)
		localuser->idle_lastmsg = ServerInstance->Time();

	if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
		return CMD_SUCCESS;

	if (parameters[0][0] == '$')
	{
		if (!user->HasPrivPermission("users/mass-message"))
			return CMD_SUCCESS;

		ModResult MOD_RESULT;
		std::string temp = parameters[1];
		FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, except_list, MSG_PRIVMSG));
		if (MOD_RESULT == MOD_RES_DENY)
			return CMD_FAILURE;

		const char* text = temp.c_str();
		const char* servermask = (parameters[0].c_str()) + 1;

		FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list));
		if (InspIRCd::Match(ServerInstance->Config->ServerName, servermask, NULL))
		{
			user->SendAll("PRIVMSG", "%s", text);
		}
		FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, except_list, MSG_PRIVMSG));
		return CMD_SUCCESS;
	}
	char status = 0;
	const char* target = parameters[0].c_str();

	if (ServerInstance->Modes->FindPrefix(*target))
	{
		status = *target;
		target++;
	}
	if (*target == '#')
	{
		chan = ServerInstance->FindChan(target);

		except_list.insert(user);

		if (chan)
		{
			if (localuser && chan->GetPrefixValue(user) < VOICE_VALUE)
			{
				if (chan->IsModeSet('n') && !chan->HasUser(user))
				{
					user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
					return CMD_FAILURE;
				}

				if (chan->IsModeSet('m'))
				{
					user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
					return CMD_FAILURE;
				}

				if (ServerInstance->Config->RestrictBannedUsers)
				{
					if (chan->IsBanned(user))
					{
						user->WriteNumeric(404, "%s %s :Cannot send to channel (you're banned)", user->nick.c_str(), chan->name.c_str());
						return CMD_FAILURE;
					}
				}
			}
			ModResult MOD_RESULT;

			std::string temp = parameters[1];
			FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, chan, TYPE_CHANNEL, temp, status, except_list, MSG_PRIVMSG));
			if (MOD_RESULT == MOD_RES_DENY)
				return CMD_FAILURE;

			const char* text = temp.c_str();

			/* Check again, a module may have zapped the input string */
			if (temp.empty())
			{
				user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
				return CMD_FAILURE;
			}

			FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,except_list));

			if (status)
			{
				if (ServerInstance->Config->UndernetMsgPrefix)
				{
					chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%c %s", status, chan->name.c_str(), status, text);
				}
				else
				{
					chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %c%s :%s", status, chan->name.c_str(), text);
				}
			}
			else
			{
				chan->WriteAllExcept(user, false, status, except_list, "PRIVMSG %s :%s", chan->name.c_str(), text);
			}

			FOREACH_MOD(I_OnUserMessage, OnUserMessage(user,chan, TYPE_CHANNEL, text, status, except_list, MSG_PRIVMSG));
		}
		else
		{
			/* no such nick/channel */
			user->WriteNumeric(401, "%s %s :No such nick/channel", user->nick.c_str(), target);
			return CMD_FAILURE;
		}
		return CMD_SUCCESS;
	}

	const char* destnick = parameters[0].c_str();

	if (localuser)
	{
		const char* targetserver = strchr(destnick, '@');

		if (targetserver)
		{
			std::string nickonly;

			nickonly.assign(destnick, 0, targetserver - destnick);
			dest = ServerInstance->FindNickOnly(nickonly);
			if (dest && strcasecmp(dest->server.c_str(), targetserver + 1))
			{
				/* Incorrect server for user */
				user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
				return CMD_FAILURE;
			}
		}
		else
			dest = ServerInstance->FindNickOnly(destnick);
	}
	else
		dest = ServerInstance->FindNick(destnick);

	if ((dest) && (dest->registered == REG_ALL))
	{
		if (parameters[1].empty())
		{
			user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
			return CMD_FAILURE;
		}

		if (dest->IsAway())
		{
			/* auto respond with aweh msg */
			user->WriteNumeric(301, "%s %s :%s", user->nick.c_str(), dest->nick.c_str(), dest->awaymsg.c_str());
		}

		ModResult MOD_RESULT;

		std::string temp = parameters[1];
		FIRST_MOD_RESULT(OnUserPreMessage, MOD_RESULT, (user, dest, TYPE_USER, temp, 0, except_list, MSG_PRIVMSG));
		if (MOD_RESULT == MOD_RES_DENY)
			return CMD_FAILURE;

		const char* text = temp.c_str();

		FOREACH_MOD(I_OnText,OnText(user, dest, TYPE_USER, text, 0, except_list));

		if (IS_LOCAL(dest))
		{
			// direct write, same server
			user->WriteTo(dest, "PRIVMSG %s :%s", dest->nick.c_str(), text);
		}

		FOREACH_MOD(I_OnUserMessage,OnUserMessage(user, dest, TYPE_USER, text, 0, except_list, MSG_PRIVMSG));
	}
	else
	{
		/* no such nick/channel */
		user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
		return CMD_FAILURE;
	}
	return CMD_SUCCESS;
}
Пример #15
0
	CmdResult HandleRMB(const std::vector<std::string>& parameters, User *user, bool neworder)
	{
		User* target;
		Channel* channel;
		std::string reason;
		std::string protectkey;
		std::string founderkey;
		bool hasnokicks;

		/* Set these to the parameters needed, the new version of this module switches it's parameters around
		 * supplying a new command with the new order while keeping the old /remove with the older order.
		 * /remove <nick> <channel> [reason ...]
		 * /fpart <channel> <nick> [reason ...]
		 */
		const std::string& channame = parameters[neworder ? 0 : 1];
		const std::string& username = parameters[neworder ? 1 : 0];

		/* Look up the user we're meant to be removing from the channel */
		target = ServerInstance->FindNick(username);

		/* And the channel we're meant to be removing them from */
		channel = ServerInstance->FindChan(channame);

		/* Fix by brain - someone needs to learn to validate their input! */
		if ((!target) || (target->registered != REG_ALL) || (!channel))
		{
			user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel", user->nick.c_str(), !channel ? channame.c_str() : username.c_str());
			return CMD_FAILURE;
		}

		if (!channel->HasUser(target))
		{
			user->WriteServ( "NOTICE %s :*** The user %s is not on channel %s", user->nick.c_str(), target->nick.c_str(), channel->name.c_str());
			return CMD_FAILURE;
		}

		int ulevel = channel->GetPrefixValue(user);
		int tlevel = channel->GetPrefixValue(target);

		hasnokicks = (ServerInstance->Modules->Find("m_nokicks.so") && channel->IsModeSet('Q'));

		if (ServerInstance->ULine(target->server))
		{
			user->WriteNumeric(482, "%s %s :Only a u-line may remove a u-line from a channel.", user->nick.c_str(), channame.c_str());
			return CMD_FAILURE;
		}

		/* We support the +Q channel mode via. the m_nokicks module, if the module is loaded and the mode is set then disallow the /remove */
		if ((!IS_LOCAL(user)) || (!supportnokicks || !hasnokicks))
		{
			/* We'll let everyone remove their level and below, eg:
			 * ops can remove ops, halfops, voices, and those with no mode (no moders actually are set to 1)
			 * a ulined target will get a higher level than it's possible for a /remover to get..so they're safe.
			 * Nobody may remove a founder.
			 */
			if ((!IS_LOCAL(user)) || ((ulevel > VOICE_VALUE) && (ulevel >= tlevel) && (tlevel != 50000)))
			{
				// REMOVE/FPART will be sent to the target's server and it will reply with a PART (or do nothing if it doesn't understand the command)
				if (!IS_LOCAL(target))
					return CMD_SUCCESS;

				std::string reasonparam;

				/* If a reason is given, use it */
				if(parameters.size() > 2)
					reasonparam = parameters[2];
				else
					reasonparam = "No reason given";

				/* Build up the part reason string. */
				reason = "Removed by " + user->nick + ": " + reasonparam;

				channel->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s removed %s from the channel", channel->name.c_str(), user->nick.c_str(), target->nick.c_str());
				target->WriteServ("NOTICE %s :*** %s removed you from %s with the message: %s", target->nick.c_str(), user->nick.c_str(), channel->name.c_str(), reasonparam.c_str());

				channel->PartUser(target, reason);
			}
			else
			{
				user->WriteServ( "NOTICE %s :*** You do not have access to /remove %s from %s", user->nick.c_str(), target->nick.c_str(), channel->name.c_str());
				return CMD_FAILURE;
			}
		}
		else
		{
			/* m_nokicks.so was loaded and +Q was set, block! */
			user->WriteServ( "484 %s %s :Can't remove user %s from channel (+Q set)", user->nick.c_str(), channel->name.c_str(), target->nick.c_str());
			return CMD_FAILURE;
		}

		return CMD_SUCCESS;
	}
Пример #16
0
/** Handle /INVITE
 */
CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, User *user)
{
	ModResult MOD_RESULT;

	if (parameters.size() == 2 || parameters.size() == 3)
	{
		User* u;
		if (IS_LOCAL(user))
			u = ServerInstance->FindNickOnly(parameters[0]);
		else
			u = ServerInstance->FindNick(parameters[0]);

		Channel* c = ServerInstance->FindChan(parameters[1]);
		time_t timeout = 0;
		if (parameters.size() == 3)
		{
			if (IS_LOCAL(user))
				timeout = ServerInstance->Time() + InspIRCd::Duration(parameters[1]);
			else
				timeout = ConvToInt(parameters[2]);
		}

		if ((!c) || (!u) || (u->registered != REG_ALL))
		{
			user->WriteNumeric(ERR_NOSUCHNICK, "%s %s :No such nick/channel",user->nick.c_str(), c ? parameters[0].c_str() : parameters[1].c_str());
			return CMD_FAILURE;
		}

		if ((IS_LOCAL(user)) && (!c->HasUser(user)))
		{
			user->WriteNumeric(ERR_NOTONCHANNEL, "%s %s :You're not on that channel!",user->nick.c_str(), c->name.c_str());
			return CMD_FAILURE;
		}

		if (c->HasUser(u))
		{
			user->WriteNumeric(ERR_USERONCHANNEL, "%s %s %s :is already on channel",user->nick.c_str(),u->nick.c_str(),c->name.c_str());
			return CMD_FAILURE;
		}

		FIRST_MOD_RESULT(OnUserPreInvite, MOD_RESULT, (user,u,c,timeout));

		if (MOD_RESULT == MOD_RES_DENY)
		{
			return CMD_FAILURE;
		}
		else if (MOD_RESULT == MOD_RES_PASSTHRU)
		{
			if (IS_LOCAL(user))
			{
				unsigned int rank = c->GetPrefixValue(user);
				if (rank < HALFOP_VALUE)
				{
					// Check whether halfop mode is available and phrase error message accordingly
					ModeHandler* mh = ServerInstance->Modes->FindMode('h', MODETYPE_CHANNEL);
					user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must be a channel %soperator",
						user->nick.c_str(), c->name.c_str(), (mh && mh->name == "halfop" ? "half-" : ""));
					return CMD_FAILURE;
				}
			}
		}

		if (IS_LOCAL(u))
		{
			Invitation::Create(c, IS_LOCAL(u), timeout);
			u->WriteFrom(user,"INVITE %s :%s",u->nick.c_str(),c->name.c_str());
		}

		if (IS_LOCAL(user))
			user->WriteNumeric(RPL_INVITING, "%s %s %s",user->nick.c_str(),u->nick.c_str(),c->name.c_str());

		if (ServerInstance->Config->AnnounceInvites != ServerConfig::INVITE_ANNOUNCE_NONE)
		{
			char prefix;
			switch (ServerInstance->Config->AnnounceInvites)
			{
				case ServerConfig::INVITE_ANNOUNCE_OPS:
				{
					prefix = '@';
					break;
				}
				case ServerConfig::INVITE_ANNOUNCE_DYNAMIC:
				{
					PrefixMode* mh = ServerInstance->Modes->FindPrefixMode('h');
					prefix = (mh && mh->name == "halfop" ? mh->GetPrefix() : '@');
					break;
				}
				default:
				{
					prefix = 0;
					break;
				}
			}
			c->WriteAllExceptSender(user, true, prefix, "NOTICE %s :*** %s invited %s into the channel", c->name.c_str(), user->nick.c_str(), u->nick.c_str());
		}
		FOREACH_MOD(OnUserInvite, (user,u,c,timeout));
	}
	else if (IS_LOCAL(user))
	{
		// pinched from ircu - invite with not enough parameters shows channels
		// youve been invited to but haven't joined yet.
		InviteList& il = IS_LOCAL(user)->GetInviteList();
		for (InviteList::const_iterator i = il.begin(); i != il.end(); ++i)
		{
			user->WriteNumeric(RPL_INVITELIST, "%s :%s",user->nick.c_str(), (*i)->chan->name.c_str());
		}
		user->WriteNumeric(RPL_ENDOFINVITELIST, "%s :End of INVITE list",user->nick.c_str());
	}
	return CMD_SUCCESS;
}
Пример #17
0
CmdResult CommandNotice::Handle (const std::vector<std::string>& parameters, User *user)
{
    User *dest;
    Channel *chan;

    CUList exempt_list;

    user->idle_lastmsg = ServerInstance->Time();

    if (ServerInstance->Parser->LoopCall(user, this, parameters, 0))
        return CMD_SUCCESS;
    if (parameters[0][0] == '$')
    {
        if (!user->HasPrivPermission("users/mass-message"))
            return CMD_SUCCESS;

        int MOD_RESULT = 0;
        std::string temp = parameters[1];
        FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, temp, 0, exempt_list));
        if (MOD_RESULT)
            return CMD_FAILURE;
        const char* text = temp.c_str();
        const char* servermask = (parameters[0].c_str()) + 1;

        FOREACH_MOD(I_OnText,OnText(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
        if (InspIRCd::Match(ServerInstance->Config->ServerName,servermask, NULL))
        {
            user->SendAll("NOTICE", "%s", text);
        }
        FOREACH_MOD(I_OnUserNotice,OnUserNotice(user, (void*)parameters[0].c_str(), TYPE_SERVER, text, 0, exempt_list));
        return CMD_SUCCESS;
    }
    char status = 0;
    const char* target = parameters[0].c_str();

    if (ServerInstance->Modes->FindPrefix(*target))
    {
        status = *target;
        target++;
    }
    if (*target == '#')
    {
        chan = ServerInstance->FindChan(target);

        exempt_list[user] = user->nick;

        if (chan)
        {
            if (IS_LOCAL(user))
            {
                if ((chan->IsModeSet('n')) && (!chan->HasUser(user)))
                {
                    user->WriteNumeric(404, "%s %s :Cannot send to channel (no external messages)", user->nick.c_str(), chan->name.c_str());
                    return CMD_FAILURE;
                }
                if ((chan->IsModeSet('m')) && (chan->GetStatus(user) < STATUS_VOICE))
                {
                    user->WriteNumeric(404, "%s %s :Cannot send to channel (+m)", user->nick.c_str(), chan->name.c_str());
                    return CMD_FAILURE;
                }
            }
            int MOD_RESULT = 0;

            std::string temp = parameters[1];
            FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user,chan,TYPE_CHANNEL,temp,status, exempt_list));
            if (MOD_RESULT) {
                return CMD_FAILURE;
            }
            const char* text = temp.c_str();

            if (temp.empty())
            {
                user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
                return CMD_FAILURE;
            }

            FOREACH_MOD(I_OnText,OnText(user,chan,TYPE_CHANNEL,text,status,exempt_list));

            if (status)
            {
                if (ServerInstance->Config->UndernetMsgPrefix)
                {
                    chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%c %s", status, chan->name.c_str(), status, text);
                }
                else
                {
                    chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %c%s :%s", status, chan->name.c_str(), text);
                }
            }
            else
            {
                chan->WriteAllExcept(user, false, status, exempt_list, "NOTICE %s :%s", chan->name.c_str(), text);
            }

            FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,chan,TYPE_CHANNEL,text,status,exempt_list));
        }
        else
        {
            /* no such nick/channel */
            user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), target);
            return CMD_FAILURE;
        }
        return CMD_SUCCESS;
    }

    const char* destnick = parameters[0].c_str();

    if (IS_LOCAL(user))
    {
        const char* targetserver = strchr(destnick, '@');

        if (targetserver)
        {
            std::string nickonly;

            nickonly.assign(destnick, 0, targetserver - destnick);
            dest = ServerInstance->FindNickOnly(nickonly);
            if (dest && strcasecmp(dest->server, targetserver + 1))
            {
                /* Incorrect server for user */
                user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
                return CMD_FAILURE;
            }
        }
        else
            dest = ServerInstance->FindNickOnly(destnick);
    }
    else
        dest = ServerInstance->FindNick(destnick);

    if (dest)
    {
        if (parameters[1].empty())
        {
            user->WriteNumeric(412, "%s :No text to send", user->nick.c_str());
            return CMD_FAILURE;
        }

        int MOD_RESULT = 0;
        std::string temp = parameters[1];
        FOREACH_RESULT(I_OnUserPreNotice,OnUserPreNotice(user,dest,TYPE_USER,temp,0,exempt_list));
        if (MOD_RESULT) {
            return CMD_FAILURE;
        }
        const char* text = temp.c_str();

        FOREACH_MOD(I_OnText,OnText(user,dest,TYPE_USER,text,0,exempt_list));

        if (IS_LOCAL(dest))
        {
            // direct write, same server
            user->WriteTo(dest, "NOTICE %s :%s", dest->nick.c_str(), text);
        }

        FOREACH_MOD(I_OnUserNotice,OnUserNotice(user,dest,TYPE_USER,text,0,exempt_list));
    }
    else
    {
        /* no such nick/channel */
        user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
        return CMD_FAILURE;
    }

    return CMD_SUCCESS;

}
Пример #18
0
std::string CommandWhois::ChannelList(User* source, User* dest, bool spy)
{
	std::string list;

	for (User::ChanList::iterator i = dest->chans.begin(); i != dest->chans.end(); i++)
	{
		Membership* memb = *i;
		Channel* c = memb->chan;
		/* If the target is the sender, neither +p nor +s is set, or
		 * the channel contains the user, it is not a spy channel
		 */
		if (spy != (source == dest || !(c->IsModeSet(privatemode) || c->IsModeSet(secretmode)) || c->HasUser(source)))
		{
			char prefix = memb->GetPrefixChar();
			if (prefix)
				list.push_back(prefix);
			list.append(c->name).push_back(' ');
		}
	}

	return list;
}
Пример #19
0
std::string CommandWhois::ChannelList(User* source, User* dest, bool spy)
{
	std::string list;

	for (UCListIter i = dest->chans.begin(); i != dest->chans.end(); i++)
	{
		Channel* c = *i;
		/* If the target is the sender, neither +p nor +s is set, or
		 * the channel contains the user, it is not a spy channel
		 */
		if (spy != (source == dest || !(c->IsModeSet(privatemode) || c->IsModeSet(secretmode)) || c->HasUser(source)))
			list.append(c->GetPrefixChar(dest)).append(c->name).append(" ");
	}

	return list;
}
Пример #20
0
CmdResult CommandWho::Handle (const std::vector<std::string>& parameters, User *user)
{
	/*
	 * XXX - RFC says:
	 *   The <name> passed to WHO is matched against users' host, server, real
	 *   name and nickname
	 * Currently, we support WHO #chan, WHO nick, WHO 0, WHO *, and the addition of a 'o' flag, as per RFC.
	 */

	/* WHO options */
	opt_viewopersonly = false;
	opt_showrealhost = false;
	opt_realname = false;
	opt_mode = false;
	opt_ident = false;
	opt_metadata = false;
	opt_port = false;
	opt_away = false;
	opt_local = false;
	opt_far = false;
	opt_time = false;

	std::vector<std::string> whoresults;
	std::string initial = "352 " + user->nick + " ";

	/* Change '0' into '*' so the wildcard matcher can grok it */
	std::string matchtext = ((parameters[0] == "0") ? "*" : parameters[0]);

	// WHO flags count as a wildcard
	bool usingwildcards = ((parameters.size() > 1) || (matchtext.find_first_of("*?.") != std::string::npos));

	if (parameters.size() > 1)
	{
		for (std::string::const_iterator iter = parameters[1].begin(); iter != parameters[1].end(); ++iter)
		{
			switch (*iter)
			{
				case 'o':
					opt_viewopersonly = true;
					break;
				case 'h':
					if (user->HasPrivPermission("users/auspex"))
						opt_showrealhost = true;
					break;
				case 'r':
					opt_realname = true;
					break;
				case 'm':
					if (user->HasPrivPermission("users/auspex"))
						opt_mode = true;
					break;
				case 'M':
					if (user->HasPrivPermission("users/auspex"))
						opt_metadata = true;
					break;
				case 'i':
					opt_ident = true;
					break;
				case 'p':
					if (user->HasPrivPermission("users/auspex"))
						opt_port = true;
					break;
				case 'a':
					opt_away = true;
					break;
				case 'l':
					if (user->HasPrivPermission("users/auspex") || ServerInstance->Config->HideWhoisServer.empty())
						opt_local = true;
					break;
				case 'f':
					if (user->HasPrivPermission("users/auspex") || ServerInstance->Config->HideWhoisServer.empty())
						opt_far = true;
					break;
				case 't':
					opt_time = true;
					break;
			}
		}
	}


	/* who on a channel? */
	Channel* ch = ServerInstance->FindChan(matchtext);

	if (ch)
	{
		if (CanView(ch,user))
		{
			bool inside = ch->HasUser(user);

			/* who on a channel. */
			const UserMembList *cu = ch->GetUsers();

			for (UserMembCIter i = cu->begin(); i != cu->end(); i++)
			{
				/* None of this applies if we WHO ourselves */
				if (user != i->first)
				{
					/* opers only, please */
					if (opt_viewopersonly && !i->first->IsOper())
						continue;

					/* If we're not inside the channel, hide +i users */
					if (i->first->IsModeSet(invisiblemode) && !inside && !user->HasPrivPermission("users/auspex"))
						continue;
				}

				SendWhoLine(user, parameters, initial, ch, i->first, whoresults);
			}
		}
	}
	else
	{
		/* Match against wildcard of nick, server or host */
		if (opt_viewopersonly)
		{
			/* Showing only opers */
			for (std::list<User*>::iterator i = ServerInstance->Users->all_opers.begin(); i != ServerInstance->Users->all_opers.end(); i++)
			{
				User* oper = *i;

				if (whomatch(user, oper, matchtext.c_str()))
				{
					if (!user->SharesChannelWith(oper))
					{
						if (usingwildcards && (!oper->IsModeSet(invisiblemode)) && (!user->HasPrivPermission("users/auspex")))
							continue;
					}

					SendWhoLine(user, parameters, initial, NULL, oper, whoresults);
				}
			}
		}
		else
		{
			for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++)
			{
				if (whomatch(user, i->second, matchtext.c_str()))
				{
					if (!user->SharesChannelWith(i->second))
					{
						if (usingwildcards && (i->second->IsModeSet(invisiblemode)) && (!user->HasPrivPermission("users/auspex")))
							continue;
					}

					SendWhoLine(user, parameters, initial, NULL, i->second, whoresults);
				}
			}
		}
	}
	/* Send the results out */
	for (std::vector<std::string>::const_iterator n = whoresults.begin(); n != whoresults.end(); n++)
		user->WriteServ(*n);
	user->WriteNumeric(RPL_ENDOFWHO, "%s :End of /WHO list.", *parameters[0].c_str() ? parameters[0].c_str() : "*");

	// Penalize the user a bit for large queries
	// (add one unit of penalty per 200 results)
	if (IS_LOCAL(user))
		IS_LOCAL(user)->CommandFloodPenalty += whoresults.size() * 5;
	return CMD_SUCCESS;
}
Пример #21
0
	CmdResult HandleChannelTarget(User* source, const Params& parameters, const char* target, PrefixMode* pm)
	{
		Channel* chan = ServerInstance->FindChan(target);
		if (!chan)
		{
			// The target channel does not exist.
			source->WriteNumeric(Numerics::NoSuchChannel(parameters[0]));
			return CMD_FAILURE;
		}

		if (IS_LOCAL(source))
		{
			if (chan->IsModeSet(noextmsgmode) && !chan->HasUser(source))
			{
				// The noextmsg mode is set and the source is not in the channel.
				source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (no external messages)");
				return CMD_FAILURE;
			}

			bool no_chan_priv = chan->GetPrefixValue(source) < VOICE_VALUE;
			if (no_chan_priv && chan->IsModeSet(moderatedmode))
			{
				// The moderated mode is set and the source has no status rank.
				source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (+m)");
				return CMD_FAILURE;
			}

			if (no_chan_priv && ServerInstance->Config->RestrictBannedUsers != ServerConfig::BUT_NORMAL && chan->IsBanned(source))
			{
				// The source is banned in the channel and restrictbannedusers is enabled.
				if (ServerInstance->Config->RestrictBannedUsers == ServerConfig::BUT_RESTRICT_NOTIFY)
					source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (you're banned)");
				return CMD_FAILURE;
			}
		}

		// Fire the pre-message events.
		MessageTarget msgtarget(chan, pm ? pm->GetPrefix() : 0);
		CTCTags::TagMessageDetails msgdetails(parameters.GetTags());
		if (!FirePreEvents(source, msgtarget, msgdetails))
			return CMD_FAILURE;

		unsigned int minrank = pm ? pm->GetPrefixRank() : 0;
		CTCTags::TagMessage message(source, chan, parameters.GetTags());
		const Channel::MemberMap& userlist = chan->GetUsers();
		for (Channel::MemberMap::const_iterator iter = userlist.begin(); iter != userlist.end(); ++iter)
		{
			LocalUser* luser = IS_LOCAL(iter->first);

			// Don't send to remote users or the user who is the source. 
			if (!luser || luser == source)
				continue;

			// Don't send to unprivileged or exempt users.
			if (iter->second->getRank() < minrank || msgdetails.exemptions.count(luser))
				continue;

			// Send to users if they have the capability.
			if (cap.get(luser))
				luser->Send(msgevprov, message);
		}
		return FirePostEvent(source, msgtarget, msgdetails);
	}
Пример #22
0
	CmdResult HandleRMB(User* user, const CommandBase::Params& parameters,  bool fpart)
	{
		User* target;
		Channel* channel;
		std::string reason;

		// If the command is a /REMOVE then detect the parameter order
		bool neworder = ((fpart) || (parameters[0][0] == '#'));

		/* Set these to the parameters needed, the new version of this module switches it's parameters around
		 * supplying a new command with the new order while keeping the old /remove with the older order.
		 * /remove <nick> <channel> [reason ...]
		 * /fpart <channel> <nick> [reason ...]
		 */
		const std::string& channame = parameters[neworder ? 0 : 1];
		const std::string& username = parameters[neworder ? 1 : 0];

		/* Look up the user we're meant to be removing from the channel */
		if (IS_LOCAL(user))
			target = ServerInstance->FindNickOnly(username);
		else
			target = ServerInstance->FindNick(username);

		/* And the channel we're meant to be removing them from */
		channel = ServerInstance->FindChan(channame);

		/* Fix by brain - someone needs to learn to validate their input! */
		if (!channel)
		{
			user->WriteNumeric(Numerics::NoSuchChannel(channame));
			return CMD_FAILURE;
		}
		if ((!target) || (target->registered != REG_ALL))
		{
			user->WriteNumeric(Numerics::NoSuchNick(username));
			return CMD_FAILURE;
		}

		if (!channel->HasUser(target))
		{
			user->WriteNotice(InspIRCd::Format("*** The user %s is not on channel %s", target->nick.c_str(), channel->name.c_str()));
			return CMD_FAILURE;
		}

		if (target->server->IsULine())
		{
			user->WriteNumeric(ERR_CHANOPRIVSNEEDED, channame, "Only a u-line may remove a u-line from a channel.");
			return CMD_FAILURE;
		}

		/* We support the +Q channel mode via. the m_nokicks module, if the module is loaded and the mode is set then disallow the /remove */
		if ((!IS_LOCAL(user)) || (!supportnokicks) || (!channel->IsModeSet(nokicksmode)))
		{
			/* We'll let everyone remove their level and below, eg:
			 * ops can remove ops, halfops, voices, and those with no mode (no moders actually are set to 1)
			  a ulined target will get a higher level than it's possible for a /remover to get..so they're safe.
			 * Nobody may remove people with >= protectedrank rank.
			 */
			unsigned int ulevel = channel->GetPrefixValue(user);
			unsigned int tlevel = channel->GetPrefixValue(target);
			if ((!IS_LOCAL(user)) || ((ulevel > VOICE_VALUE) && (ulevel >= tlevel) && ((protectedrank == 0) || (tlevel < protectedrank))))
			{
				// REMOVE will be sent to the target's server and it will reply with a PART (or do nothing if it doesn't understand the command)
				if (!IS_LOCAL(target))
				{
					// Send an ENCAP REMOVE with parameters being in the old <user> <chan> order which is
					// compatible with both 2.0 and 3.0. This also turns FPART into REMOVE.
					CommandBase::Params p;
					p.push_back(target->uuid);
					p.push_back(channel->name);
					if (parameters.size() > 2)
						p.push_back(":" + parameters[2]);
					ServerInstance->PI->SendEncapsulatedData(target->server->GetName(), "REMOVE", p, user);

					return CMD_SUCCESS;
				}

				std::string reasonparam;

				/* If a reason is given, use it */
				if(parameters.size() > 2)
					reasonparam = parameters[2];
				else
					reasonparam = "No reason given";

				/* Build up the part reason string. */
				reason = "Removed by " + user->nick + ": " + reasonparam;

				channel->WriteNotice(InspIRCd::Format("%s removed %s from the channel", user->nick.c_str(), target->nick.c_str()));
				target->WriteNotice("*** " + user->nick + " removed you from " + channel->name + " with the message: " + reasonparam);

				channel->PartUser(target, reason);
			}
			else
			{
				user->WriteNotice(InspIRCd::Format("*** You do not have access to /remove %s from %s", target->nick.c_str(), channel->name.c_str()));
				return CMD_FAILURE;
			}
		}
		else
		{
			/* m_nokicks.so was loaded and +Q was set, block! */
			user->WriteNumeric(ERR_RESTRICTED, channel->name, InspIRCd::Format("Can't remove user %s from channel (nokicks mode is set)", target->nick.c_str()));
			return CMD_FAILURE;
		}

		return CMD_SUCCESS;
	}