Contenido principal

TheWalrusBot: Un cliente IRC sencillo en PHP

Junio 23, 2009

TheWalrusBot es un pequeño cliente realizado en PHP que tiene soporte para las funciones básicas del protocolo IRC, pueden leer todo lo que se refiere a este protocolo en sus respectivos Request For Comments: Arquitectura del IRC (RFC 2810), Administración de Canales (RFC 2811), Protocolo del Cliente (RFC 2812), y Protocolo del servidor (RFC 2813)

El cliente se compone por ahora de cinco archivos, dos de ellos que son solo para demostrar el funcionamiento del cliente (ircCli.php, ircWeb.php), Cliente.php, ClienteBasico.php y el archivo IrcParser.php.
El código fuente de los cinco archivos puede ser descargado de acá: TheWalrusBot Cliente IRC, cada archivo tiene comentado sus funciones y lo que hace precisamente, recomiendo usar Cliente.php ya que este contiene implementado la mayoría de mensajes del protocolo (Algunas con funcionalidad), mientras que ClienteBasico.php como su nombre lo indica, es lo básico del protocolo, no tiene conexión y no responde a PING.

ircCli.php
Es el cliente que se puede correr desde la línea de comandos con el comando:

php ircCli.php -host irc.freenode.org

Ejecutando el comando "php ircCli.php", el programa nos muestra como lo podemos utilizar, sólo es necesario pasarle el parámetro host, los demás parámetros son opcionales.

ircWeb.php
Este cliente puede ser ejecutado vía web, al igual que el anterior archivo solo necesita un parámetro que es el servidor donde se conectará. Podemos ver una muestra de como luce este cliente en este enlace

Cliente.php
Este archivo contiene prácticamente las bases del cliente, tales como la conexión al servidor, la identificación de algunos comandos y respuestas del servidor, la salida y escritura de mensajes, y la escritura en el socket.
Se compone de once atributos públicos (Variables que pueden ser modificadas fuera de la clase) y estos son:
verbose(bool): Determina si se muestra información detallada del funcionamiento del cliente.
veryverbose(bool): Determina si se muestra información muy detallada del funcionamiento del cliente.
log(bool): Con este atributo podemos enviar toda la información a un archivo de registro. verbose o veryverbose deben ser verdaderos.
sep(string): Sirve como separador cuando estamos mostrando o almacenando datos. Por defecto adquiere los valores de "\r\n" cuando lo iniciamos desde CLI o "<br>\r\n" desde web.
servidor(string): Es el nombre del servidor al cual se conectará el cliente.
puerto(integer): Puerto usado en la conexión, por defecto es 6667.
canal(string): El canal al cual ingresará el cliente al tener una conexión exitosa. Se hace luego de que finaliza el mensaje del día (MOTD).
nick(string): El nick que usará el cliente en el IRC. Si el nickname no coincide con la expresión regular '/^[\-\d\x41-\x7d]+$/' entonces se asigna un nick aleatorio de diez carácteres.
clave(string): Clase usada para iniciar la sesión con el servidor IRC, se usa cuando estamos registrados.
nombre(string): Es el nombre real usado en la comunicación. Se usa en el momento de enviar el comando USER.
php(string): Este atributo es delicado, ya que en él podemos almacenar código PHP el cuál se ejecutará luego de que el cliente ha procesado con éxito un mensaje IRC. Se ejecuta en un bloque try..cath con la función eval().

Los atributos privados de Cliente.php son:
version(string): Contiene la versión actual del cliente.
cli(bool): Si el cliente es ejecutado desde la línea de comandos, esta variable será "Verdadera", en otro caso será "Falsa".
archivo(string): Si la variable pública "log" tiene un valor verdadero (log = true), entonces este atributo contendrá el nombre del archivo donde se está guardando el contenido.
umsg(string): Contiene el último mensaje enviado por el cliente. Sirve cuando ha ocurrido un error y deseamos enviar el anterior comando.
logged(bool): Cuando el cliente ha finalizado correctamente la secuencia inicial (PASS, NICK, USER).
encanal(bool): Está en verdadero cuando el cliente se encuentra en un canal.
socket(resource): Es el socket en el que actualmente se encuentra la conexión.

El bloque de código que ejecuta el código PHP configurado en el atributo "php" es:

if( isset($this-&gt;php) ){
    try{
        eval($this-&gt;php);
    }catch(Exception $e){
    }
}

IrcParser.php
Este es el archivo principal de este paquete, ya que es el procesador para los mensajes Irc, lo hice en base al RFC del Protocolo del Cliente (RFC 2812). Una breve explicación.
Cualquier mensaje de IRC sigue este formato: [":" prefijo ESPACIO] [parámetros] CRLF, (la cadena que está entre corchetes es opcional), y donde:
:arrow: El prefijo puede componerse de dos cosas: Nombre de servidor ó nickname [ [ "!" user ] "@" host ]
:arrow: El comando es cualquier cadena o secuencia de tres dígitos. La secuencias de tres dígitos son usadas como respuestas numéricas a los diferentes comandos que proporcionamos.
:arrow: Los parámetros se componen de dos tipos de subparámetros por así decir, los de la mitad, y al parámetro final, cada parámetro de la mitad está separado por espacio, mientras que el parámetro final está separado por un espacio seguido de dos puntos, lo cual permite que el parámetro final contenga espacios.
Cualquier error de lógica o en el mismo diseño de este procesador por favor mandar un correo electrónico a especificando el error.
Esta clase contiene el método parse(), el cual retorna en un Array lo siguiente:
raw = Contiene el mensaje en crudo que se recibió del servidor
prefix = El prefijo
servername = Nombre del servidor
nickname = Nick que se encontró en el prefijo
user = Nombre de usuario del nick
host = Host del nick
command = El comando recibido
params = Contiene la cadena de parámetros sin procesarse
middle = Es un array con los parámetros de la mitad
trailing = Es una cadena que contiene el último parámetro

ClienteBasico.php
Lo anterior fue una explicación a los scripts que realice para evitar el trabajo de estar programando un cliente, en el archivo comprimido se encuentra también el cliente básico, sin algunas implementaciones útiles que se encuentran en Cliente.php. Muy útil para trabajos rápidos. Una forma de usarlo sería:

include('ClienteBasico.php');
$cliente = new Cliente();
$cliente->servidor = 'irc.freenode.org';
$cliente->nick = 'minickxor';
$cliente->php = '
if($irc["command"] == "PING"){
   $this->_out( str_replace("PING", "PONG", $irc["raw"]));
   echo "Respuesta a PING enviada\r\n";
}';
$cliente->conectar();

Podemos apreciar el uso del código PHP, el cual si encuentra que el comando de la cadena procesada es "PING", entonces dirige al socket lo que debería responder, que en este caso es el mismo mensaje recibido pero en vez de "PING" un "PONG", y luego muestra que la respuesta fue enviada.

De nuevo, si alguna duda o error en los script por favor comunicármela vía correo electrónico a o en esta misma publicación.

Archivado en: Miscelaneo, Programación |

7 comentarios

  1. g30rg3_x Junio 23, 2009 @ 8:48 am

    A toda madre...

    Vamos a buscarle bugs =)

    Saludos
    PD: Mi regalo de cumpleaños para cuando? XD

  2. PerverthsO Junio 23, 2009 @ 9:22 am

    hey justo loq que estaba buscando muy buena info gracias man ;)

  3. Persefone Junio 25, 2009 @ 5:33 pm

    Chevere, Chevere!!!

  4. g30rg3_x Noviembre 10, 2009 @ 1:38 am

    Mayor usabilidad en el código seria creo lo que le falta a este bot/clase-abstracta-de-irc...

    Saludos
    PD: El modulo web IRC tiene un XSS reflectivo, cuando se usa un host invalido =).

  5. Sysroot Noviembre 10, 2009 @ 8:36 pm

    Cuál sería la usabilidad del código de la que hablas?

    Y ya quedo arreglado el script ircWeb.php, aunque creo que es algo temporal, porque los mensajes que provienen del servidor pueden contener carácteres como < y >, así que habría que filtrar desde la clase Cliente.php
    Gracias por el aviso ;)

  6. LoMb Julio 3, 2011 @ 12:05 pm

    pss la vdd a mi no me jalo, deskargue el comprimido y ejecute, no modifike nada, al darle connect se queda en blanco todo y no hace nada :S

    te agradeceria si me echas la mano!

  7. Sysroot Julio 4, 2011 @ 7:59 pm

    Parece que para algunas versiones de PHP 5 no está funcionando como se requiere, tan pronto tenga tiempo lo corrijo y actualizo la publicación.

Deja un comentario