<?php
/**
 * Procesa mensajes que se encuentran en el protocolo IRC/Parse message that we can found in the protocol
 *
 * @author     Sinfocol
 * @copyright  2009 www.sinfocol.org
 * @license    http://www.sinfocol.org/disclaimer/
 * @version    Release: 1.0.0
 * @link       http://www.sinfocol.org/2009/06/thewalrusbot-un-cliente-irc-sencillo-en-php/
 * @since      Class available since Release 1.0.0
 */
class IrcParser{

    
/**
     * Procesa el mensaje en crudo del protocolo IRC/Parse the raw message of the protocol
     * @param string $string Cadena a analizar/String to parse
     * @return array Array(raw, prefix, servername, nickname, user, host, command, params)
     */
    
public function parse($string){
        
$elem null;
        
$message null;

        
$nickname '[\-\d\x41-\x7d]+';
        
$user '[\x01-\x09\x0b-\x0c\x0e-\x1f\x21-\x3f\x41-\xff]+';
        
$oct  '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9])';
        
$ipv4 "($oct\.){3}$oct|([[:xdigit:]]:){3}[[:xdigit:]]";
        
$ipv6 "([[:xdigit:]]{1,4}:){7}[[:xdigit:]]{1,4}";
        
$host "([[:alnum:]]([[:alnum:]\-]{0,61}[[:alnum:]])?\.)+[[:alpha:]]{2,6}|$ipv4|$ipv6|[\w\-\.\/]+";

        
//prefix     =  servername | ( nickname [ [ "!" user ] "@" host ] )
        
$prefix "(?<prefix>:((?<nickname>$nickname)((!(?<user>$user))?@(?<host>$host))?|(?<servername>[\S]+))\s)?";

        
//command    =  1*letter | 3digit
        
$command '(?<command>([a-zA-Z]+|\d{3}){1})';

        
//nospcrlfcl =  %x01-09 | %x0B-0C | %x0E-1F | %x21-39 | %x3B-FF; any octet except NUL, CR, LF, " " and ":"
        
$nospcrlfcl '([\x01-\x09\x0b-\x0c\x0e-\x1f\x21-\x39\x3b-\xff])';
        
//middle     =  nospcrlfcl *( ":" | nospcrlfcl )
        
$middle "($nospcrlfcl+(:|$nospcrlfcl)*)";
        
//trailing   =  *( ":" | " " | nospcrlfcl )
        
$trailing "(:|\s|$nospcrlfcl)*";
        
//params     =  *14( SPACE middle ) [ SPACE ":" trailing ] | 14( SPACE middle ) [ SPACE [ ":" ] trailing ]
        
$params "((?<middle>\s($middle{1,14}))?(?<trailing>\s:$trailing$)?|((?<middle2>(\s$middle{14}))(?<trailing2>\s:?$trailing$)?))";


        
//message    =  [ ":" prefix SPACE ] command [ params ] crlf
        //El mensaje se compone por un prefijo que es opcional, un comando que siempre es requerido y unos parámetros, finalizando con \r\n (Retorno de carro y avance de línea)
        //The message is composed by an optional prefix, a command that always is required and the parameters, ending with \r\n (Carriage return and line feed)
        
$regex "/^{$prefix}{$command}(?<params>.*)(\r\n)+/";

        
//Cada elemento del mensaje en crudo es almacenado en $elem
        //Each element of the raw message is stored in $elem
        
preg_match($regex$string$elem);

        
/**
         * El mensaje/The message
         * raw = Es el mensaje en crudo que llegó del servidor o es enviado por el cliente/Is the raw message that arrives from the server or was sent by the client
         * prefix = Es el prefijo, contiene el nombre del servidor, nickname, usuario y host del usuario/Is the prefix, it contains the server name, nickname, user and the user host
         *          servername = Nombre del servidor/Server name
         *          nickname   = Contiene el nick (Nick que está hablando en el canal o enviando mensajes privados)/It contains the nick (Nick that is talking on the channel or sending private messages)
         *                       user = Nombre de usuario del nick/User name of the nick
         *                       host = Host del nick/Host of the nick
         * command = Es el comando, tales como PING, PRIVMSG, MODE, entre otros/It is the command, such as PING, PRIVMSG, MODE, etc.
         * params = Parámetros que se envian con los diferentes comandos/Parameters that are sent with the various commands
         *          middle = Son todos los parámetros que se encuentran en la mitad del mensaje/They are all the messages that is in the middle of the message
         *          trailing = Es la última cadena que se encuentra en el mensaje/It is the las string that is in the message
         */
        
$message['raw']        = $string;
        
$message['prefix']     = $elem['prefix'];
        
$message['servername'] = $elem['servername'];
        
$message['nickname']   = $elem['nickname'];
        
$message['user']       = $elem['user'];
        
$message['host']       = $elem['host'];
        
$message['command']    = $elem['command'];
        
$message['params']     = $elem['params'];

        
preg_match_all($params$elem['params'], $elem);

        
$middle NULL;
        for(
$z=0$z<count($elem['middle']); $z++){
            if( 
$elem['middle'][$z] != ''$middle[] = trim($elem['middle'][$z]);
        }
        
$message['middle'] = $middle;

        
$middle NULL;
        for(
$z=0$z<count($elem['middle2']); $z++){
            if( 
$elem['middle2'][$z] != ''$middle[] = trim($elem['middle2'][$z]);
        }
        
$message['middle2'] = $middle;

        
$trailing '';
        for(
$z=0$z<count($elem['trailing']); $z++){
            if( 
$elem['trailing'][$z] != ''){
                
$trailing substr(trim($elem['trailing'][$z]), 1);
                break;
            }
        }
        
$message['trailing'] = $trailing;

        
$trailing '';
        for(
$z=0$z<count($elem['trailing2']); $z++){
            if( 
$elem['trailing2'][$z] != ''){
                
$trailing trim($elem['trailing2'][$z]);
                break;
            }
        }
        
$message['trailing2'] = $trailing;

        return 
$message;
    }
}