⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_nick.c

📁 Unreal irc 服务器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		 */#ifdef GUEST		if (IsUnknown(sptr))		{			RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv);			return 0;		}#endif		sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),		    /* parv[0] is empty when connecting */		    me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);		return 0;	/* NICK message ignored */	}	/*	   ** NICK was coming from a server connection.	   ** This means we have a race condition (two users signing on	   ** at the same time), or two net fragments reconnecting with	   ** the same nick.	   ** The latter can happen because two different users connected	   ** or because one and the same user switched server during a	   ** net break.	   ** If we have the old protocol (no TimeStamp and no user@host)	   ** or if the TimeStamps are equal, we kill both (or only 'new'	   ** if it was a "NICK new"). Otherwise we kill the youngest	   ** when user@host differ, or the oldest when they are the same.	   ** --Run	   **	 */	if (IsServer(sptr))	{		/*		   ** A new NICK being introduced by a neighbouring		   ** server (e.g. message type "NICK new" received)		 */		if (parc > 3)		{			lastnick = TS2ts(parv[3]);			if (parc > 5)				differ = (mycmp(acptr->user->username, parv[4])				    || mycmp(acptr->user->realhost, parv[5]));		}		sendto_failops("Nick collision on %s (%s %ld <- %s %ld)",		    acptr->name, acptr->from->name, acptr->lastnick,		    cptr->name, lastnick);		/*		   **    I'm putting the KILL handling here just to make it easier		   ** to read, it's hard to follow it the way it used to be.		   ** Basically, this is what it will do.  It will kill both		   ** users if no timestamp is given, or they are equal.  It will		   ** kill the user on our side if the other server is "correct"		   ** (user@host differ and their user is older, or user@host are		   ** the same and their user is younger), otherwise just kill the		   ** user an reintroduce our correct user.		   **    The old code just sat there and "hoped" the other server		   ** would kill their user.  Not anymore.		   **                                               -- binary		 */		if (!(parc > 3) || (acptr->lastnick == lastnick))		{			ircstp->is_kill++;			sendto_serv_butone(NULL,			    ":%s KILL %s :%s (Nick Collision)",			    me.name, acptr->name, me.name);			acptr->flags |= FLAGS_KILLED;			(void)exit_client(NULL, acptr, &me,			    "Nick collision with no timestamp/equal timestamps");			return 0;	/* We killed both users, now stop the process. */		}		if ((differ && (acptr->lastnick > lastnick)) ||		    (!differ && (acptr->lastnick < lastnick)) || acptr->from == cptr)	/* we missed a QUIT somewhere ? */		{			ircstp->is_kill++;			sendto_serv_butone(cptr,			    ":%s KILL %s :%s (Nick Collision)",			    me.name, acptr->name, me.name);			acptr->flags |= FLAGS_KILLED;			(void)exit_client(NULL, acptr, &me, "Nick collision");			goto nickkilldone;	/* OK, we got rid of the "wrong" user,						   ** now we're going to add the user the						   ** other server introduced.						 */		}		if ((differ && (acptr->lastnick < lastnick)) ||		    (!differ && (acptr->lastnick > lastnick)))		{			/*			 * Introduce our "correct" user to the other server			 */			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",			    me.name, parv[1], me.name);			send_umode(NULL, acptr, 0, SEND_UMODES, buf);			sendto_one_nickcmd(cptr, acptr, buf);			if (acptr->user->away)				sendto_one(cptr, ":%s AWAY :%s", acptr->name,				    acptr->user->away);			send_user_joins(cptr, acptr);			return 0;	/* Ignore the NICK */		}		return 0;	}	else	{		/*		   ** A NICK change has collided (e.g. message type ":old NICK new").		 */		if (parc > 2)			lastnick = TS2ts(parv[2]);		differ = (mycmp(acptr->user->username, sptr->user->username) ||		    mycmp(acptr->user->realhost, sptr->user->realhost));		sendto_failops		    ("Nick change collision from %s to %s (%s %ld <- %s %ld)",		    sptr->name, acptr->name, acptr->from->name, acptr->lastnick,		    sptr->from->name, lastnick);		if (!(parc > 2) || lastnick == acptr->lastnick)		{			ircstp->is_kill += 2;			sendto_serv_butone(NULL,	/* First kill the new nick. */			    ":%s KILL %s :%s (Self Collision)",			    me.name, acptr->name, me.name);			sendto_serv_butone(cptr,	/* Tell my servers to kill the old */			    ":%s KILL %s :%s (Self Collision)",			    me.name, sptr->name, me.name);			sptr->flags |= FLAGS_KILLED;			acptr->flags |= FLAGS_KILLED;			(void)exit_client(NULL, sptr, &me, "Self Collision");			(void)exit_client(NULL, acptr, &me, "Self Collision");			return 0;	/* Now that I killed them both, ignore the NICK */		}		if ((differ && (acptr->lastnick > lastnick)) ||		    (!differ && (acptr->lastnick < lastnick)))		{			/* sptr (their user) won, let's kill acptr (our user) */			ircstp->is_kill++;			sendto_serv_butone(cptr,			    ":%s KILL %s :%s (Nick collision: %s <- %s)",			    me.name, acptr->name, me.name,			    acptr->from->name, sptr->from->name);			acptr->flags |= FLAGS_KILLED;			(void)exit_client(NULL, acptr, &me, "Nick collision");			goto nickkilldone;	/* their user won, introduce new nick */		}		if ((differ && (acptr->lastnick < lastnick)) ||		    (!differ && (acptr->lastnick > lastnick)))		{			/* acptr (our user) won, let's kill sptr (their user),			   ** and reintroduce our "correct" user			 */			ircstp->is_kill++;			/* Kill the user trying to change their nick. */			sendto_serv_butone(cptr,			    ":%s KILL %s :%s (Nick collision: %s <- %s)",			    me.name, sptr->name, me.name,			    sptr->from->name, acptr->from->name);			sptr->flags |= FLAGS_KILLED;			(void)exit_client(NULL, sptr, &me, "Nick collision");			/*			 * Introduce our "correct" user to the other server			 */			/* Kill their user. */			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",			    me.name, parv[1], me.name);			send_umode(NULL, acptr, 0, SEND_UMODES, buf);			sendto_one_nickcmd(cptr, acptr, buf);			if (acptr->user->away)				sendto_one(cptr, ":%s AWAY :%s", acptr->name,				    acptr->user->away);			send_user_joins(cptr, acptr);			return 0;	/* their user lost, ignore the NICK */		}	}	return 0;		/* just in case */      nickkilldone:	if (IsServer(sptr))	{		/* A server introducing a new client, change source */		sptr = make_client(cptr, serv);		add_client_to_list(sptr);		if (parc > 2)			sptr->hopcount = TS2ts(parv[2]);		if (parc > 3)			sptr->lastnick = TS2ts(parv[3]);		else		/* Little bit better, as long as not all upgraded */			sptr->lastnick = TStime();		if (sptr->lastnick < 0)		{			sendto_realops			    ("Negative timestamp recieved from %s, resetting to TStime (%s)",			    cptr->name, backupbuf);			sptr->lastnick = TStime();		}		newusr = 1;	}	else if (sptr->name[0] && IsPerson(sptr))	{		/*		   ** If the client belongs to me, then check to see		   ** if client is currently on any channels where it		   ** is currently banned.  If so, do not allow the nick		   ** change to occur.		   ** Also set 'lastnick' to current time, if changed.		 */		if (MyClient(sptr))		{			for (mp = sptr->user->channel; mp; mp = mp->next)			{				if (!is_skochanop(sptr, mp->chptr) && is_banned(sptr, mp->chptr, BANCHK_NICK))				{					sendto_one(sptr,					    err_str(ERR_BANNICKCHANGE),					    me.name, parv[0],					    mp->chptr->chname);					return 0;				}				if (CHECK_TARGET_NICK_BANS && !is_skochanop(sptr, mp->chptr) && is_banned_with_nick(sptr, mp->chptr, BANCHK_NICK, nick))				{					sendto_one(sptr,					    ":%s 437 %s %s :Cannot change to a nickname banned on channel",					    me.name, parv[0],					    mp->chptr->chname);					return 0;				}				if (!IsOper(sptr) && !IsULine(sptr)				    && mp->chptr->mode.mode & MODE_NONICKCHANGE				    && !is_chanownprotop(sptr, mp->chptr))				{					sendto_one(sptr,					    err_str(ERR_NONICKCHANGE),					    me.name, parv[0],					    mp->chptr->chname);					return 0;				}			}			if (TStime() - sptr->user->flood.nick_t >= NICK_PERIOD)			{				sptr->user->flood.nick_t = TStime();				sptr->user->flood.nick_c = 1;			} else				sptr->user->flood.nick_c++;			sendto_snomask(SNO_NICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",				sptr->name, sptr->user->username, sptr->user->realhost, nick);			RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, sptr, nick);		} else {			if (!IsULine(sptr))				sendto_snomask(SNO_FNICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",					sptr->name, sptr->user->username, sptr->user->realhost, nick);			RunHook3(HOOKTYPE_REMOTE_NICKCHANGE, cptr, sptr, nick);		}		/*		 * Client just changing his/her nick. If he/she is		 * on a channel, send note of change to all clients		 * on that channel. Propagate notice to other servers.		 */		if (mycmp(parv[0], nick) ||		    /* Next line can be removed when all upgraded  --Run */		    (!MyClient(sptr) && parc > 2		    && TS2ts(parv[2]) < sptr->lastnick))			sptr->lastnick = (MyClient(sptr)			    || parc < 3) ? TStime() : TS2ts(parv[2]);		if (sptr->lastnick < 0)		{			sendto_realops("Negative timestamp (%s)", backupbuf);			sptr->lastnick = TStime();		}		add_history(sptr, 1);		sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);		sendto_serv_butone_token(cptr, parv[0], MSG_NICK, TOK_NICK,		    "%s %ld", nick, sptr->lastnick);		if (removemoder)			sptr->umodes &= ~UMODE_REGNICK;	}	else if (!sptr->name[0])	{#ifdef NOSPOOF		/*		 * Client setting NICK the first time.		 *		 * Generate a random string for them to pong with.		 */		sptr->nospoof = getrandom32();		if (PINGPONG_WARNING)			sendto_one(sptr, ":%s NOTICE %s :*** If you are having problems"			    " connecting due to ping timeouts, please"			    " type /quote pong %X or /raw pong %X now.",			    me.name, nick, sptr->nospoof, sptr->nospoof);		sendto_one(sptr, "PING :%X", sptr->nospoof);#endif /* NOSPOOF */#ifdef CONTACT_EMAIL		sendto_one(sptr,		    ":%s NOTICE %s :*** If you need assistance with a"		    " connection problem, please email " CONTACT_EMAIL		    " with the name and version of the client you are"		    " using, and the server you tried to connect to: %s",		    me.name, nick, me.name);#endif /* CONTACT_EMAIL */#ifdef CONTACT_URL		sendto_one(sptr,		    ":%s NOTICE %s :*** If you need assistance with"		    " connecting to this server, %s, please refer to: "		    CONTACT_URL, me.name, nick, me.name);#endif /* CONTACT_URL */		/* Copy password to the passwd field if it's given after NICK		 * - originally by taz, modified by Wizzu		 */		if ((parc > 2) && (strlen(parv[2]) <= PASSWDLEN)		    && !(sptr->listener->umodes & LISTENER_JAVACLIENT))		{			if (sptr->passwd)				MyFree(sptr->passwd);			sptr->passwd = MyMalloc(strlen(parv[2]) + 1);			(void)strcpy(sptr->passwd, parv[2]);		}		/* This had to be copied here to avoid problems.. */		(void)strcpy(sptr->name, nick);		if (sptr->user && IsNotSpoof(sptr))		{			/*			   ** USER already received, now we have NICK.			   ** *NOTE* For servers "NICK" *must* precede the			   ** user message (giving USER before NICK is possible			   ** only for local client connection!). register_user			   ** may reject the client and call exit_client for it			   ** --must test this and exit m_nick too!!!			 */#ifndef NOSPOOF			if (USE_BAN_VERSION && MyConnect(sptr))				sendto_one(sptr, ":IRC!IRC@%s PRIVMSG %s :\1VERSION\1",					me.name, nick);#endif			sptr->lastnick = TStime();	/* Always local client */			if (register_user(cptr, sptr, nick,			    sptr->user->username, NULL, NULL, NULL) == FLUSH_BUFFER)				return FLUSH_BUFFER;			strcpy(nick, sptr->name); /* don't ask, but I need this. do not remove! -- Syzop */			update_watch = 0;			newusr = 1;		}	}	/*	 *  Finally set new nick name.	 */	if (update_watch && sptr->name[0])	{		(void)del_from_client_hash_table(sptr->name, sptr);		if (IsPerson(sptr))			hash_check_watch(sptr, RPL_LOGOFF);	}	(void)strcpy(sptr->name, nick);	(void)add_to_client_hash_table(nick, sptr);	if (IsServer(cptr) && parc > 7)	{		parv[3] = nick;		do_cmd(cptr, sptr, "USER", parc - 3, &parv[3]);		if (GotNetInfo(cptr) && !IsULine(sptr))			sendto_fconnectnotice(sptr->name, sptr->user, sptr, 0, NULL);	}	else if (IsPerson(sptr) && update_watch)		hash_check_watch(sptr, RPL_LOGON);#ifdef NEWCHFLOODPROT	if (sptr->user && !newusr && !IsULine(sptr))	{		for (mp = sptr->user->channel; mp; mp = mp->next)		{			aChannel *chptr = mp->chptr;			if (chptr && !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANPROT)) &&			    chptr->mode.floodprot && do_chanflood(chptr->mode.floodprot, FLD_NICK) && MyClient(sptr))			{				do_chanflood_action(chptr, FLD_NICK, "nick");			}		}		}#endif	if (newusr && !MyClient(sptr) && IsPerson(sptr))	{		RunHook(HOOKTYPE_REMOTE_CONNECT, sptr);	}	return 0;}/*** register_user**	This function is called when both NICK and USER messages**	have been accepted for the client, in whatever order. Only**	after this the USER message is propagated.****	NICK's must be propagated at once when received, although**	it would be better to delay them too until full info is**	available. Doing it is not so simple though, would have**	to implement the following:****	1) user telnets in and gives only "NICK foobar" and waits**	2) another user far away logs in normally with the nick**	   "foobar" (quite legal, as this server didn't propagate**	   it).**	3) now this server gets nick "foobar" from outside, but**	   has already the same defined locally. Current server**	   would just issue "KILL foobar" to clean out dups. But,**	   this is not fair. It should actually request another

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -