Esempio n. 1
0
static void handle_ctcp_request(irc_session_t *session, irc_parser_result_t *result) {
    char ctcp_buf[LIBIRC_BUFFER_SIZE];
    char **params = result->params;
    size_t msglen = strlen(result->params[1]);

    msglen -= 2;
    if (msglen > sizeof (ctcp_buf) - 1)
        msglen = sizeof (ctcp_buf) - 1;

    memcpy(ctcp_buf, params[1] + 1, msglen);
    ctcp_buf[msglen] = '\0';
    DBG_OK("ctcp req recvd! %s", ctcp_buf);

    if (is_dcc_request(ctcp_buf)) {
        libirc_dcc_request(session, result, ctcp_buf);
    }
    else if (is_action_message(ctcp_buf) && session->callbacks.event_ctcp_action) {
        // this removes "ACTION" in front of the message
        char *buf = calloc(strlen(ctcp_buf)+1, sizeof(char));
        memcpy(buf, ctcp_buf+7, strlen(ctcp_buf)-7);
        params[1] = buf; 
        result->num_params = 2;

        (*session->callbacks.event_ctcp_action) (session, "ACTION", result);
    }
    else {
        char *buf = calloc(strlen(ctcp_buf)+1, sizeof(char));
        memcpy(buf, ctcp_buf, strlen(ctcp_buf));
        params[0] = buf;
        result->num_params = 1;

        if (session->callbacks.event_ctcp_req)
            (*session->callbacks.event_ctcp_req) (session, "CTCP", result);
    }
}
static void libirc_process_incoming_data (irc_session_t * session, int process_length)
{
	#define MAX_PARAMS_ALLOWED 10
	char buf[2*512], *p, *s;
	const char * command = 0, *prefix = 0, *params[MAX_PARAMS_ALLOWED+1];
	int code = 0, paramindex = 0;

	if ( process_length > (int)sizeof(buf) )
		abort(); // should be impossible

	memcpy (buf, session->incoming_buf, process_length);
	buf[process_length] = '\0';

	memset (params, 0, sizeof(params));
	p = buf;

    /*
     * From RFC 1459:
	 *  <message>  ::= [':' <prefix> <SPACE> ] <command> <params> <crlf>
	 *  <prefix>   ::= <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
	 *  <command>  ::= <letter> { <letter> } | <number> <number> <number>
	 *  <SPACE>    ::= ' ' { ' ' }
	 *  <params>   ::= <SPACE> [ ':' <trailing> | <middle> <params> ]
	 *  <middle>   ::= <Any *non-empty* sequence of octets not including SPACE
	 *                 or NUL or CR or LF, the first of which may not be ':'>
	 *  <trailing> ::= <Any, possibly *empty*, sequence of octets not including
	 *                   NUL or CR or LF>
 	 */

	// Parse <prefix>
	if ( buf[0] == ':' )
	{
		while ( *p && *p != ' ')
			p++;

		*p++ = '\0';

		// we use buf+1 to skip the leading colon
		prefix = buf + 1;

		// If LIBIRC_OPTION_STRIPNICKS is set, we should 'clean up' nick
		// right here
		if ( session->options & LIBIRC_OPTION_STRIPNICKS )
		{
			for ( s = buf + 1; *s; ++s )
			{
				if ( *s == '@' || *s == '!' )
				{
					*s = '\0';
					break;
				}
			}
		}
	}

	// Parse <command>
	if ( isdigit (p[0]) && isdigit (p[1]) && isdigit (p[2]) )
	{
		p[3] = '\0';
		code = atoi (p);
		p += 4;
	}
	else
	{
		s = p;

		while ( *p && *p != ' ')
			++p;

		*p++ = '\0';

		command = s;
	}

	// Parse middle/params
	while ( *p &&  paramindex < MAX_PARAMS_ALLOWED )
	{
		// beginning from ':', this is the last param
		if ( *p == ':' )
		{
			params[paramindex++] = p + 1; // skip :
			break;
		}

		// Just a param
		for ( s = p; *p && *p != ' '; ++p )
			;

		params[paramindex++] = s;

		if ( !*p )
			break;

		*p++ = '\0';
	}

	// Handle PING/PONG
	if ( command && !strcmp (command, "PING") && params[0] )
	{
		irc_send_raw (session, "PONG %s", params[0]);
		return;
	}

	// and dump
	if ( code )
	{
		// We use session->motd_received to check whether it is the first
		// RPL_ENDOFMOTD or ERR_NOMOTD after the connection.
		if ( (code == 376 || code == 422) && !session->motd_received )
		{
			session->motd_received = 1;

			if ( session->callbacks.event_connect )
				(*session->callbacks.event_connect) (session, "CONNECT", prefix, params, paramindex);
		}

		if ( session->callbacks.event_numeric )
			(*session->callbacks.event_numeric) (session, code, prefix, params, paramindex);
	}
	else
	{
		if ( !strcmp (command, "NICK") )
		{
			/*
			 * If we're changed our nick, we should save it.
             */
			char nickbuf[256];

			irc_target_get_nick (prefix, nickbuf, sizeof(nickbuf));

			if ( !strcmp (nickbuf, session->nick) && paramindex > 0 )
			{
				free (session->nick);
				session->nick = strdup (params[0]);
			}

			if ( session->callbacks.event_nick )
				(*session->callbacks.event_nick) (session, command, prefix, params, paramindex);
		}
		else if ( !strcmp (command, "QUIT") )
		{
			if ( session->callbacks.event_quit )
				(*session->callbacks.event_quit) (session, command, prefix, params, paramindex);
		}
		else if ( !strcmp (command, "JOIN") )
		{
			if ( session->callbacks.event_join )
				(*session->callbacks.event_join) (session, command, prefix, params, paramindex);
		}
		else if ( !strcmp (command, "PART") )
		{
			if ( session->callbacks.event_part )
				(*session->callbacks.event_part) (session, command, prefix, params, paramindex);
		}
		else if ( !strcmp (command, "MODE") )
		{
			if ( paramindex > 0 && !strcmp (params[0], session->nick) )
			{
				params[0] = params[1];
				paramindex = 1;

				if ( session->callbacks.event_umode )
					(*session->callbacks.event_umode) (session, command, prefix, params, paramindex);
			}
			else
			{
				if ( session->callbacks.event_mode )
					(*session->callbacks.event_mode) (session, command, prefix, params, paramindex);
			}
		}
		else if ( !strcmp (command, "TOPIC") )
		{
			if ( session->callbacks.event_topic )
				(*session->callbacks.event_topic) (session, command, prefix, params, paramindex);
		}
		else if ( !strcmp (command, "KICK") )
		{
			if ( session->callbacks.event_kick )
				(*session->callbacks.event_kick) (session, command, prefix, params, paramindex);
		}
		else if ( !strcmp (command, "PRIVMSG") )
		{
			if ( paramindex > 1 )
			{
				unsigned int msglen = strlen (params[1]);

				/*
				 * Check for CTCP request (a CTCP message starts from 0x01
				 * and ends by 0x01
                 */
				if ( params[1][0] == 0x01 && params[1][msglen-1] == 0x01 )
				{
					char ctcp_buf[ 128 ];
                    memset( ctcp_buf, 0, 128 );

					msglen -= 2;
					if ( msglen > sizeof(ctcp_buf) - 1 )
						msglen = sizeof(ctcp_buf) - 1;

					memcpy (ctcp_buf, params[1] + 1, msglen);
					ctcp_buf[msglen] = '\0';

					if ( strstr(ctcp_buf, "DCC ") == ctcp_buf )
						libirc_dcc_request (session, prefix, ctcp_buf);
					else if ( strstr(ctcp_buf, "ACTION ") == ctcp_buf
					&& session->callbacks.event_ctcp_action )
					{
						params[0] = ctcp_buf + 7; // the length of "ACTION "
						paramindex = 1;

						(*session->callbacks.event_ctcp_action) (session, "ACTION", prefix, params, paramindex);
					}
					else
					{
						params[0] = ctcp_buf;
						paramindex = 1;

						if ( session->callbacks.event_ctcp_req )
							(*session->callbacks.event_ctcp_req) (session, "CTCP", prefix, params, paramindex);
					}
				}
				else if ( !strcmp (params[0], session->nick) )
				{
					if ( session->callbacks.event_privmsg )
						(*session->callbacks.event_privmsg) (session, command, prefix, params, paramindex);
				}
				else
				{
					if ( session->callbacks.event_channel )
						(*session->callbacks.event_channel) (session, command, prefix, params, paramindex);
				}
			}
		}
		else if ( !strcmp (command, "NOTICE") )
		{
			unsigned int msglen = strlen (params[1]);

			/*
			 * Check for CTCP request (a CTCP message starts from 0x01
			 * and ends by 0x01
             */
			if ( paramindex > 1 && params[1][0] == 0x01 && params[1][msglen-1] == 0x01 )
			{
				char ctcp_buf[512];

				msglen -= 2;
				if ( msglen > sizeof(ctcp_buf) - 1 )
					msglen = sizeof(ctcp_buf) - 1;

				memcpy (ctcp_buf, params[1] + 1, msglen);
				ctcp_buf[msglen] = '\0';

				params[0] = ctcp_buf;
				paramindex = 1;

				if ( session->callbacks.event_ctcp_rep )
					(*session->callbacks.event_ctcp_rep) (session, "CTCP", prefix, params, paramindex);
			}
			else
			{
				if ( session->callbacks.event_notice )
					(*session->callbacks.event_notice) (session, command, prefix, params, paramindex);
			}
		}
		else if ( !strcmp (command, "INVITE") )
		{
			if ( session->callbacks.event_invite )
				(*session->callbacks.event_invite) (session, command, prefix, params, paramindex);
		}
		else if ( !strcmp (command, "KILL") )
		{
			; /* ignore this event - not all servers generate this */
		}
	 	else
	 	{
			/*
			 * The "unknown" event is triggered upon receipt of any number of
			 * unclassifiable miscellaneous messages, which aren't handled by
			 * the library.
			 */

			if ( session->callbacks.event_unknown )
				(*session->callbacks.event_unknown) (session, command, prefix, params, paramindex);
		}
	}
}