Conectando a IRC-Hispano con X-Chat

Entrada que agrego porque me lo han preguntado hace un rato, y así comparto el tutorial con quien tenga dudas. Aunque a más de uno os sorprenda, el protocolo de chat IRC se sigue utilizando. Desde luego no de una forma tan masiva como a principios de los dosmiles, pero existe actividad. Me preguntaba hace un rato una colega cómo podría conectarse a un canal de la red IRC-Hispano y le dije que había un app para Android, que chupa la hostia de bateria y ancho de banda, pero cumple el cometido en tu móvil. ¿Y para PC? Pues en Ubuntu/Mint/Elementary tienes opciones como X-Chat, que puedes instalar desde el centro de software de la popular distribución (Existen otras, como HEX-Chat, del que ya hablamos aquí).

Una vez instalado verás que te da opciones como elegir varios apodos por si el tuyo está ocupado, nombre de usuario, etc… y debajo te aparecerá una lista de servidores a los que conectarte, entre los cuales NO ESTÁ el IRC-Hispano. Y esto era lo que le interesaba la persona que preguntaba, ya que quería unirse al canal #Coruña, perteneciente a ese servidor ¿Cómo se configura esto?. Pues muy simple:

  • En el apartado Redes pulsa el botón Añadir
  • Ponle el nombre, para acordarte
  • Con la red recién añadida selecciónala y pulsa Editar
  • Una vez pulsado editar veremos todos los servidores de la red (debería haber sólo uno que ponga «nuevo/6667» o algo así). Editáis el que aparece por defecto y lo cambiáis por irc.irc-hispano.org/6667 siendo 6667 el número del puerto al que os conectaréis.
  • Tras añadir esto os queda pulsar Aceptar y Conectar, y ya conseguís el acceso a los canales de IRC-Hispano.

Y tras esto podéis disfrutar del chateo old-school.

Servidor de Chat con Raspberry Pi

Un amigo me ha dejado una Raspberry Pi y ando dando vueltas a experimentos varios. Esta mañana, hablando con un compañero de curso, este me comentó de un proyecto libre para convertir equipos en centros multimedia basado en software de XBOX de Microsoft (XBMC), si bien llegamos a la conclusión de que el pequeño miniordenador educativo tal vez no era lo más idóneo si quieres reproducir películas en HD (ojo, que hay una versión para Raspberry Pi de dicho software). Pero con todo esto del PRISM y el espionaje descarado de la NSA tal vez un servidor de chat pueda interesar a alguien.

Raspberry Pi de 2011
La Raspberry Pi del experimento

En este caso vamos a usar Prosody, y vamos a suponer que estáis usando la versión adaptada de Debian para la Raspberry Pi. Lo primero, como no, instalar Prosody:

sudo apt-get install prosody

Ok, ya está instalado. Con esto, el archivo de configuración básico y un par de usuarios creados ya podrías operar, pero vamos a configurar un poco la historia. Lo primero vamos a meter las librerías para encriptación, compresión y soporte de base de datos:

sudo apt-get install luasec lua-zlib luadbi

Con esto ya tenemos las librerías necesarias. Ahora toca irse al archivo de configuración y activar ciertos módulos. Dichos módulos, por defecto, vienen desactivados ya que las líneas en el archivo de configuración están comentadas con dos guiones al principio de la línea. Para descomentarlas simplemente borra esos guiones.

Para entrar a editar el archivo de configuración:

sudo gedit /etc/prosody/prosody.cfg.lua

Allí elegís ya los módulos a activar. Yo en el mío he activado estos:

                "privacy"; -- Support privacy lists
                "compression"; -- Stream compression
                "groups"; --Shared roster support
                "roster"; -- Allow users to have a roster. Recommended 
                "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
                "tls"; -- Add support for secure TLS on c2s/s2s connections
                "disco"; -- Service discovery
                "private"; -- Private XML storage (for room bookmarks, etc.)
                "vcard"; -- Allow users to set vCards                
                "version"; -- Replies to server version requests
                "uptime"; -- Report how long server has been running
                "time"; -- Let others know the time here on this server
                "ping"; -- Replies to XMPP pings with pongs
                "adhoc"; -- Support for "ad-hoc commands" that can be executed with an XMPP client
                "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands

Vosotros configurad como queráis. Ahora sí que vamos con un punto importante: ¿queremos que la gente pueda registrarse o queremos sólo poder crear usuarios nosotros para tener un mayor control del acceso? Ya que hablamos de seguridad y privacidad es un punto importante. Por defecto el módulo de registro y la opción de permitir el registro están desactivados, así que si queremos activarlo toca descomentar el módulo «register» y la línea que pone allow_registration=true. Es de suponer que no tendréis una ip fija, al menos en España lo normal es tenerla dinámica y la fija implica un sobrecargo en la factura, por lo que será cosa buena haceros con un dominio (podéis conseguir uno gratis en noip.com). Luego buscáis en la configuracion una línea que pone VirtualHost «example.com» y la cambiáis por vuestro dominio. Debajo habrá una línea que pone enabled = false, la comentáis o borráis y estará activado vuestro dominio.

Bueno, con esto ya tendrías el servidor de chat furrulando cosa buena. Pero como no queremos que un pajillero del FBI lea lo que escribimos casi mejor vamos a encriptar, que para algo metimos antes el módulo (aunque si leemos entre líneas la declaración de Snowden, es probable que la NSA ya sea capaz de romper la seguridad SSL). En todo caso lo primero es irnos a la carpeta de certificados de Prosody y desde allí trabajar:

cd /etc/prosody/certs/
sudo openssl req -new -x509 -days 365 -nodes -out "prosody.cert" -keyout "prosody.key"

Tras esto te pedirá una serie de datos que, excepto uno, no son muy relevantes. La excepción es Common Name (e.g. server FQDN or YOUR name) []:, donde tenéis que poner el nombre de dominio conseguido antes, el resto si queréis los podéis ignorar. Una vez acabado este proceso se crearán dos archivos: prosody.cert y prosody.key. Con ellos creados os toca volver a abrir para editar el archivo de configuración principal.

Ahí tenéis que copiar lo siguiente dos veces:

ssl = {
key = “/etc/prosody/certs/prosody.key”;
certificate = “/etc/prosody/certs/prosody.cert”;
}

La primera vez lo ponéis sobre las rutas ssl por defecto y ponéis exactamente lo mismo justo debajo de la línea de VirtualHost «elnombrededominioquetengáis».

Yo no me voy a meter a configurar base de datos, aunque instalara antes la librería, porque en una Raspeberry Pi no es que vayamos sobrados de recursos. Si queréis hacerlo tenéis un excelente tutorial en español aquí (fue uno de los varios que utilicé como documentación mientras hacía las pruebas).

Bueno, una vez acabado esto ya sólo nos queda lanzar Prosody:

sudo /etc/init.d/prosody start

Podéis modificar el sistema para que arranque al a vez que el sistema operativo, si lo véis necesario. Ahora con cualquier cliente de XMPP o Jabber, como Pidgin, podéis acceder a él. Cuando entréis por primera vez os pedirá que creéis una cuenta en el servidor. Bueno, si habéis habilitado el registro de usuarios bien, ¿y si no? Ya lo comentamos arriba, puedes no permitir el registro y crear tú los usuarios, si quieres un servidor de chat para un pequeño grupo de trabajo/amigos no es mala idea. Bueno, los usuarios se crean con la sintaxis sudo prosodyctl adduser nombredeusuario@eldominioquepillaras. Por ejemplo, supongamos que tu dominio es fucknsa.cc y el usuario que quieres crear se va a llamar, no sé, un nombre aleatorio, por ejemplo assange:

sudo prosodyctl adduser assange@fucknsa.cc

Por cierto, que si quieres montar el servidor de chat en una red local no necesitarás el dominio.

Bueno, ya tienes tu cacharrito con servidor de chat. A divertirse tocan.

Crear un chat con PHP y jQuery

En este caso no se trata de un artículo original, sino de una medio traducción medio interpretación de este original en inglés. Podéis descargaros todo el código desde el enlace.

Se trata de un chat web simple, programado en php y basado en Ajax, haciendo uso de jQuery, con función de login y logout y soporte para varios usuarios.

El tutorial comienza creando un archivo index.php tal cual este:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
<title>Chat - Customer Module</title>  
<link type="text/css" rel="stylesheet" href="style.css" />  
</head>  
<div id="wrapper">  
    <div id="menu">  
        <p class="welcome">Welcome, <b></b></p>  
        <p class="logout"><a id="exit" href="#">Exit Chat</a></p>  
        <div style="clear:both"></div>  
    </div>  
    <div id="chatbox"></div>  
    <form name="message" action="">  
        <input name="usermsg" type="text" id="usermsg" size="63" />  
        <input name="submitmsg" type="submit"  id="submitmsg" value="Send" />  
    </form>  
</div>  
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.0.js"></script>  
<script type="text/javascript">  
// jQuery Document  
$(document).ready(function(){  
});  
</script>  
</body>  
</html>

Como podéis ver se trata de un marcado HTML normal. La referencia a jQuery del código original está anticuada, en este ejemplo ya veréis una apuntando una dirección actualizada. En cuanto a la estructura hay tres grandes divs: el #wrapper, que contiene los otros dos y el formulario de envío de mensaje; el #menu, que sólo es un mensaje de bienvenida y un botón de logout y, finalmente, el #chatbox, que es donde se incluirán los mensajes.

El css sería tal que así:

    /* CSS Document */  
    body {  
        font:12px arial;  
        color: #222;  
        text-align:center;  
        padding:35px; }  
    form, p, span {  
        margin:0;  
        padding:0; }  
    input { font:12px arial; }  
    a {  
        color:#0000FF;  
        text-decoration:none; }  
        a:hover { text-decoration:underline; }  
    #wrapper, #loginform {  
        margin:0 auto;  
        padding-bottom:25px;  
        background:#EBF4FB;  
        width:504px;  
        border:1px solid #ACD8F0; }  
    #loginform { padding-top:18px; }  
        #loginform p { margin: 5px; }  
    #chatbox {  
        text-align:left;  
        margin:0 auto;  
        margin-bottom:25px;  
        padding:10px;  
        background:#fff;  
        height:270px;  
        width:430px;  
        border:1px solid #ACD8F0;  
        overflow:auto; }  
    #usermsg {  
        width:395px;  
        border:1px solid #ACD8F0; }  
    #submit { width: 60px; }  
    .error { color: #ff0000; }  
    #menu { padding:12.5px 25px 12.5px 25px; }  
    .welcome { float:left; }  
    .logout { float:rightright; }  
    .msgln { margin:0 0 2px 0; }  

Poca cosa que comentar, pero entre esto y el marcado ya tenemos la apariencia definida del chat.

Ahora toca el formulario de login en PHP:

    <?  
    session_start();  
    function loginForm(){  
        echo' 
        <div id="loginform"> 
        <form action="index.php" method="post"> 
            <p>Please enter your name to continue:</p> 
            <label for="name">Name:</label> 
            <input type="text" name="name" id="name" /> 
            <input type="submit" name="enter" id="enter" value="Enter" /> 
        </form> 
        </div> 
        ';  
    }  
    if(isset($_POST['enter'])){  
        if($_POST['name'] != ""){  
            $_SESSION['name'] = stripslashes(htmlspecialchars($_POST['name']));  
        }  
        else{  
            echo '<span class="error">Please type in a name</span>';  
        }  
    }  
    ?>     

En este caso se trata de un login simple, no comprueba usuarios registrados en una base de datos. Sobre su funcionamiento hay poco que comentar: nos pide un nombre y lo incluye dentro de una variable de sesión (de ahí la llamada a session_start()). El uso de htmlspecialchars() es para evitar ataques XSS.

Lo siguiente es motrar tanto el nombre de usuario en el Welcome como el formulario si el usuario no está logueado. La idea es dejar el primer archivo, el index.php tal cual este:

    <?php  
    if(!isset($_SESSION['name'])){  
        loginForm();  
    }  
    else{  
    ?>  
    <div id="wrapper">  
        <div id="menu">  
            <p class="welcome">Welcome, <b><?php echo $_SESSION['name']; ?></b></p>  
            <p class="logout"><a id="exit" href="#">Exit Chat</a></p>  
            <div style="clear:both"></div>  
        </div>  
        <div id="chatbox"></div>  
        <form name="message" action="">  
            <input name="usermsg" type="text" id="usermsg" size="63" />  
            <input name="submitmsg" type="submit"  id="submitmsg" value="Send" />  
        </form>  
    </div>  
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>  
    <script type="text/javascript">  
    // jQuery Document  
    $(document).ready(function(){  
    });  
    </script>  
    <?php  
    }  
    ?>  

Bien, ahora vamos con el código de Javascript para la funcionalidad de logout. Dentro del script que ya tenemos creado en nestro código insertamos:

    <script type="text/javascript">  
    // jQuery Document  
    $(document).ready(function(){  
        //If user wants to end session  
        $("#exit").click(function(){  
            var exit = confirm("Are you sure you want to end the session?");  
            if(exit==true){window.location = 'index.php?logout=true';}  
        });  
    });  
    </script>  

Esto no sólo nos permite enviar una llamada por el método GET para desconectar al usuario, sino que también nos sacará una ventana de confirmación antes de hacerlo. Y claro está, tendremos que tocar nuestro código del index.php para comprobar que se ha hecho una petición de logout y destruir la sesión que se había creado en el login:

    if(isset($_GET['logout'])){  
        //Simple exit message  
        $fp = fopen("log.html", 'a');  
        fwrite($fp, "<div class='msgln'><i>User ". $_SESSION['name'] ." has left the chat session.</i><br></div>");  
        fclose($fp);  
        session_destroy();  
        header("Location: index.php"); //Redirect the user  
    }  

Este código, además, escribe en un archivo de logs (más tarde vemos para qué se usará) que el usuario se ha desconectado y redirecciona de nuevo a la página principal.

Lo siguiente es manejar las inserciones de mensajes de los usuarios. Hay que empezar por definir una función de jQuery para enviar los mensajes por el método POST haciendo uso de Ajax. El proceso sería recoger el evento de click del formulario, leer los datos del campo de texto, enviarlos al script de php que los va a tratar y borrar el campo de texto para que quede de nuevo en blanco:

    //If user submits the form  
    $("#submitmsg").click(function(){  
        var clientmsg = $("#usermsg").val();  
        $.post("post.php", {text: clientmsg});  
        $("#usermsg").attr("value", "");  
        return false;  
    });  

Y claro, esto implica crear el archivo post.php para manejar los datos en el lado del servidor. Un archivo que llevaría este código:

    <?  
    session_start();  
    if(isset($_SESSION['name'])){  
        $text = $_POST['text'];  
        $fp = fopen("log.html", 'a');  
        fwrite($fp, "<div class='msgln'>(".date("g:i A").") <b>".$_SESSION['name']."</b>: ".stripslashes(htmlspecialchars($text))."<br></div>");  
        fclose($fp);  
    }  
    ?>  

De nuevo iniciamos sesión, comprobamos que el usuario está logueado, recogemos el texto del mensaje del array $_POST y escribimos el mensaje junto al nombre de usuario en el log del chat.

Finalmente llevamos a la parte de mostrar los mensajes de chat en pantalla. Lo primero es cargar el log del chat dentro del #chatbox si este existe, para ahorrarnos tiempo:

    <div id="chatbox"><?php  
    if(file_exists("log.html") && filesize("log.html") > 0){  
        $handle = fopen("log.html", "r");  
        $contents = fread($handle, filesize("log.html"));  
        fclose($handle);  
        echo $contents;  
    }  
    ?></div>  

Lo siguiente es la carga por Ajax de los datos contenidos en el archivo de log. La cosa se arreglaría con el método de jQuery para Ajax:

    //Load the file containing the chat log  
        function loadLog(){  
            $.ajax({  
                url: "log.html",  
                cache: false,  
                success: function(html){  
                    $("#chatbox").html(html); //Insert chat log into the #chatbox div  
                },  
            });  
        }  

El parámetro url nos indica a qué archivo intentamos acceder por Ajax, cache es para definir si queremos cachear el archivo o no (en este caso, por lógica, no, porque queremos recargarlo en cada llamada) y finalmente la función que se ejecutará en caso de éxito (en este caso insertar el log en el div #chatbowx).

Para añadir autoscrolling, modificas el código anterior añadiendo lo siguiente:

    //Load the file containing the chat log  
    function loadLog(){  
        var oldscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height before the request  
        $.ajax({  
            url: "log.html",  
            cache: false,  
            success: function(html){  
                $("#chatbox").html(html); //Insert chat log into the #chatbox div  
                //Auto-scroll  
                var newscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height after the request  
                if(newscrollHeight > oldscrollHeight){  
                    $("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll to bottom of div  
                }  
            },  
        });  
    }  

Básicamente consiste en ir modificando el tamaño para ocultar la parte de arriba y ampliar la de abajo. Simple truquillo. Ahora nos falta que el chat se auto recargue, cosa que haremos desde javascript:

setInterval (loadLog, 2500);

Esto lanza la función loadLog cada dos segundos y medio, logrando recargar los datos.

En el artículo orginal además encontraréis al final una serie de artículos con consejos varios para mejorar el código (en inglés) y todo el código completo para descargar.