Ejemplo n.º 1
0
GLOBAL bool
IRC_NJOIN( CLIENT *Client, REQUEST *Req )
{
	char nick_in[COMMAND_LEN], nick_out[COMMAND_LEN], *channame, *ptr, modes[8];
	bool is_op, is_voiced;
	CHANNEL *chan;
	CLIENT *c;
	
	assert( Client != NULL );
	assert( Req != NULL );

	if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );

	strlcpy( nick_in, Req->argv[1], sizeof( nick_in ));
	strcpy( nick_out, "" );

	channame = Req->argv[0];
	ptr = strtok( nick_in, "," );
	while( ptr )
	{
		is_op = is_voiced = false;
		
		/* cut off prefixes */
		while(( *ptr == '@' ) || ( *ptr == '+' ))
		{
			if( *ptr == '@' ) is_op = true;
			if( *ptr == '+' ) is_voiced = true;
			ptr++;
		}

		c = Client_Search( ptr );
		if( c )
		{
			Channel_Join( c, channame );
			chan = Channel_Search( channame );
			assert( chan != NULL );
			
			if( is_op ) Channel_UserModeAdd( chan, c, 'o' );
			if( is_voiced ) Channel_UserModeAdd( chan, c, 'v' );

			/* announce to channel... */
			IRC_WriteStrChannelPrefix( Client, chan, c, false, "JOIN :%s", channame );

			/* set Channel-User-Modes */
			strlcpy( modes, Channel_UserModes( chan, c ), sizeof( modes ));
			if( modes[0] )
			{
				/* send modes to channel */
				IRC_WriteStrChannelPrefix( Client, chan, Client, false, "MODE %s +%s %s", channame, modes, Client_ID( c ));
			}

			if( nick_out[0] != '\0' ) strlcat( nick_out, ",", sizeof( nick_out ));
			if( is_op ) strlcat( nick_out, "@", sizeof( nick_out ));
			if( is_voiced ) strlcat( nick_out, "+", sizeof( nick_out ));
			strlcat( nick_out, ptr, sizeof( nick_out ));
		}
		else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, channame );
		
		/* search for next Nick */
		ptr = strtok( NULL, "," );
	}

	/* forward to other servers */
	if( nick_out[0] != '\0' ) IRC_WriteStrServersPrefix( Client, Client_ThisServer( ), "NJOIN %s :%s", Req->argv[0], nick_out );

	return CONNECTED;
} /* IRC_NJOIN */
Ejemplo n.º 2
0
/**
 * Handler for the IRC "JOIN" command.
 *
 * @param Client The client from which this command has been received.
 * @param Req Request structure with prefix and all parameters.
 * @return CONNECTED or DISCONNECTED.
 */
GLOBAL bool
IRC_JOIN( CLIENT *Client, REQUEST *Req )
{
	char *channame, *key = NULL, *flags, *lastkey = NULL, *lastchan = NULL;
	CLIENT *target;
	CHANNEL *chan;

	assert (Client != NULL);
	assert (Req != NULL);

	_IRC_GET_SENDER_OR_RETURN_(target, Req, Client)

	/* Is argument "0"? */
	if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
		return part_from_all_channels(Client, target);

	/* Are channel keys given? */
	if (Req->argc > 1)
		key = strtok_r(Req->argv[1], ",", &lastkey);

	channame = Req->argv[0];
	channame = strtok_r(channame, ",", &lastchan);

	/* Make sure that "channame" is not the empty string ("JOIN :") */
	if (!channame)
		return IRC_WriteErrClient(Client, ERR_NEEDMOREPARAMS_MSG,
					  Client_ID(Client), Req->command);

	while (channame) {
		flags = NULL;

		/* Did the server include channel-user-modes? */
		if (Client_Type(Client) == CLIENT_SERVER) {
			flags = strchr(channame, 0x7);
			if (flags) {
				*flags = '\0';
				flags++;
			}
		}

		chan = Channel_Search(channame);

		/* Local client? */
		if (Client_Type(Client) == CLIENT_USER) {
			if (chan) {
				/* Already existing channel: already member? */
				if (Channel_IsMemberOf(chan, Client))
				    goto join_next;
			} else {
				/* Channel must be created */
				if (!strchr(Conf_AllowedChannelTypes, channame[0])) {
					/* ... but channel type is not allowed! */
					IRC_WriteErrClient(Client,
						ERR_NOSUCHCHANNEL_MSG,
						Client_ID(Client), channame);
					goto join_next;
				}
			}

			/* Test if the user has reached the channel limit */
			if ((Conf_MaxJoins > 0) &&
			    (Channel_CountForUser(Client) >= Conf_MaxJoins)) {
				if (!IRC_WriteErrClient(Client,
						ERR_TOOMANYCHANNELS_MSG,
						Client_ID(Client), channame))
					return DISCONNECTED;
				goto join_next;
			}

			if (chan) {
				/* Already existing channel: check if the
				 * client is allowed to join */
				if (!join_allowed(Client, chan, channame, key))
					goto join_next;
			} else {
				/* New channel: first user will become channel
				 * operator unless this is a modeless channel */
				if (*channame != '+')
					flags = "o";
			}

			/* Local client: update idle time */
			Conn_UpdateIdle(Client_Conn(Client));
		} else {
			/* Remote server: we don't need to know whether the
			 * client is invited or not, but we have to make sure
			 * that the "one shot" entries (generated by INVITE
			 * commands) in this list become deleted when a user
			 * joins a channel this way. */
			if (chan)
				(void)Lists_Check(Channel_GetListInvites(chan),
						  target);
		}

		/* Join channel (and create channel if it doesn't exist) */
		if (!Channel_Join(target, channame))
			goto join_next;

		if (!chan) { /* channel is new; it has been created above */
			chan = Channel_Search(channame);
			assert(chan != NULL);
			if (Channel_IsModeless(chan)) {
				Channel_ModeAdd(chan, 't'); /* /TOPIC not allowed */
				Channel_ModeAdd(chan, 'n'); /* no external msgs */
			}
		}
		assert(chan != NULL);

		join_set_channelmodes(chan, target, flags);

		join_forward(Client, target, chan, channame);

		if (!join_send_topic(Client, target, chan, channame))
			break; /* write error */

	join_next:
		/* next channel? */
		channame = strtok_r(NULL, ",", &lastchan);
		if (channame && key)
			key = strtok_r(NULL, ",", &lastkey);
	}
	return CONNECTED;
} /* IRC_JOIN */