X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=418f2c9aa3557f187e45eb189c892a07b154970c;hb=68211809ee3111bdc9609fbd46dc3c875fbb5ea6;hp=0580bf54f91e2424eb8b6dba8b7b12ea5b5a540d;hpb=2c3745edb3013d4ffce393337566a8a58924740b;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index 0580bf54f..418f2c9aa 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -88,12 +88,12 @@ std::string User::ProcessNoticeMasks(const char *sm) this->SetNoticeMask(*c, adding); output += *c; + oldadding = adding; } } else this->WriteNumeric(ERR_UNKNOWNSNOMASK, "%s %c :is unknown snomask char to me", this->nick.c_str(), *c); - oldadding = adding; break; } @@ -219,14 +219,16 @@ User::User(const std::string &uid, const std::string& sid, int type) LocalUser::LocalUser(int myfd, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* servaddr) : User(ServerInstance->GetUID(), ServerInstance->Config->ServerName, USERTYPE_LOCAL), eh(this), + localuseriter(ServerInstance->Users->local_users.end()), bytes_in(0), bytes_out(0), cmds_in(0), cmds_out(0), nping(0), CommandFloodPenalty(0), already_sent(0) { + ident = "unknown"; lastping = 0; eh.SetFd(myfd); - - SetClientIP(client); + memcpy(&client_sa, client, sizeof(irc::sockets::sockaddrs)); memcpy(&server_sa, servaddr, sizeof(irc::sockets::sockaddrs)); + dhost = host = GetIPString(); } User::~User() @@ -453,6 +455,7 @@ void UserIOHandler::OnDataReady() ServerInstance->Users->QuitUser(user, "RecvQ exceeded"); ServerInstance->SNO->WriteToSnoMask('a', "User %s RecvQ of %lu exceeds connect class maximum of %lu", user->nick.c_str(), (unsigned long)recvq.length(), user->MyClass->GetRecvqMax()); + return; } unsigned long sendqmax = ULONG_MAX; if (!user->HasPrivPermission("users/flood/increased-buffers")) @@ -538,11 +541,16 @@ CullResult User::cull() CullResult LocalUser::cull() { - std::vector::iterator x = find(ServerInstance->Users->local_users.begin(),ServerInstance->Users->local_users.end(),this); - if (x != ServerInstance->Users->local_users.end()) - ServerInstance->Users->local_users.erase(x); + // The iterator is initialized to local_users.end() in the constructor. It is + // overwritten in UserManager::AddUser() with the real iterator so this check + // is only a precaution currently. + if (localuseriter != ServerInstance->Users->local_users.end()) + { + ServerInstance->Users->local_count--; + ServerInstance->Users->local_users.erase(localuseriter); + } else - ServerInstance->Logs->Log("USERS", DEBUG, "Failed to remove user from vector"); + ServerInstance->Logs->Log("USERS", DEFAULT, "ERROR: LocalUserIter does not point to a valid entry for " + this->nick); ClearInvites(); eh.cull(); @@ -587,7 +595,7 @@ void User::Oper(OperInfo* info) nick.c_str(), ident.c_str(), host.c_str(), oper->NameStr(), opername.c_str()); this->WriteNumeric(381, "%s :You are now %s %s", nick.c_str(), strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->NameStr()); - ServerInstance->Logs->Log("OPER", DEFAULT, "%s!%s@%s opered as type: %s", this->nick.c_str(), this->ident.c_str(), this->host.c_str(), oper->NameStr()); + ServerInstance->Logs->Log("OPER", DEFAULT, "%s opered as type: %s", GetFullRealHost().c_str(), oper->NameStr()); ServerInstance->Users->all_opers.push_back(this); // Expand permissions from config for faster lookup @@ -622,25 +630,27 @@ void OperInfo::init() AllowedPrivs.insert(mypriv); } - for (unsigned char* c = (unsigned char*)tag->getString("usermodes").c_str(); *c; ++c) + std::string modes = tag->getString("usermodes"); + for (std::string::const_iterator c = modes.begin(); c != modes.end(); ++c) { if (*c == '*') { this->AllowedUserModes.set(); } - else if (*c >= 'A' && *c < 'z') + else if (*c >= 'A' && *c <= 'z') { this->AllowedUserModes[*c - 'A'] = true; } } - for (unsigned char* c = (unsigned char*)tag->getString("chanmodes").c_str(); *c; ++c) + modes = tag->getString("chanmodes"); + for (std::string::const_iterator c = modes.begin(); c != modes.end(); ++c) { if (*c == '*') { this->AllowedChanModes.set(); } - else if (*c >= 'A' && *c < 'z') + else if (*c >= 'A' && *c <= 'z') { this->AllowedChanModes[*c - 'A'] = true; } @@ -771,11 +781,16 @@ void LocalUser::FullConnect() if (quitting) return; - this->WriteServ("NOTICE Auth :Welcome to \002%s\002!",ServerInstance->Config->Network.c_str()); - this->WriteNumeric(RPL_WELCOME, "%s :Welcome to the %s IRC Network %s!%s@%s",this->nick.c_str(), ServerInstance->Config->Network.c_str(), this->nick.c_str(), this->ident.c_str(), this->host.c_str()); - this->WriteNumeric(RPL_YOURHOSTIS, "%s :Your host is %s, running version InspIRCd-2.0",this->nick.c_str(),ServerInstance->Config->ServerName.c_str()); + if (ServerInstance->Config->WelcomeNotice) + this->WriteServ("NOTICE Auth :Welcome to \002%s\002!",ServerInstance->Config->Network.c_str()); + this->WriteNumeric(RPL_WELCOME, "%s :Welcome to the %s IRC Network %s",this->nick.c_str(), ServerInstance->Config->Network.c_str(), GetFullRealHost().c_str()); + this->WriteNumeric(RPL_YOURHOSTIS, "%s :Your host is %s, running version %s",this->nick.c_str(),ServerInstance->Config->ServerName.c_str(),BRANCH); this->WriteNumeric(RPL_SERVERCREATED, "%s :This server was created %s %s", this->nick.c_str(), __TIME__, __DATE__); - this->WriteNumeric(RPL_SERVERVERSION, "%s %s InspIRCd-2.0 %s %s %s", this->nick.c_str(), ServerInstance->Config->ServerName.c_str(), ServerInstance->Modes->UserModeList().c_str(), ServerInstance->Modes->ChannelModeList().c_str(), ServerInstance->Modes->ParaModeList().c_str()); + + std::string umlist = ServerInstance->Modes->UserModeList(); + std::string cmlist = ServerInstance->Modes->ChannelModeList(); + std::string pmlist = ServerInstance->Modes->ParaModeList(); + this->WriteNumeric(RPL_SERVERVERSION, "%s %s %s %s %s %s", this->nick.c_str(), ServerInstance->Config->ServerName.c_str(), BRANCH, umlist.c_str(), cmlist.c_str(), pmlist.c_str()); ServerInstance->Config->Send005(this); this->WriteNumeric(RPL_YOURUUID, "%s %s :your unique ID", this->nick.c_str(), this->uuid.c_str()); @@ -790,13 +805,13 @@ void LocalUser::FullConnect() std::vector parameters; FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true, command)); if (!MOD_RESULT) - ServerInstance->CallCommandHandler(command, parameters, this); + ServerInstance->Parser->CallHandler(command, parameters, this); MOD_RESULT = MOD_RES_PASSTHRU; command = "LUSERS"; FIRST_MOD_RESULT(OnPreCommand, MOD_RESULT, (command, parameters, this, true, command)); if (!MOD_RESULT) - ServerInstance->CallCommandHandler(command, parameters, this); + ServerInstance->Parser->CallHandler(command, parameters, this); if (ServerInstance->Config->RawLog) WriteServ("PRIVMSG %s :*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.", nick.c_str()); @@ -811,8 +826,8 @@ void LocalUser::FullConnect() FOREACH_MOD(I_OnPostConnect,OnPostConnect(this)); - ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d (class %s): %s!%s@%s (%s) [%s]", - this->GetServerPort(), this->MyClass->name.c_str(), this->nick.c_str(), this->ident.c_str(), this->host.c_str(), this->GetIPString(), this->fullname.c_str()); + ServerInstance->SNO->WriteToSnoMask('c',"Client connecting on port %d (class %s): %s (%s) [%s]", + this->GetServerPort(), this->MyClass->name.c_str(), GetFullRealHost().c_str(), this->GetIPString(), this->fullname.c_str()); ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCache: Adding NEGATIVE hit for %s", this->GetIPString()); ServerInstance->BanCache->AddHit(this->GetIPString(), "", ""); // reset the flood penalty (which could have been raised due to things like auto +x) @@ -830,6 +845,12 @@ void User::InvalidateCache() bool User::ChangeNick(const std::string& newnick, bool force) { + if (quitting) + { + ServerInstance->Logs->Log("USERS", DEFAULT, "ERROR: Attempted to change nick of a quitting user: " + this->nick); + return false; + } + ModResult MOD_RESULT; if (force) @@ -867,8 +888,8 @@ bool User::ChangeNick(const std::string& newnick, bool force) { if (this->registered == REG_ALL) { - ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s!%s@%s: %s", - newnick.c_str(), this->nick.c_str(), this->ident.c_str(), this->host.c_str(), mq->reason.c_str()); + ServerInstance->SNO->WriteGlobalSno('a', "Q-Lined nickname %s from %s: %s", + newnick.c_str(), GetFullRealHost().c_str(), mq->reason.c_str()); } this->WriteNumeric(432, "%s %s :Invalid nickname: %s",this->nick.c_str(), newnick.c_str(), mq->reason.c_str()); return false; @@ -957,7 +978,7 @@ const char* User::GetIPString() irc::sockets::satoap(client_sa, cachedip, port); /* IP addresses starting with a : on irc are a Bad Thing (tm) */ if (cachedip.c_str()[0] == ':') - cachedip.insert(0,1,'0'); + cachedip.insert(cachedip.begin(),1,'0'); } return cachedip.c_str(); @@ -978,22 +999,41 @@ irc::sockets::cidr_mask User::GetCIDRMask() return irc::sockets::cidr_mask(client_sa, range); } -bool User::SetClientIP(irc::sockets::sockaddrs *sa) +bool User::SetClientIP(const char* sip, bool recheck_eline) { - memcpy(&client_sa, sa, sizeof(irc::sockets::sockaddrs)); + cachedip.clear(); + cached_hostip.clear(); + return irc::sockets::aptosa(sip, 0, client_sa); +} - return true; +void User::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +{ + cachedip.clear(); + cached_hostip.clear(); + memcpy(&client_sa, &sa, sizeof(irc::sockets::sockaddrs)); } -bool User::SetClientIP(const char* sip) +bool LocalUser::SetClientIP(const char* sip, bool recheck_eline) { irc::sockets::sockaddrs sa; - - this->cachedip = ""; if (!irc::sockets::aptosa(sip, 0, sa)) + // Invalid return false; - return SetClientIP(&sa); + LocalUser::SetClientIP(sa, recheck_eline); + return true; +} + +void LocalUser::SetClientIP(const irc::sockets::sockaddrs& sa, bool recheck_eline) +{ + if (sa != client_sa) + { + User::SetClientIP(sa); + if (recheck_eline) + this->exempt = (ServerInstance->XLines->MatchesLine("E", this) != NULL); + + FOREACH_MOD(I_OnSetUserIP,OnSetUserIP(this)); + } } static std::string wide_newline("\r\n"); @@ -1281,26 +1321,19 @@ void User::SendText(const char *text, ...) void User::SendText(const std::string &LinePrefix, std::stringstream &TextStream) { - char line[MAXBUF]; - int start_pos = LinePrefix.length(); - int pos = start_pos; - memcpy(line, LinePrefix.data(), pos); + std::string line; std::string Word; while (TextStream >> Word) { - int len = Word.length(); - if (pos + len + 12 > MAXBUF) + size_t lineLength = LinePrefix.length() + line.length() + Word.length() + 13; + if (lineLength > MAXBUF) { - line[pos] = '\0'; - SendText(std::string(line)); - pos = start_pos; + SendText(LinePrefix + line); + line.clear(); } - line[pos] = ' '; - memcpy(line + pos + 1, Word.data(), len); - pos += len + 1; + line += " " + Word; } - line[pos] = '\0'; - SendText(std::string(line)); + SendText(LinePrefix + line); } /* return 0 or 1 depending if users u and u2 share one or more common channels @@ -1458,7 +1491,7 @@ bool User::ChangeIdent(const char* newident) std::string quitstr = ":" + GetFullHost() + " QUIT :Changing ident"; - this->ident.assign(newident, 0, ServerInstance->Config->Limits.IdentMax + 1); + this->ident.assign(newident, 0, ServerInstance->Config->Limits.IdentMax); this->InvalidateCache(); @@ -1480,9 +1513,10 @@ void User::SendAll(const char* command, const char* text, ...) snprintf(formatbuffer,MAXBUF,":%s %s $* :%s", this->GetFullHost().c_str(), command, textbuffer); std::string fmt = formatbuffer; - for (std::vector::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); i++) + for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); i++) { - (*i)->Write(fmt); + if ((*i)->registered == REG_ALL) + (*i)->Write(fmt); } } @@ -1508,7 +1542,7 @@ void User::SplitChanList(User* dest, const std::string &cl) { std::string line; std::ostringstream prefix; - std::string::size_type start, pos, length; + std::string::size_type start, pos; prefix << this->nick << " " << dest->nick << " :"; line = prefix.str(); @@ -1516,23 +1550,13 @@ void User::SplitChanList(User* dest, const std::string &cl) for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1) { - length = (pos == std::string::npos) ? cl.length() : pos; - - if (line.length() + namelen + length - start > 510) + if (line.length() + namelen + pos - start > 510) { ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str()); line = prefix.str(); } - if(pos == std::string::npos) - { - line.append(cl.substr(start, length - start)); - break; - } - else - { - line.append(cl.substr(start, length - start + 1)); - } + line.append(cl.substr(start, pos - start + 1)); } if (line.length() != prefix.str().length())