*/
#include "inspircd.h"
-#include "configreader.h"
-#include "channels.h"
-#include "users.h"
#include <stdarg.h>
#include "socketengine.h"
#include "wildcard.h"
void userrec::DecrementModes()
{
- for (int n = 0; n < 64; n++)
+ ServerInstance->Log(DEBUG,"DecrementModes()");
+ for (unsigned char n = 'A'; n <= 'z'; n++)
{
- if (modes[n])
+ if (modes[n-65])
{
- ModeHandler* mh = ServerInstance->Modes->FindMode(n+65, MODETYPE_USER);
+ ServerInstance->Log(DEBUG,"DecrementModes() found mode %c", n);
+ ModeHandler* mh = ServerInstance->Modes->FindMode(n, MODETYPE_USER);
if (mh)
+ {
+ ServerInstance->Log(DEBUG,"Found handler %c and call ChangeCount", n);
mh->ChangeCount(-1);
+ }
}
}
}
-userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance)
+userrec::userrec(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance)
{
*password = *nick = *ident = *host = *dhost = *fullname = *awaymsg = *oper = *uuid = 0;
server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName);
memset(snomasks,0,sizeof(snomasks));
/* Invalidate cache */
operquit = cached_fullhost = cached_hostip = cached_makehost = cached_fullrealhost = NULL;
+
+ if (uid.empty())
+ strlcpy(uuid, Instance->GetUID().c_str(), UUID_LENGTH);
+ else
+ strlcpy(uuid, uid.c_str(), UUID_LENGTH);
+
+ ServerInstance->Log(DEBUG,"New UUID for user: %s (%s)", uuid, uid.empty() ? "allocated new" : "used remote");
+
+ user_hash::iterator finduuid = Instance->uuidlist->find(uuid);
+ if (finduuid == Instance->uuidlist->end())
+ (*Instance->uuidlist)[uuid] = this;
+ else
+ throw CoreException("Duplicate UUID "+std::string(uuid)+" in userrec constructor");
}
void userrec::RemoveCloneCounts()
}
#endif
}
+
+ ServerInstance->uuidlist->erase(uuid);
}
char* userrec::MakeHost()
// unset their oper type (what IS_OPER checks), and remove +o
*this->oper = 0;
this->modes[UM_OPERATOR] = 0;
-
- // remove them from the opers list.
- for (std::vector<userrec*>::iterator a = ServerInstance->all_opers.begin(); a < ServerInstance->all_opers.end(); a++)
- {
- if (*a == this)
- {
- ServerInstance->all_opers.erase(a);
- return;
- }
- }
+
+ // remove the user from the oper list. Will remove multiple entries as a safeguard against bug #404
+ ServerInstance->all_opers.remove(this);
}
}
/* add a client connection to the sockets list */
void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, int socketfamily, sockaddr* ip)
{
- std::string tempnick = Instance->GetUID();
+ /* NOTE: Calling this one parameter constructor for userrec automatically
+ * allocates a new UUID and places it in the hash_map.
+ */
+ userrec* New = NULL;
+ try
+ {
+ New = new userrec(Instance);
+ }
+ catch (...)
+ {
+ Instance->Log(DEFAULT,"*** WTF *** Duplicated UUID! -- Crack smoking monkies have been unleashed.");
+ Instance->WriteOpers("*** WARNING *** Duplicate UUID allocated!");
+ return;
+ }
+
+ int j = 0;
+
+ Instance->unregistered_count++;
- Instance->Log(DEBUG,"New client has UID %s ..", tempnick.c_str());
- user_hash::iterator iter = Instance->clientlist->find(tempnick);
char ipaddr[MAXBUF];
#ifdef IPV6
if (socketfamily == AF_INET6)
else
#endif
inet_ntop(AF_INET, &((const sockaddr_in*)ip)->sin_addr, ipaddr, sizeof(ipaddr));
- userrec* New;
- int j = 0;
- Instance->unregistered_count++;
+ (*(Instance->clientlist))[New->uuid] = New;
+ New->SetFd(socket);
- /*
- * fix by brain.
- * as these nicknames are 'RFC impossible', we can be sure nobody is going to be
- * using one as a registered connection. As they are per fd, we can also safely assume
- * that we wont have collisions. Therefore, if the nick exists in the list, its only
- * used by a dead socket, erase the iterator so that the new client may reclaim it.
- * this was probably the cause of 'server ignores me when i hammer it with reconnects'
- * issue in earlier alphas/betas
- */
- if (iter != Instance->clientlist->end())
- {
- userrec* goner = iter->second;
- DELETE(goner);
- Instance->clientlist->erase(iter);
- }
-
- New = new userrec(Instance);
- (*(Instance->clientlist))[tempnick] = New;
- New->fd = socket;
- strlcpy(New->nick, tempnick.c_str(), NICKMAX - 1);
- strlcpy(New->uuid, tempnick.c_str(), UUID_LENGTH);
+ /* The users default nick is their UUID */
+ strlcpy(New->nick, New->uuid, NICKMAX - 1);
New->server = Instance->FindServerNamePtr(Instance->Config->ServerName);
/* We don't need range checking here, we KNOW 'unknown\0' will fit into the ident field. */
if (this->registered == REG_ALL)
{
- return (ServerInstance->Parser->CallHandler("NICK", &newnick, 1, this) == CMD_SUCCESS);
+ std::deque<classbase*> dummy;
+ command_t* nickhandler = ServerInstance->Parser->GetHandler("NICK");
+ if (nickhandler)
+ {
+ nickhandler->HandleInternal(1, dummy);
+ bool result = (ServerInstance->Parser->CallHandler("NICK", &newnick, 1, this) == CMD_SUCCESS);
+ nickhandler->HandleInternal(0, dummy);
+ return result;
+ }
}
return false;
}
try
{
- /* ServerInstance->Log(DEBUG,"C[%d] <- %s", this->GetFd(), text.c_str());
+ /* ServerInstance->Log(DEBUG,"C[%d] O %s", this->GetFd(), text.c_str());
* WARNING: The above debug line is VERY loud, do NOT
* enable it till we have a good way of filtering it
* out of the logs (e.g. 1.2 would be good).