Introducción

Presentación

  • Buenos Aires Libre Location System (BALLS) es un desarrollo realizado para cumplir con la necesidad de registro y ubicación de nodos en la red digital comunitaria “Buenos Aires Libre”. Se han utilizado las herramientas PHP y MySQL. Luego se incorporó JavaScript y AJAX. El desarrollo completo fue ideado y creado ad-honorem y bajo licencia libre desde sus comienzos (Creative Commons Non-Commercial). La utilización completa o parcial del código de BALLS es libre para cualquier uso no comercial y es entregado sin garantías “as is”.

    La misión de éste documento no es otorgar conocimientos de PHP ni MySQL sino, explicar las técnicas y tecnologías utilizadas para crear BALLS para que cualquiera que con un poco de conocimientos en programación, pueda realizar sus aportes.

    Cabe aclarar que BALLS fue desde sus comienzos, uno de mis primeros desarrollos en éstas tecnologías, y que todos los conocimientos aplicados para realizarlo fueron adquiridos con documentos, ejemplos obtenidos en Internet y de los manuales oficiales. Puede entonces, que la terminología aplicada no sea la correcta ni la académica. Lo cual supone un enfoque distinto para encarar los problemas que se fueron presentando, que en definitiva puede y espero, resultar muy enriquecedor para quien haya aprendido con las técnicas y metodologías oficiales.

    Sepan disculpar si en alguna ocasión confundo términos y/o utilizo un vocabulario equivocado, agradecería entonces que envíen la corrección o crítica vía email y será corregido o aceptado muy gratamente.

    Gracias por poner interés en éste documento.

    Diego F. Sancho
    diegosancho@gmail.com

Objetivos

  • Ser el primer registro de un usuario nuevo en la red y otorgarle un conocimiento inmediato de su situación geográfica para con sus vecinos.
  • Brindar contacto con otras personas del proyecto según una ubicación geográfica.
  • Informar a el resto de la comunidad la situación actual de nodos.
  • Describir los enlaces realizados entre integrantes.
  • Detallar información de las MAC Address para identificar a miembros de BAL.
  • Asignar y mostrar las sub redes otorgadas del proyecto.
  • Relevar las direcciones IP asignadas en cada nodo.
  • Mantener información de estado online de nodos.
  • Compilar suficiente información del hardware para futura incorporación de una herramienta de administración integrada con Obelisco.
  • Unificar usuario y clave de ingres para todas las herramientas de BAL.
  • Alimentar de información de usuarios a herramientas BAL que lo requieran.

Dentro de BALLS

Capas

  • En un diseño sencillo, se podría incluir toda la funcionalidad de una web en un mismo código php que muestre el contenido HTML dinámicamente consultando en la base de datos (db) mientras se genera en la carga del servidor web. Pero esta técnica supone un código mezclado, a veces muy confuso de leer y modificar.
    Si quisiera luego modificar un simple botón de lugar o agregar una nueva funcionalidad, es muy probable que con un esquema como éste haya que rehacer prácticamente toda la página.

    Para evitar estos problemas, y para seguir con las buenas costumbres de programación se separó el código en varias etapas de desarrollo. (en capas en el lenguaje de programación)

    • Capa de presentación (HTML)
    • Script generador (PHP)
    • Base de datos (PHP-MySQL)

    Quedando un código puro que realiza consultas en la DB a través de llamadas a procedimientos almacenados (Stored Procedures o SP) y lo ‘envía’ al pharser de templates que se encarga de generar una presentación que el usuario verá finalmente.

    Por parte del código, la idea es que en un script PHP solo exista código PHP, en un SP, solo código SQL y en un HTML o Template solo contenido HTML (o con el mínimo pseudo código del necesario para el pharser de templates)

    A continuación, mostraré un ejemplo muy sencillo para determinar cada una de las capas mencionadas:

    Template HTML: “basico.tpl.php” (nombrado de esta manera para resaltar que se trata de un template con pseudo código PHP)

    <html>
      <head>
        <title><?=$titulo_de_la_pagina?>
      </head>
      <body>
        <h1><?=$encabezado?></h1>
        <p><?=$contenido?></p>
      </body>
    </html>
    Código PHP: “basico.php” (preferentemente de nombre similar al template que llama)
    <?php
     include "Template.class.php";  // Motor de templates hecho en PHP
     include "Database.class.php”; // Clase para manejo de DBs 
     
     $db = new database;
     $db->connect();
     $listado = $db->Obtiene_listado();
     
     $t_cuerpo = new Template(“basico.tpl.php') ;
     $t_cuerpo ->set('titulo_de_la_pagina', 'Ejemplo muy sencillo de capas separadas’);
     $t_cuerpo ->set('encablezado, 'informacion en db’);
     $t_cuerpo ->set('contenido', $listado);
     
     $t_cuerpo->dump();
     
    ?>
    Stored Procedure (SQL): “listado_usuarios”
     CREATE PROCEDURE listado_usuarios ()
     BEGIN
      SELECT * FROM usuarios;
     END;

    No entraremos en detalle todavía de lo que realizan las funciones dentro de las rutinas incluidas, por ahora nos podemos abstener a saber que son ellas las que realizan el trabajo pesado por nosotros.
    En el ejemplo anterior, se puede apreciar tres códigos completamente distinguidos y de cada una de las capas sin mezclarse entre sí, dejando una clara configuración para quien pueda manipular solo HTML, PHP o SQL.
    Esto supone una óptima detección de fallas, facilidad para implementar mejoras y/o cambios y es posible lograr un funcionamiento más robusto en cuestiones de seguridad debido a sólo habrá que atender a las validaciones en pocas oportunidades.

Marcos

  • Cualquier página mostrada dentro de BALLS se divide en cinco marcos básicos fundamentales contenidos en un sexto marco contenedor (esqueleto)

    Esqueleto

    Encabezado

    Menu

    Cuerpo

    Info

    Pie



    Cada uno de estos marcos, lleva un script que lo genera (PHP) y un template resultante. Si bien puede parecer complicado, resulta en una serie de pequeños documentos fáciles de manejar y reutilizar.
    Como ejemplo, podríamos describir en la presentación de una página de BALLS intervienen los siguientes archivos:

    En un script básico (como el changelog) están incluidas las siguientes llamadas:

    Primero, realiza todas las tareas previas de validación y de obtención de datos (consultando a la db si es necesario). Luego le envía al pharser (intérprete) de templates toda la información de todos los marcos que se mostrarán en el HTML resultante y que plantillas utilizarán para ello. Y por último, se le da la instrucción al pharser que las presente en pantalla.

    Puede parecer engorroso, pero el resultado final es muy sencillo.

     <?php      // Obtengo variables de sesión
            session_start();
     
            // Envío a otra página si el usuario no se encuentra validado
            if (not isset($HTTP_SESSION_VARS[logged_id]))
                    header(“Location: index.php”)}
     
            include "inc/Template.class.php";
     
      // Elección de templates 
            $t_esqueleto    = new Template('tpl-common/esqueleto.tpl.php');
            $t_menu         = new Template('tpl-common/menu.tpl.php');
            $t_info         = new Template('tpl-common/info.tpl.php');
            $t_encabezado   = new Template('tpl-common/encabezado.tpl.php');
            $t_pie          = new Template('tpl-common/pie.tpl.php');
            $t_cuerpo       = new Template('tpl/changelog.tpl.php') ;
     
            // Pharseo de variables a templates
            $t_esqueleto    ->set('titulo',         'Change Log');
            $t_encabezado   ->set('session',        $HTTP_SESSION_VARS);
            $t_menu         ->set('session',        $HTTP_SESSION_VARS);
            $t_info         ->set('ultimos_nodos',  $ultimos_nodos);
            $t_pie          ->set('noticias'        $HTTP_SESSION_VARS[noticias]);
     // Al esqueleto le transfiero los otros marcos ya armados.     
     $t_esqueleto   ->set('cuerpo',                 $t_cuerpo);     
            $t_esqueleto    ->set('menu',           $t_menu);
            $t_esqueleto    ->set('info',           $t_info);
            $t_esqueleto    ->set('encabezado',     $t_encabezado);
            $t_esqueleto    ->set('pie',            $t_pie);
     
            // Doy orden final para que el pharser genere el contenido completo
            $t_esqueleto    ->dump();
     ?>
    En resumen:
    • Verifico si el existen las credenciales del usuario en las variables de sesión, si no, lo devuelvo a la portada para que lo realice
    • Incluyo librería de teplates (que nos dará las funciones para presentarlos)
    • Creo seis objetos de template para formar cada uno de los marcos
    • A cada marco, le transfiero las variables que va a mostrar
    • Al esqueleto le transfiero los sub marcos como si fueran variables comunes
    • Disparo la generación del HTML resultante (dump)

Sesiones y logueo

  • Es importante destacar el énfasis puesto en seguridad del sitio, para proteger la información privada de los usuarios y mantener su confianza. Por esta razón, las contraseñas de los usuarios son almacenadas en forma de hash MD5 para que no puedan ser reveladas, ni siquiera cuando un administrador malintencionado o hacker pueda tener acceso a la base de datos. La contraseña solo viaja en formato plano vía POST en el instante de ingreso. Luego no las credenciales son almacenadas en el servidor web.

    Durante la rutina de ingreso (válida), se generan nuevas cookies y se almacena el mismo hash en la DB. Inmediatamente después, se carga información recurrente en el espacio de variables de sesión para que puedan ser accedidas inmediatamente durante la visita en el sitio. (ver código inc/ingreso.inc.php”)

    Para una recuperación de contraseña, el sistema genera un hash temporal con una corta validez y lo envía en forma de link por mail al destino indicado por el usuario (si existe en la DB). Cuando el usuario regresa con el hash, el sistema valida como email correcto y genera la sesión de usuario como si hubiese ingresado correctamente con su clave, inmediatamente después, se sugiere el cambio de contraseña por una nueva.

Rutina redundante de sesiones

  • Para permitir que un usuario permanezca registrado en los sitios de BAL, y sea posible brindar contenidos relativos a ese usuario, es necesario que el cliente mantenga la información de registro durante los saltos entre los diferentes subdominios, debido a que las sesiones que permanecen vivas durante la visita a una página, permanecen aisladas cuando el explorador se refiere a otro sitio o subdominio de internet.

    Para solucionar este inconveniente, se ha creado una rutina de validación dentro de cada script del sitio que verifica las credenciales del usuario en el subdominio y las vuelve a generar en caso de que haya realizado un salto. El esquema lógico es el siguiente:

introduccion_balls1_.jpg

  • Ni bien se recibe el pedido de cualquier página, el script solicita las variables de sesión. Si las encuentra, renueva las cookies luego continua con la carga normal.
    Si no encuentra las variables de sesión (ya sea hayan caducado, venga de otro subdominio o bien no las tenga, Verifica si existen cookies de sesión. Si las cookies tampoco existen, devuelve “usuario no validado”. Cuando las cookies existen, las verifica y compara un hash en la base de datos, si son válidas, el script vuelve a generar las variables de sesión y recarga la página. Si no, borra las cookies inválidas y la rutina devuelve “usuario no validado”.

    Lamentablemente esta rutina hay que repetirla en todos los scripts y no es posible incluirla en una función, debido a que PHP requiere que función de carga de sesiones (session_start) se realice como primer paso del script, no pudiendo incluir a una librería en primera instancia (o simplemente quizás no supe cómo hacerlo)
    El Código es el siguiente:

    <?php  // Obtener variables de sesion
            session_start();
            include "inc/database.inc.php";
            if (isset($HTTP_SESSION_VARS[logged_id])) {
                    $logged_id      = $HTTP_SESSION_VARS[logged_id];
                    $logged_email   = $HTTP_SESSION_VARS[logged_email];
                    $logged_nombre  = $HTTP_SESSION_VARS[logged_nombre];
                    $logged_tipo    = $HTTP_SESSION_VARS[logged_tipo]; 
                    $sinodo         = $HTTP_SESSION_VARS[sinodo];   
                    include "inc/gencoockies.inc.php";
                    genera_coockies($logged_id);
            } else {
                    include "inc/chequeacoockies.inc.php";
                    chequea_coockies ( $PHP_SELF );
            }
    …
    Código “gencookies.inc.php”
    <?php
    // Genera coockies y actualiza db con nuevo token de verificación
    function genera_coockies ($id_usuario) {
                    $db = new database;
                    $db ->connect();
                    $segundo_actual = date('Y-m-d H:i:s');
                    $new_token = md5(rand(1,32000));
                    $res = $db -> updateRow("usuarios", "token='$new_token', fecha_token = '$segundo_actual'", "id_usuario='$id_usuario'");
                    setcookie("balls_id",    $id_usuario, time()+1800, "/", ".buenosaireslibre.org", 0);
                    setcookie("balls_token", $new_token,  time()+1800, "/", ".buenosaireslibre.org", 0);
    }
    ?>
    Código “Chequeacookies.inc.php”
    <?
    function chequea_coockies ( $pagina_reenvio ) {
            // Verifica Coockies
            if (isset($_COOKIE[balls_id]) AND isset($_COOKIE[balls_token])) {
                    include "ingreso.inc.php";
                    genera_sesion ($pagina_reenvio);
            } else { 
                    // Destruye coockies
                    $logged_id = "";
                    setcookie("balls_id",    $logged_id, time()-36000,"/",".buenosaireslibre.org",0);
                    setcookie("balls_token", $new_token,  time()-36000,"/",".buenosaireslibre.org",0);      
            }
    }
    ?>

Jerarquia de la Base de datos

  • Las tablas fundamentales de la base de datos están organizadas y relacionadas de la siguiente manera:

  • introduccion_balls2.jpg De manera que: Las subredes y nodos se asignan a los usuarios; Las interfaces se asignan a los nodos; Las IPs y Enlaces, se asignan a las interfaces. Permitiendo de esta manera, que un usuario posea uno o varios nodos y subredes; Que un nodo posea una o varias interfaces; y que una interface posea una o varias IPs y Enlaces.

    El listado completo de tablas y la descripción detallada de las mismas, está fuera del alcance de éste documento.

Esquema y división de mapas

  • Entre varios métodos de segmentación de mapas, se ha elegido el utilizado por los municipios. Quedando la Ciudad Autónoma de Buenos Aires (CABA) dividida en barrios y el Area Metropolitana de Buenos Aires (AMBA) y la Provincia de Buenos Aires (Pcia BsAs) divididas en partidos.
    A su vez, AMBA y Pcia BsAs han sido identificados con distintas áreas geográficas (para una referencia más clara.

    BsAs AMBA
    Las regiones geográficas y los partidos/barrios determinan la numeración (id) de las zonas de Balls

    por ejemplo:

    • En CABA, los barrios comienzan en un id 100, Palermo 101, Recoleta 102, Retiro 103, etc.,
    • En AMBA la “región o Zona Norte” los id comienzan por 200, 201 Vicente López, 202 San Isidro, etc.,
    • En la Pcia de Buenos Aires, se asignaron los id de las regiones en orden a su cercanía a AMBA. Primero los múltiplos como regiones y luego los partidos como incremento. Quedando por entre otros 701 La plata, 702 Ensenada, 703 Berisso, etc.,

    Las regiones pueden ser nombradas con cualquier nombre, por ejemplo la región 15, popularmente llamada “Partido de la costa”

    Cada mapa, región o división es nombrada en BALLS con un nombre de archivo. Para una determinación práctica se estableció: id_zona.png y para una región o grupo de barrios/partidos id_inicio-id_fin.png
    Cada archivo debe estar acompañado de otro archivo XML con el mismo nombre que contiene la información de esa región (cuando no existe el XML el sistema identifica que se trata de un barrio/partido y no una región). A continuación se muestra un código XML con el código contenido de la región 15. (archivo “1500.xml”)

    <?xml version="1.0" encoding="ISO-8859-1"?>
    <zona>
            <nombre>Region</nombre>
            <mapa>1500.png</mapa>
            <tamanox>500</tamanox><tamanoy>500</tamanoy>
            <regiones>
                    <region><id>1501</id><nombre>La Costa     </nombre> <centrox>325</centrox><centroy>143</centroy>             <coords>311,22,337,24,358,55,356,182,348,218,352,245,307,303,271,287,310,232,308,215,315,181,320,174,319,125,301,109,321,106,321,77,317,71,319,58,309,47</coords></region>
                    <region><id>1502</id><nombre>Pinamar      </nombre> <centrox>257</centrox><centroy>314</centroy><coords>273,286,307,303,268,354,230,342</coords></region>
                    <region><id>1503</id><nombre>Villa Gessell</nombre> <centrox>201</centrox><centroy>389</centroy><coords>228,341,268,354,214,431,165,481,145,463,176,418,183,398,204,370,182,355,194,340,219,348</coords></region>
            </regiones>
    </zona>

    Donde primero se define la zona, Su nombre y su archivo PNG asociado.

    Para una simple configuración del HTML que lo emplea, se define también el tamaño de la imagen.
    Dentro de el tag regiones, se especificará cada una de las regiones que contenga este mapa. Cada región especifica: El ID de la sección, el nombre, las coordenadas centrales de esa división (para que el sistema sepa dónde poner el contador de usuarios) y las coordenadas de el polígono que delimita el partido/barrio (estas coordenadas son tomadas fácilmente desde un editor HTML.
    Para facilitar la comprensión y modificación de estas coordenadas, se brinda también el HTML que se utilizó para realizar la división)

BALLS/DocumentacionHacking (última edición 2009-03-15 22:33:53 efectuada por JavierVitoSpezzi)