X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcommands%2Fcmd_nick.cpp;h=bdaff8723d62364ba66323762d44a155db613022;hb=6d03943426dcce76ba66567a9b18425a5ebb4c0c;hp=a83d0d80011fbf9eeedbc4fa392f08f43b5517fa;hpb=b3ea96554e5334c27030c14b72ea1c69c253bde0;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/commands/cmd_nick.cpp b/src/commands/cmd_nick.cpp index a83d0d800..bdaff8723 100644 --- a/src/commands/cmd_nick.cpp +++ b/src/commands/cmd_nick.cpp @@ -2,8 +2,8 @@ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * - * InspIRCd: (C) 2002-2008 InspIRCd Development Team - * See: http://www.inspircd.org/wiki/index.php/Credits + * InspIRCd: (C) 2002-2009 InspIRCd Development Team + * See: http://wiki.inspircd.org/Credits * * This program is free but copyrighted software; see * the file COPYING for details. @@ -13,12 +13,26 @@ #include "inspircd.h" #include "xline.h" -#include "commands/cmd_nick.h" -extern "C" DllExport Command* init_command(InspIRCd* Instance) +/** Handle /NICK. These command handlers can be reloaded by the core, + * and handle basic RFC1459 commands. Commands within modules work + * the same way, however, they can be fully unloaded, where these + * may not. + */ +class CommandNick : public Command { - return new CommandNick(Instance); -} + public: + /** Constructor for nick. + */ + CommandNick ( Module* parent) : Command(parent,"NICK", 1, 1) { works_before_reg = true; syntax = ""; Penalty = 3; } + /** Handle command. + * @param parameters The parameters to the comamnd + * @param pcnt The number of parameters passed to teh command + * @param user The user issuing the command + * @return A value from CmdResult to indicate command success or failure. + */ + CmdResult Handle(const std::vector& parameters, User *user); +}; /** Handle nick changes from users. * NOTE: If you are used to ircds based on ircd2.8, and are looking @@ -27,7 +41,7 @@ extern "C" DllExport Command* init_command(InspIRCd* Instance) */ CmdResult CommandNick::Handle (const std::vector& parameters, User *user) { - char oldnick[NICKMAX]; + std::string oldnick; if (parameters[0].empty()) { @@ -36,19 +50,18 @@ CmdResult CommandNick::Handle (const std::vector& parameters, User return CMD_FAILURE; } - if (((!ServerInstance->IsNick(parameters[0].c_str()))) && (IS_LOCAL(user))) + if (((!ServerInstance->IsNick(parameters[0].c_str(), ServerInstance->Config->Limits.NickMax))) && (IS_LOCAL(user))) { - if (!allowinvalid) + if (!User::NICKForced.get(user)) { if (parameters[0] == "0") { // Special case, Fake a /nick UIDHERE. Useful for evading "ERR: NICK IN USE" on connect etc. std::vector p2; - std::deque dummy; p2.push_back(user->uuid); - this->HandleInternal(1, dummy); + User::NICKForced.set(user, 1); this->Handle(p2, user); - this->HandleInternal(0, dummy); + User::NICKForced.set(user, 0); return CMD_SUCCESS; } @@ -57,24 +70,26 @@ CmdResult CommandNick::Handle (const std::vector& parameters, User } } - if (irc::string(user->nick.c_str()) == assign(parameters[0])) + if (assign(user->nick) == parameters[0]) { /* If its exactly the same, even case, dont do anything. */ if (parameters[0] == user->nick) + { return CMD_SUCCESS; + } /* Its a change of case. People insisted that they should be * able to do silly things like this even though the RFC says * the nick AAA is the same as the nick aaa. */ - strlcpy(oldnick, user->nick.c_str(), NICKMAX - 1); - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user,parameters[0].c_str())); - if (MOD_RESULT) + oldnick.assign(user->nick, 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF); + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnUserPreNick, MOD_RESULT, (user,parameters[0])); + if (MOD_RESULT == MOD_RES_DENY) return CMD_FAILURE; if (user->registered == REG_ALL) user->WriteCommon("NICK %s",parameters[0].c_str()); - user->nick.assign(parameters[0], 0, NICKMAX - 1); + user->nick.assign(parameters[0], 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF); user->InvalidateCache(); FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick)); return CMD_SUCCESS; @@ -89,15 +104,32 @@ CmdResult CommandNick::Handle (const std::vector& parameters, User * Also don't check Q:Lines for remote nickchanges, they should have our Q:Lines anyway to enforce themselves. * -- w00t */ - if (!allowinvalid || !IS_LOCAL(user)) + if (!IS_LOCAL(user)) { XLine* mq = ServerInstance->XLines->MatchesLine("Q",parameters[0]); if (mq) { - ServerInstance->SNO->WriteToSnoMask('x', "Q-Lined nickname %s from %s!%s@%s: %s", parameters[0].c_str(), user->nick.c_str(), user->ident.c_str(), user->host, mq->reason); - user->WriteNumeric(432, "%s %s :Invalid nickname: %s",user->nick.c_str(), parameters[0].c_str(), mq->reason); + if (user->registered == REG_ALL) + { + ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s!%s@%s: %s", + parameters[0].c_str(), user->nick.c_str(), user->ident.c_str(), user->host.c_str(), mq->reason.c_str()); + } + user->WriteNumeric(432, "%s %s :Invalid nickname: %s",user->nick.c_str(), parameters[0].c_str(), mq->reason.c_str()); return CMD_FAILURE; } + + if (ServerInstance->Config->RestrictBannedUsers) + { + for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++) + { + Channel *chan = *i; + if (chan->GetPrefixValue(user) < VOICE_VALUE && 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; + } + } + } } /* @@ -118,7 +150,7 @@ CmdResult CommandNick::Handle (const std::vector& parameters, User InUse->WriteTo(InUse, "NICK %s", InUse->uuid.c_str()); InUse->WriteNumeric(433, "%s %s :Nickname overruled.", InUse->nick.c_str(), InUse->nick.c_str()); InUse->UpdateNickHash(InUse->uuid.c_str()); - InUse->nick.assign(InUse->uuid, 0, NICKMAX - 1); + InUse->nick.assign(InUse->uuid, 0, IS_LOCAL(InUse) ? ServerInstance->Config->Limits.NickMax : MAXBUF); InUse->InvalidateCache(); InUse->registered &= ~REG_NICK; } @@ -132,16 +164,16 @@ CmdResult CommandNick::Handle (const std::vector& parameters, User } - int MOD_RESULT = 0; - FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(user, parameters[0])); - if (MOD_RESULT) + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnUserPreNick, MOD_RESULT, (user, parameters[0])); + if (MOD_RESULT == MOD_RES_DENY) // if a module returns true, the nick change is silently forbidden. return CMD_FAILURE; if (user->registered == REG_ALL) user->WriteCommon("NICK %s", parameters[0].c_str()); - strlcpy(oldnick, user->nick.c_str(), NICKMAX - 1); + oldnick.assign(user->nick, 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF); /* change the nick of the user in the users_hash */ user = user->UpdateNickHash(parameters[0].c_str()); @@ -150,43 +182,33 @@ CmdResult CommandNick::Handle (const std::vector& parameters, User if (!user) return CMD_FAILURE; - user->nick.assign(parameters[0], 0, NICKMAX - 1); + user->nick.assign(parameters[0], 0, IS_LOCAL(user) ? ServerInstance->Config->Limits.NickMax : MAXBUF); user->InvalidateCache(); - /* Update display nicks */ - for (UCListIter v = user->chans.begin(); v != user->chans.end(); v++) - { - CUList* ulist = v->first->GetUsers(); - CUList::iterator i = ulist->find(user); - if (i != ulist->end()) - i->second = user->nick; - } - if (user->registered < REG_NICKUSER) { user->registered = (user->registered | REG_NICK); + if (user->registered == REG_NICKUSER) + { + /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ + FIRST_MOD_RESULT(OnUserRegister, MOD_RESULT, (user)); + if (MOD_RESULT == MOD_RES_DENY) + return CMD_FAILURE; + + // return early to not penalize new users + return CMD_SUCCESS; + } } - if (user->registered == REG_NICKUSER) - { - /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ - MOD_RESULT = 0; - FOREACH_RESULT(I_OnUserRegister,OnUserRegister(user)); - if (MOD_RESULT > 0) - return CMD_FAILURE; - } + if (user->registered == REG_ALL) { user->IncreasePenalty(10); - FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user,oldnick)); + FOREACH_MOD(I_OnUserPostNick,OnUserPostNick(user, oldnick)); } return CMD_SUCCESS; } -CmdResult CommandNick::HandleInternal(const unsigned int id, const std::deque&) -{ - allowinvalid = (id != 0); - return CMD_SUCCESS; -} +COMMAND_INIT(CommandNick)