Anti-Monopoly ( ― San Francisco State University ― Professor Ralph Anspach)

La Historia de Internet – Guerra de Navegadores

Si no sabemos de dónde venimos, no sabremos -jamás ni nunca- hacia dónde vamos, las nuevas generaciones deben saber, deben conocer lo que nosotros vivimos en esa época ¡por la libertad del internet! Recuerdo las descargas del código fuente del Netscape eran una barbaridad de 200 megabytes cuando nos afanábamos de nuestros discos duros de 700 MB (yo tenía un flamante Samsung, IDE por supuesto que había comprado con un préstamo en el trabajo y duré 6 meses para pagarlo ¡un disco duro!). Continue reading

Feliz Día del Programador

Feliz Día del Programador 2017

«Feliz Día del Programador» desde el 2015 tenemos conocimiento que celebramos este día, sin distingo del lenguaje que usemos, tengamos que usar o que desarrollemos (los más avezados en la materia). Sin duda que los ordenadores es uno de los más grandes inventos de la humanidad, con la labor destacada de Alan Turing (con quien en vida se cometió una gran injusticia en su vida personal).

Feliz Día del Programador
Feliz Día del Programador

Modestía aparte: sobre nosotros recae un gran poder que conlleva una gran responsabilidad y aprovechamos el día para recordarnos nuestra dosis diaria de humildad, paciencia y empeño no solo en este día sino en todo el año para que los usuarios a quienes nos debemos (y nos dan el sustento económico en este, por ahora, sistema capitalista) sean los máximos beneficiados de nuestros frutos mentales ¡Y SI PROGRAMAMOS EN SOFTWARE LIBRE CONTRIBUIMOS AL PATRIMONIO TECNOLÓGICO DE LA HUMANIDAD! Continue reading

Chromium Web Browser Logo

Chromium extension tutorial

Por supuesto que no estamos hablando del elemento químico cromo (“chromium” en inglés) sino del popular navegador web de código abierto para todos. Lo que desarrollaremos es una “extensión”, una herramienta integrada al navegador y que tiene muy diferentes propósitos. Con fines didácticos haremos una extensión muy sencilla que nos redirige hacia una página web que nos devuelve simplemente nuestra propia dirección IPv4, ¡manos al teclado!

¿Qué es una extensión para Chromium?

Chromium Web Browser Logo

Como ya lo definimos al principio, una herramienta puede tener fines diversos, uno o más:

  • Pueden ser usadas para notificarnos si tenemos nuevos mensajes de correo electrónico por medio del pequeño icono que se coloca al lado de la barra de direcciones.
  • Si no hemos iniciado sesión en nuestra cuenta de correo-e basado en web, podemos hacer click en el icono para ir a la página donde introduciremos nuestras credenciales (¡Cuidado con las páginas falsas o “phishing”!).
  • Podría alertarnos si una palabra clave en particular aparece en la página que estemos visitando.
  • Podríamos programarla para NO cargar las imágenes de un sitio determinado -o todos los que visitemos-.
  • Tal vez sería útil para alertarnos de la modificación de una página (aunque para ellos hay lectores RSS específicos para ese trabajo) o su cambio de estado.
  • ¡Incluso, si somos aventureros, nos permitiría programar una calculadora!

Como ven los usos son muchos y variados, nuestra imaginación no tiene límites más sin embargo el entorno donde va a funcionar nuestra novel extensión sí que está supeditada al navegador Chromium. Esencialmente una extensión es una pequeñita página web que está alojada en un navegador web – en este caso Chromium – y que además puede acceder a ciertas funciones API (“Application Programming Interface“: conjunto de clases, métodos y funciones normalizadas).

La que nosotros vamos a realizar es bastante modesta y a medida que avanzemos la iremos profundizando más, pero la idea es introduciros en esta área de programación en un entorno de desarrollo bastante peculiar.

Creando el proyecto.

Pues que para comenzar crearemos en nuestro disco duro, donde gustemos, una carpeta con el nombre “KS7000_ConoceTuIPv4” – o el nombre que vosotros querais, sed de libre albedrío, lo importante es que aprendamos los conceptos y procedimientos-.

Primer componente de nuestra extensión en Chromium.

Como somos inclinados al dibujo técnico más que al dibujo artístico (¡Ea, que por allí viene nuestro tutorial sobre Inkscape!) lo que hicimos fue redimensionar un logotipo en formato PNG (que ya teníamos rodando por internet) a un tamaño de 16 por 16 píxeles ya que necesitados una pequeña interfaz gráfica para el botón donde nuestros usuarios harán click y abrirán nuestro trabajo. Cuando “subamos” – y especifiquemos- este icono a Chromium no tendremos que programar línea alguna: ya el navegador sabrá qué hacer al evento de hacer click sobre nuestra pequeña obra de arte microscópica (935 bytes “pesa” el fichero):

KS7000_ConoceTuIPv4 (icono)

Precisamente queremos hacer hincapié en este punto: esa imagen pequeñita que vamos a especificar ya Chromium le añade el evento click para cargar y ejecutar los siguientes componentes que vamos a crear, eso es, en sí, una Interfaz de Programación de Aplicaciones “API” -normalizadas en un ambiente determinado (Chromium, en este caso) -.

Creando un archivo de manifiesto.

Un manifiesto es simplemente una declaración de propósitos o programas. Para este caso es un fichero llamado manifest.json y por su extensión deducireis que está en lenguaje JSON: JavaScript Object Notation, el cual permite el intercambio de información entre cliente y servidor. Aunque está basado en la norma ECMA-262 3ª edición de 1999 nosotros consideramos que es una norma de facto. En todo caso no representa mayor misterio, tal como lo es XML, el JSON (a menos que guarde datos binarios) es plenamente legible tanto a humanos como a máquinas, pasemos a analizar su estructura mínima necesaria:

{
  "manifest_version": 2,
  "name": "KS7000_ConoceTuIPv4",
  "version": "1.0",
}

Explicado línea por línea, los tres primeros elementos son obligatorios:

  1. “manifest_version”: toma el valor 2 -sin comillas- para indicar que es a partir de la versión 18 de Chromium que funcionará la extensión. Al momento de escribir este reportaje vamos por la versión 59 así que ya sabeis que la versión 1 está obsoleta e inútil, de hecho. Notad cada coma para indicar separación de componentes, lo colocamos antes del fin de línea y retorno de carro.
  2. “name”: con hasta un máximo de 45 caracteres, es como identificaremos nuestra extensión y tratad que sea bien original y único si es que quereis algún día hacerlo famoso por internet y evitar malentendidos con otros programadores o incluso poderosas corporaciones.
  3. “version”: pues la numeración que utilizemos para identificar los cambios que le hagamos, y aunque está entrecomillado no os equivoquéis: son cuatro enteros de ntreo cero y 65535 separados por puntos y sirven para identificar – y actualizar a nuestros usuarios si hacemos una mejora -. En nuestro ejemplo colocamos “1.0” ¿Dónde diablos están los otros dos números faltantes? Pues en realidad nuestra versión es “1.0.0.0”, tened mucho cuidado al numerar porque como dijimos se usa para comparar y actualizar, de ser necesario, a nuestros usuarios.

Más adelante ahondaremos en otras propiedades que deberíamos agregar y que implican otros ficheros en nuestra mini aplicación, per antes de finalizar esta sección os contamos que hay otras propiedades interesantes:

  • “description”: la descripción de lo que realiza nuestra extensión, para lo que sirve, sed breve y conciso; entrecomillad.
  • “short_name“: que soporta hasta 12 caracteres y es especialmente útil para titular las pestañas y el lanzador de aplicaciones (en teoría).
  • “version_name”: un nombre no necesariamente numérica, si queremos colocarle un nombre afectuoso, deberiamos tratar de que sea único.

Así las cosas nuestro archivo de manifiesto va quedando como sigue:

{
  "manifest_version": 2,
  "name": "KS7000_ConoceTuIPv4",
  "short_name": "KS7000_IP",
  "description": "Esta extensión os permitirá saber vuestra dirección IPv4.",
  "version": "1.0",
  "version_name": "TuIPv4",
}

¿Acciones de página o acciones de navegador?

Aunque dijimos que Chromium sabría qué hacer con nuestra extensión, esto no es totalmente cierto ya que en esta API desarrollaron dos aciones principales de la cual debemos especificar que nuestra extensión realize alguna de las dos (o ninguna: si es ninguna pues no obtenemos ningún resultado, es una extensión inútil).

  • Acción de navegador: se ejecutará en cualquier pestaña y paǵina que abramos y permite que nuestros usuarios interactuen con nuestra extensión (ejecutar una orden o cambiar las preferencias, por ejemplo).
  • Acción de página: es un icono que indica un estado o condición a la página que estamos visitando (¿recuerdan que propusimos, al principio, una extensión que buesque y notifique la existencia de una palabra clave? pues eso, se puede activar -o no- si esa palabra clave está presente). Esta acción NO permite interactuar con los usuarios, es más bien informativa.

Nosotros usaremos la acción de navegador para lo cual debemos escribir:

"browser_action": {}

y colocamos entre los corchetes los elementos que queremos especificar y que a continuación especificamos:

 "default_icon": "KS7000_ConoceTuIPv4.png",
 "default_popup": "aviso.html"

La primera línea indicamos que utilice el ícono que os mostramos al principo, pero !ah,caramba! ¿habiais dicho que Chromium sabrá que hacer por nosotros? pues aquí el detalle no es culpa de Chromium ya que debido a los múltiples dispositivos (hardware) que pueden ejecutar este navegador web son muy diversos, los tamaños de pantalla son muy diversos también así que debemos -en teoría- hacer íconos de diferentes tamaños Y CHROMIUM SE ENCARGARÁ DE MOSTRAR EL QUE SEA DEL TAMAÑO ADECUADO AL DISPOSITIVO y tal como prometimos nos “harán” el trabajo a nosotros los programadores.

Acá nos quedaremos con un solo ícono, queda para vosotros estudies cómo especificar más iconos. La segunda línea establece cuál archivo .html queremos mostrar cuando el usuario haga click, y de nuevo es cuestión de tener variedad de opciones ya que podemos hacer varios ficheros .html (según la complejidad de nuestra extensión) pero debemos decirle al navegador cual queremos que muestre primero, así solo sea una la que “subamos” ¡NO ESTAMOS PROGRAMANDO EN PYTHON, TAMPOCO ESPERÉIS MILAGROS!

Archivo de manifiesto, versión final, debidamente indentado.

{
  "manifest_version": 2,
  "name": "KS7000_ConoceTuIPv4",
  "short_name": "KS7000_IP",
  "description": "Esta extensión os permitirá saber vuestra dirección IPv4.",
  "version": "1.0",
  "version_name": "TuIPv4",

  "browser_action": {
    "default_icon": "KS7000_ConoceTuIPv4.png",
    "default_popup": "aviso.html"
  } 
}

Elemento emergente de interfaz.

Ya sabemos que nos falta ahora un elemento, el “default_popup” al cual le asignamos el nombre “aviso.html” y como este tema no es un tutorial de HTML5 pues de una os colocamos el código del fichero de marras:

<!doctype html system "about:legacy-compat">
<html lang="es-419">
  <head>
    <meta charset="UTF-8">
    <title>KS7000</title>
  </head>
  <body>
    <h1>KS7000_ConoceTuIPv4</h1>
    <a href="http://www.soporteweb.com/" target="_blank">Haz click para saber saber vuestra dirección IPv4</a>
  </body>
</html>

“Subiendo” nuestra extensión.

Pues tanto como “subir” no será, no vamos a publicar nada por internet (aún no, por lo menos). Para nuestro ejemplo estamos ejecutando Ubuntu 16 64 bits al cual le instalamos Chromium 59 y en la barra de direcciones escribimos lo siguiente:

chrome://extensions/

Luego presionamos Intro o Enter y veremos algo muy parecido a esto:

Chromium instalar y configurar extensiones
Chromium instalar y configurar extensiones

En letras verdes os indicamos dónde “clickar” para activar el modo de programador, se os habilitan tres botones pero el primero de izquierda a derecha es el que nos interesa, el que pone “CARGAR EXTENSIÓN SIN EMPAQUETAR” ya que le vamos simplemente a indicar la carpeta que a tal efecto creamos al comenzar este tutorial. Dice que es “sin empaquetar” porque para publicar nuestra extensión en internet debemos comprimirla en un formato específico y con una herramienta específica que no solamente ahorra tamaño sino que también agrega seguridad, pero no es tema de este tutorial, allí teneis los enlaces si quereis estudiarlos a fondo.

KS7000_ConoceTuIPv4 instalado en Chromium
KS7000_ConoceTuIPv4 instalado en Chromium

Así veremos cuando está instalada nuestra extensión, notad el icono al finalizar la barra de direcciones al cual al hacerle click nos muestra lo siguiente:

KS7000_ConoceTuIPv4 ventana emergente
KS7000_ConoceTuIPv4 ventana emergente

En esa ventana pequeñita es que se “ejecuta” nuestra página web con el enlace deseado, pues bueno, click y listo, se abre una pestaña nueva (ya que usamos el target “_blank”) y vamos a un dominio cuyo único trabajo es devolver la dirección pública IPv4 de nosotros los internautas. ¡Felicidades, hemos creado nuestra primera extensión!

Posibles problemas.

Seguimos insistiendo con las API‘s: si tenemos algún error en nuestro código, “una metida de pata”, el Chromium nos indicará y animará a seguir intentando; en este ejemplo a propósitos omitimos unas comillas de apertura, es decir, no la pusimos por pares y al cargar nos indica esto:

KS7000_ConoceTuIPv4 mensaje de error en comillas de apertura
KS7000_ConoceTuIPv4 mensaje de error en comillas de apertura

El mensaje indica que es un token desconocido, pues claro, no está bien delimitado el elemento y asume que queremos declarar un dichoso token: ¡todo esto por una simple comilla doble que omitimos!

Usando guiones JavaScript.

Recordemos que JavaScript lo podemos ubicar tanto dentro de un archivo html como en un archivo aparte js que sea llamado, desde luego, el fichero html. Ambos métodos son soportados por las extensiones en Chromium y vamos a revisar las dos opciones.

Guiones JavaScript internos.

Primero eliminamos la extensión que creamos en Chromium y vamos a agregar el siguiente guión JavaScript justo en la cabecera <head>:

 <script>alert("Aviso de JavaScript");</script>

A continuación reinstalamos desde nuestra consabida carpeta y hacemos click en el icono de la extensión instalada (si no os funciona, revisad de nuevo bien desde el principio de este artículo) y lograremos ver el siguiente aviso que os lo resaltamos en color verde:

KS7000_ConoceTuIPv4 JavaScript error
KS7000_ConoceTuIPv4 JavaScript error

Cuando hacemos click en diho botón veremos algo parecido a esto:

KS7000_ConoceTuIPv4 hash error
KS7000_ConoceTuIPv4 hash error

¿Qué ha sucedido aquí? Pues simple y llanamente que Chromium tiene ciertos requisitos de seguridad basados en recomendaciones de la W3C a fin de proteger la integridad de nuestro software. Para que se pueda ejecutar algún guión JavaScript insertado en un fichero HTML debemos calcular el hash (tenemos un tutorial que explica este tema) del fichero en cuestión en insertarlo en el manifiesto mediante un comando específico.

Para ello ya tenemos la mitad del trabajo hecho: el cálculo del hash lo hace Chromium sin siquiera pedirselo, así que lo aprovechamos para agregarlo en manifest.json y la idea es que al declararlo se obliga a compararlo con el generado al archivo HTML y si ambos coinciden se considera que no ha habido alteraciones a nuestro trabajo por parte de terceras personas con buenos o malos propósitos.

Debemos entonces incluir estas lineas en el manifiesto:

"content_security_policy": "default-src 'self' 'sha256-jLjrqnmi4O/pyY5/8e4eXAPbFQ6Vq8j76usKTBjmtb4='),

Recargamos con CTRL+R y repetimos el proceso, y ahora logramos ejecutar con éxito:

KS7000-ConoceTuIPv4 mensaje de JavaScript
KS7000-ConoceTuIPv4 mensaje de JavaScript

Para que tengamos presente la seguridad, si cambiamos un solo caracter de “aviso.html” inmediatamente Chromium dejará de ejecutar cualquier script que haya dentro del archivo. Para poder ejecutarlo de nuevo, debemos volver a actualizar el hash, pero surge la pregunta ¿y si el atacante también modifica el hash dentro del manifiesto? Si estamos en nuesstros propios ordenadores pues esto es más que dificil que suceda, un atacante no va a invertir tiempo y esfuerzo para malograr un solo ordenador, es lógico que busque atacar cientos o miles de computadoras así que el obejtivo sería un repositorio en internet y allí interviene lo que comentamos: para “subir” nuestra aplicación para se repartido por internet no solamente la debemos comprimir, SINO QUE TAMBIÉN LE TENEMOS QUE AGREGAR UN HASH AL ARCHIVO COMPRIMIDO (recordad la herramienta crxmake).

Para comprobar lo que afirmamos, solo basta modificar un solo caracter en el fichero aviso.html, nosotros le agregamos par de símbolos de admiración en el mensaje y aunque no afecte para absolutamente nada la seguridad de nuestro equipo de igual manera se muestra la línea que ha sido modificada (o, en la vida real “hackeada”), mirad:

KS7000_ConoceTuIPv4 modificado y el hash es distinto del registrado
KS7000_ConoceTuIPv4 modificado y el hash es distinto del registrado

Como nota curiosa, ya logramos que el guión se ejecute pero eso es solo lo que hará Chromium, es decir, el archivo aviso.html no será mostrado pero poco importa para nosotros porque simplemente estamos aprendiendo a programar, por ello nos olvidaremos de incluir una instrucción de este tipo que llamamos modal. Una ventana modal es aquella que se posesiona del enfoque de una aplicación y la única manera de continuar es obedecer la instrucción que ordena. Para que aprendamos los guiones que se guardan en un fichero aparte, externo a un fichero html, debemos presentar los conceptos de ejecuciones síncronas y asíncronas.

Guiones síncronos y asíncronos.

La principal diferencia entre ambos métodos estriba que mientras el método síncrono detiene su ejecución y espera el resultado o liberación de recursos, el proceso asíncrono se ejecuta por sí solo y va de manera independiente (interactue o no con el proceso que le dio origen). Se pudiera decir que ambos procesos “padre” e “hijo” deberían de alguna forma comunicarse y esto se debe hacer por medio del entorno de desarrollo o IDE, por sus iniciales en inglés de “Integrated Development Environment” o Ambiente de Desarrollo integrado, lo cual simplifica enormemente nuestro trabajo de programación ya que nos permite abstraernos en programar solamente sin importar el hardware o sistema operativo utilizado (si se quiere lo podríamos ver como “aislado por capas” como lo es el modelo OSIpara las redes de ordenadores).

Generando un proceso asíncrono.

Vamos entonces a modificar nuestro fichero “aviso.html” de la siguiente manera, resaltado en verde los cambios:

<!doctype html system "about:legacy-compat">
<html lang="es-419">
  <head>
    <meta charset="UTF-8">
    <title>KS7000</title>
  </head>
  <body>
    <h1>KS7000_ConoceTuIPv4</h1>
    <button id="conoceIPv4">¡Conoce tu dirección IPv4!</button>
    <p id="IPv4"></p>
    <script src="emergente.js"></script>  </body>
</html>

¡ IMPORTANTE ! : declarad vuestro guion externo en JavaScript DESPUÉS de los elementos, de lo contrario arrojará un error “null” indicando que los elementos no existen. Esto es así debido a que el analizador “parser” va de arriba hacia abajo, línea por línea, y el proceso asíncrono que lanzamos debe tener con qué trabajar. En este caso hay dos elementos que “pasaremos”: el botón identificado como “conoceIPv4” y el párrafo sin texto o “en blanco” identificado como”IPv4″.

Ahora vamos a crear nuestro elemento escrito en JavaScript. un guión que, por ahora, simplemente colocará un mensajito de texto en el párrafo identificado como “IPv4”:

document.getElementById("conoceIPv4").addEventListener("click", buscaIPv4);
  function buscaIPv4() {
    document.getElementById("IPv4").innerHTML = "vuestra IPv4 es:";
  }

Como veis es algo bien sencillo:

  • En la primera línea declaramos que al documento identificado como “conoceIPv4” le agregue un evento que esté en función de si el usuario hace click en el botón y que ejecute la función “buscaIPv4”.
  • A su vez la función buscaIPv4 POR AHORA lo único que hace es sustituir al elemento (párrafo) con el identificador “IPv4” y lo sustituya con el mensaje “Vuestra IPv4 es:”.

Al guardar y recargar con CTRL+R las extensiones instaladas va a volver a mostrarnos el mensaje de que los hash NO coinciden, copiamos el hash actualizado y lo pegamos en el fichero manifiest.json para volver a recargar y ejecutar, podréis observar algo muy parecido a esto:

KS7000_ConoceTuIPv4 mensaje de encabezado
KS7000_ConoceTuIPv4 mensaje de encabezado

¡LISTO, HEMOS CREADO UN PROCESO ASÍNCRONO! MUY FÁCIL, ¿CIERTO? 🤓

Creando

Comprobando compatibilidad en Mozilla Firefox.

Por medio de la cuenta Twitter de un desarrollador web de Mauritania tuvimos la excelente oportunidad de revisar cómo se desarrolla una extensión en Mozilla Firefox (versión 45 o superior) y además cómo preparse para presentarla al público, todo muy detallado y bien pensado.

Como Chromium y Firefox ambos comparten el entorno de programación chrome hace que compartan la misma estructura de datos pero se “llega” de diferente manera. Primero debemos introducir en la barra de direcciones el siguiente comando:

about:debugging

Presionamos la tecla intro y seleccionamos complementos y hacemos click en el botón “Cargar complementario temporario” (sí, suena extraño en castellano pero si queremos colaborar con las traducciones, pues las puertas están abiertas). Seleccionamos la carpeta con nuestro mini proyecto y listo ¡a comprobar!

KS7000_ConoceTuIPv4 ejecutado en Mozilla Firefox
KS7000_ConoceTuIPv4 ejecutado en Mozilla Firefox

Fuentes consultadas.

En idioma francés.

En idioma italiano.

En idioma inglés.

Content Delivery Network (CDN)

“Content Delivery Network” (CDN)  o Red de Entrega de Contenidos es la forma moderna de garantizar que nuestra página web pueda ser visitada por millones de usuarios y consiste, de manera muy simplificada, de repartir nuestro contenido estático a través de servidores ubicados físicamente en distintas partes del planeta, de tal manera que según sea la dirección IP del visitante se contacte con el servidor más cercano. Veamos ahora los detalles ¡vamos!

“Content Delivery Network” (CDN).

Content Delivery Network versus tradicional imagen de Wikipedia
Content Delivery Network versus tradicional imagen de Wikipedia

Para poder entender hacia dónde vamos debemos ver de dónde venimos.

El primer servidor web.

Tim Berner-Lee, inventor del hiperenlace y del internet tal como lo conocemos, arrancó con un ordenador avanzado para la época fabricado por la compañía “NEXT Computers” la cual fue fundada por el legendario Steve Jobs luego de que lo despidieron de “Apple Computer”, la empresa por él creada. En aquellos años 90 nosotros comprábamos la revista PCMagazine en castellano donde daban cuenta en un artículo que esas computadoras NEXT tenían la increíble cantidad de 1024 megabytes en RAM y costaba cada una más de 10 mil US$ ¡sorprendente!

Primer servidor web NEXT en el CERN
Primer servidor web NEXT en el CERN

A dicho computador le pegaron un papelito indicando que era un servidor y que no debía ser apagado, estaba alojando la primera página web del mundo y pocos usuarios se conectaban a ella, específicamente los investigadores del CERN (“European Organization for Nuclear Research” Organización Europea para la Investigación Nuclear).

Montando nuestra primera página web.

Pues hoy en día tenemos los mismos recursos -incluso rebasan- que contaban y disponían los investigadores europeos: ordenadores con más de 8 mil megabytes de RAM y 4 núcleos de 64 bits con conexiones fijas a internet con más de 1 mbps de velocidad y sin ningún límite de megabytes son comunes, ¿Qué nos impide montar en nuestro hogar u oficina nuestra página web? La limitación es que nuestro proveeedor de internet muy probablemente nos proporcionará una dirección IP dinámica: al apagar el modem y volverlo a encender tendremos una dirección IP diferente y a nuestros usuarios tendremos que volver a notificarles del cambio. Para evitar dicho inconveniente desde los albores del nacimiento del internet se utilizan los DNS “Domain Name Service” Servicio de Nombres de Dominios: son ordenadores que uno les pregunta por un dominio (dirección web) y nos devuelve la dirección IP para conectarnos al ordenador que contiene la página web deseada.

Lo anterior lo podemos simplificar con los teléfonos móviles celulares: cuando una amiga os da su número simplemente lo ingresamos al teléfono y le damos marcar y listo, la encontramos y conectamos. Pero luego recordar ese número es el problema, para ello nuestro celular tiene una agenda donde podemos colocar el nombre de la chica asociada a su número telefónico. En este ejemplo el DNS sería la agenda de contactos y el número de teléfono sería la dirección IP. Huelga decir que los DNS son más avanzados que la agenda de contactos: si un dominio cambia su dirección IP ésta es automáticamente actualizada, cosa que no hace el programita de agenda de contactos del celular (a menos que llamara todos los días a la chica confirmando el número telefónico ¡Qué locura!).

Tráfico hacia nuestra página web.

Con este escenario, un ordenador en nuestra casa u oficina, con un acceso a internet las 24 horas del día sin limites de megabytes y una dirección IP fija y un DNS configurado estamos prestos a difundir al mundo nuestro trabajo sobre el software libre. Pero para hacerle honor a la verdad, lo que distingue un servidor web de un ordenador normal es la redundancia de sus componentes, así que tienen al menos dos fuentes de poder (si una se “quema”queda la otra funcionando y se puede cambiar sin necesidad de apagar el servidor)tienen al menos dos discos duros en RAID (escriben y leen los mismos datos en ambos discos) y también se pueden reemplazar sin apagarlo (al conectar un disco nuevo automáticamente la tarjeta madre copiará los datos del disco viejo al nuevo y “emparejará” la información), memoria RAM de seguridad que -adivinen- internamente son dobles y almacenan y comparan ambas copias constantemente y también tienen dos o más tarjetas de red, generalmente ethernet con cables de cobre o fibra óptica, de igual manera si una falla queda la otra funcionando -y no se pueden reemplazar porque son integradas a la tarjeta madre pero se puede adicionar una(s) en una(s) ranura(s) PCI libre-.

En cuanto a qué podremos hacer con un ordenador con dos o más tarjetas de red (si tenéis un ordenador portátil con tarjeta de red inalámbrica y  ethernet podéis hacer pruebas)  varios usos le podemos dar:

  • Ambas tarjetas de red conectados a un concentrador/enrutador en una red de área local con diferentes direcciones IP (por supuesto de área local): podemos balancear la carga para enviar nuestra página web por ambas tarjetas, eso se configura facilmente con ifenslave para luego aplicar modprobe.
  • Una tarjeta de red conectada al modem y la otra al concentrador/enrutador para trabajarlo como “puente”.
  • Una tarjeta de red conectada al enrutador/concentrador y la otra a otro ordenador con una base de datos para aislar y aumentar la seguridad de nuestra información (páginas web dinámicas).
  • Una tarjeta de red conectada a un concentrador y la otra a otro para crear dos segmentos de red.
  • Muchas otras combinaciones (aquí imaginen ustedes).

Esto que acabamos de explicar es para ir “abriendo la mente”, para lo que luego queremos explicar acerca de los CDN’s.

Para continuar optaremos por configurar nuestro modem/concentrador/enrutador (hoy en día se puede dar los tres aparatos en uno, por eso decimos que tenemos más poder de hardware que los investigadores del CERN en los años 90). En todo caso explicamos que:

  • Un modem, generalmente ADSL, nos conecta a internet.
  • Un enrutador toma una dirección IP asignada a nuestro modem (que está en “modo puente”) y traslada las peticiones (NAT) a nuestra red de área local (LAN).
  • Un concentrador amplía la cantidad de puertos necesarios para conectar hasta 255 ordenadores en un segmento de red (la mayoría de enrutadores tienen 4 puertos físico alámbricos, son pocos en realidad).

Así las cosas nuestro enrutador recibe las peticiones y las reenvía a nuestro servidor web: hasta allí todo va bien, pero ¿qué sucede si recibimos más visitas?

Ampliando la cantidad de ordenadores en una LAN.

Con 4 ordenadores podemos realizar el siguiente esquema para atender más visitantes:

  • Ordenador 1: recibe las peticiones y balancea la carga de trabajo hacia los ordenadores 2 y 3.
  • Ordenadores 2 y 3 son los servidores web como tal, reciben las cabeceras de peticiones de ordenador 1.
  • Ordenador 4: será donde guardemos nuestra página web y que los ordenadores 2 y 3 se encargarán de verificar constantemente si tienen la última versión de nuestra página web.

Este esquema tiene como ventaja, por supuesto, el poder atender más visitantes, manteniendo nuestro trabajo original en el ordenador 4 y teniendo respaldos en los ordenadores 2 y 3, el punto débil de la cadena sería el ordenador 1, que balancea la carga ya que si falla se cae por completo nuestro dominio, ojo con eso. Como desventaja podríamos mencionar, entre otras, el registro de los visitantes (quién ha sido atendido por ordenador 2 y quién por ordenador 3), problemas con las carpetas temporales en el caso que nuestros usuarios necesiten “subir” archivos a nuestra página web y con respecto al lenguaje PHP el almacenamiento de las variables de sesión que no serán iguales para todas las páginas (aquí debemos aclarar que nuestra página web es un sitio web conformado por varias páginas que pueden ser servidas tanto por ordenador 2 y ordenador 3: un visitante puede ver una hoja en ordenador 1 y al cabo del tiempo al volver a visitar el balanceo de carga lo envia a ordenador 3 por lo tanto las variables de sesión PHP serán con distintos valores, lo que pudiera ocasionar problemas de programación -“amnesia” de las aplicaciones-).

Añadiendo más “ancho de banda” a nuestra conexión a internet.

Pues que llega un momento que nuestro humilde modem ADSL no da para más velocidad, así que le pedimos a nuestro Proveedor de Servicio de Internet (“Internet Service Provider” ISP) nos suba la velocidad pero va a ser que no, lo máximo ya lo tenemos, 10 mbps y ADSL2 que llega a 25 mbps no está disponible… Pues agregamos otra línea telefónica y otro modem y en teoría nuestro ISP debería colocarlos en modo vinculado “bonding”: con la misma dirección IP transmite por ambos modem entre nuestra casa u oficina hasta la central telefónica más cercana. ¿Recuerdan la redundancia de tarjetas de red en los servidores? Pues bueno, aquí es lo mismo, es una habilitación en una de las capas del modelo OSI, específicamente la capa física (de hecho cada modem en sí mismo cumple con esa capa y cada capa es independiente de las otras capas tanto por encima como por debajo).

Servidores espejos “mirrors”.

Pues he aquí que nuestro negocio o portal educativo ha crecido y expandido en todo nuestro país, o incluso hacia el exterior , así que decidimos contratar alojamiento web en nuestro país y/o el exterior. En esos ordenadores contratados colocaremos una sincronización de archivos para que al modificar nuestros ficheros se copien, al cabo de cierto tiempo, a los servidores espejo.

Como ya tenemos configurado nuestro balanceo de carga lo único que tenemos que configurar es que se redirija hacia unas direcciones IP que no están en nuestra red de área local, sino en internet. El pequeño detalle de esta configuración estriba en que nuestro alojamiento debe ser dedicado, tal como tenemos montado en nuestra casa u oficina, si es alojamiento compartido deberemos comprar otro dominio web porque de esa manera es que sabe un servidor web compartido qué datos mostrar al visitante.

shared hosting
shared hosting

Si contratamos un servidor dedicado bien puede ser una máquina real o, lo que es más común hoy en día, una máquina virtual que igual compartiremos con otros sitios web un ordenador físico pero con varias máquinas virtuales que tendrán sus propias tarjetas de red virtuales con sus propios y únicos MAC por los cuales se podrán identificar y asignar sus propias direcciones IP fijas (esto es particularmente atractivo para cuando migremos, por fin, a las direcciones IPv6)

Inconvenientes de los servidores espejos.

Pues como ya se habrán percatado, nuestra debilidad sigue siendo el “balanceador de carga”: nuestro dominio y por medio de los DNS sigue devolviendo una única dirección IP, la de nuestro ordenador en nuestra casa u oficina, ¡pues he aquí la brillante solución de los CDN!

CDN “Content Delivery Network”.

De nuevo simplificaremos al máximo para ilustrar de manera didáctica sobre el como funciona. A nivel mundial las direcciones IP están repartidas por grandes proveedores de acceso a internet o incluso por países enteros. Acá en Venezuela CANTV tiene su rango de direcciones IP asignadas, así que para los servidores web es “facil” determinar si nuestro visitante esta conectado por medio de ese proveedor de internet, simplemente comparando la dirección IP contra los rango registrados. Pueden incluso llegar  a determinar desde cual ciudad se conectan. Basado en esto:

  • Una empresa decide montar un CDN a nivel mundial, así que va país por país donde montar una granja de servidores con acceso a internet por medio de algún proveedor que a su vez tiene su rango de direcciones IP asignadas. Aparte de la compra de conexión en sí como tal, también se incluye la compra de un rango de direcciones IP para asignarlas a los ordenadores de la nueva granja.
  • El siguiente paso es configurar con algunas de esas máquinas unos servidores DNS (generalmente uno principal y otro secundario). Dichos servidores DNS estarán a la orden de los servidores DNS del proveedor de internet y llevarán registro de los dominios web que van a alojar.
  • Este procedimiento se repite país por páis, o región por región.
  • Una vez tengan “armada” la red es hora de ofrecer el servicio, no sin antes “unificar” todos sus servidores DNS para que operen como un conjunto armónico.

¿Cómo funciona el CDN?

Al comprar nosotros un alojamiento en CDN lo primero que tenemos que hacer es configurar ante quien nos vendió el nombre o dominio web y establecer los DNS de la empresa que ofrece el servicio CDN. Nuestro trabajo es seguir manteniendo nuestro “balanceador de carga” como siempre lo hemos hecho pero con privilegios especiales para que los ordenadores del CDN tengan acceso y copien nuestra página web y la distribuyan por cada una de las granjas de servidores que nombramos anteriormente.

Lo brillante de la idea de los CDN es analizar la dirección IP de un visitante de nuestra página web RECORDAD que primero tiene que pasar por los DNS del CDN para saber la dirección IP de nuestro balanceador de carga… PUES VA A SER QUE NO porque si nuestro visitante está más cerca de una granja de servidores del CDN pues le pasa esa dirección IP al visitante de una manera totalmente transparente, al fin y al cabo es una copia exacta de nuestra web lo que le va a ser retribuida al internauta.

Un  asunto importante para un CDN es el poder identificar según la dirección IP recibida del webnauta de dónde viene para redirigirlo a la granja de servidores más cercana -y que contiene copia de nuestra página(s) web-. Es por ello que muchas empresas ofrecen para descargar sus bases de datos, con su respectivo “manual de uso”, por ejemplo, desde MaxMind podeis visitar su página designada al respecto en este enlace. Esencialmente se resume en este comando, siempre respetando y considerando de no abusar del servicio:

wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz

Dicha base de datos es utilizada por aplicaciones de seguridad para proteger servidores web de ataques maliciosos. Dado el caso que suframos un ataque masivo de denegación de servicio (millones de dispositivos al mismo tiempo visitan nuestra página web con la intención de saturarla y colapsarla) pues simplemente será repartida a lo largo y ancho del planeta. Puede darse el caso que el ataque provenga, por ejemplo, de millones de dispositivos infectados que están localizados fisicamente en Europa: pues bien las granjas de servidores ubicadas en Europa (digamos que hayan tres, una en Francia, otra en Inglaterra y otra en Italia) solo esas tres granjas de servidores serán colapsados, si es que pueden, mientras que las demás granjas en el resto del mundo mantendrán nuestra página web incólume.

 

Conclusión.

Si queremos simplificar a tope podríamos decir, en una gran perspectiva, que los CDN actúan como unos “balanceadores de carga” pero a una gran medida, no sin antes realizar un arduo rabajo de sincronización de DNS y contenidos web. Esperamos les haya sido útil la información.

Fuentes consultadas.

En idioma castellano.

En idioma inglés.

Recursos multimedia.

Calculando factoriales de números grandes

El día de ayer por medio del perfil de línea de tiempo del Doctor Juan González observamos el interesante artículo tutorial sobre Python publicado por Juan J. Merelo Guervós el cual incluye retos de programación. Ni tardo ni perezoso, a pesar de llegar cansado a mi hogar, y tras una vigorizante taza de café negro con leche de avena sin azúcar nos dimos a la tarea de practicar algunas cositas para mantener el cerebro en forma y al día con las novedades en programación.

Calculando el factorial de un número.

Definición.

No vamos a hacer esta entrada muy profunda, ya que debemos ir a trabajar para ganarnos el pan de cada día, directo y rápido: el factorial de un número viene expresado por la multiplicación sucesiva de sus antecesores, uno a uno, hasta llegar a uno y se denota por ” n! ” ; así, por ejemplo 5!= 5 x 4 x 3 x 2 x 1 = 120 (las equis indican multiplicación).

El reto.

Pues arroja el guante el sr. Merelo con una función recursiva escrita, por supuesto, en lenguaje Python para calcular un factorial y tras ensayo y error llegamos a una satisfactoria y muy parecida a la ya famosa y escrita por todos lados en internet (para ser honestos en algún momento vimos esta función pero no recordabamos… hasta que el buscador DuckDuckGo acudió en nuestra ayuda, un asistente tan capaz -en memoria- como todas las asistentes que tuvo Albert Einstein -que en paz descansen, Valentine Bargmann y el Doctor Einstein-).

Para ilustraros cómo funciona, aprovechando nuestro mundo tecnológico –y añorando el gis y el pizarrón- os colocamos un gif animado tomado de penjee.com, un sitio web dedicado también a la enseñanza de Python:

Función factorial animada tomada de penjee.com
Función factorial animada tomada de penjee.com
def factorial(num):
  if num == 1:
    return 1
  else:
    return num * factorial(num - 1)

Calculando el factorial de un número grande.

Factorial, fórmula y definición
Factorial, fórmula y definición

Hasta acá todo muy bien, pero el reto no finalizaba allí, una segunda pregunta era ¿qué tal calcula los números grandes? Como bien podéis imaginar, el multiplicar y multiplicar en ordenador pues en algún momento se nos agota la memoria suponíamos nosotros… pues que aquí está la pega del asunto, tras calcular el factorial 120! de manera fácil (en Wikipedia en inglés denotan que normalmente el máximo factorial que se puede calcular con un procesador de 64 bits en una variable de tipo entero es 20! –ya nosotros hemos comentado el poder de cómputo de los procesadores y sistemas operativos de 64 bits-) pues nos envalentonamos a ir “al infinito y más allá”.

python factorial.py con n = 120 (ciento veinte)
python factorial.py con n = 120 (ciento veinte)

Siendo así la cosa le establecemos a 1200 (un mil doscientos) a la función de marras y nos arrojó este lindísimo mensaje de error que os mostramos:

python factorial.py con n = 1200 (mil doscientos)
python factorial.py con n = 1200 (mil doscientos)

Pero leyendo nos percatamos que el problema no es el desbordamiento de memoria, no,  el desbordamiento es un error en la profundidad de recursión:

RecursionError: maximum recursion depth exceeded in comparison

El contrareto.

Ya esto se salía del reto impuesto, es un contrareto que nos presenta Python pues claro, en un entorno de programación uno debe siempre imponer límites considerando que aún no ha llegado la computación cuántica (y aún así ésta tiene límites en este universo). Indagando, y hay bastante material sobre el tema, llegamos a la librería sys encargada de manejar tales asuntos y de hecho el manual en línea de Pyton nos advierte:

Set the maximum depth of the Python interpreter stack to limit. This limit prevents infinite recursion from causing an overflow of the C stack and crashing Python. The highest possible limit is platform-dependent. A user may need to set the limit higher when she has a program that requires deep recursion and a platform that supports a higher limit. This should be done with care, because a too-high limit can lead to a crash.

Que traducimos al castellano:

Establece el límite de la profundidad máxima de la pila del interprete Python. Este límite previene una recursión infinita ocasionando un desbordamiento en la pila (del lenguaje) C y la consecuente falla de Python (Dios nos ampare que alguien crea que Python es falible†). El límite más alto posible es dependiente de la plataforma empleada. Un usuario puede necesitar ajustar el límite superior cuando tenga un programa que requiera una mayor recursión y la plataforma que lo soporta lo permita. Esto debería hacerse con cuidado porque un límite muy alto puede conducir a un fallo (Dios nos ampare que alguien crea que Python es falible†).

†(Nota del traductor en tono de sarcasmo).

Python recursion limit get and set
Python recursion limit get and set

O inventamos o erramos.

Don Simón Rodríguez: "Inventamos o erramos".
Don Simón Rodríguez: “Inventamos o erramos”.

Como nuestro insigne Don Simón Rordríguez nos legó, debemos inventar y a lo sumo fallar (y reintentar y así sucesivamente hasta lograr inventar) nosotros pensamos ¿Y si establecemos el límite superior de la pila de procedimientos (límite de recursión) precisamente de manera recursiva? 🤔

Pues acá vamos entonces:

import sys
def factorial(num):
  '''Return large factorial by Jimmy Olano Sayago
               (GNU General Public License v3.0) '''
  if num<=1:
    return 1
  else:
    sys.setrecursionlimit(sys.getrecursionlimit()+1)
    return num * factorial(num - 1)

file = open('large_factorial_result.txt', 'w')
cad = factorial.__doc__
file.write( cad )
file.write( ' factorial(21700): ' )
file.write( str( factorial( 21700) ) )
file.close

Al tener nosotros establecida la función, por tanteo y utilizando un procesador AMD A8-6600K APU (64 bits, 4 núcleos y 8 gigabytes en RAM) llegamos un valor de 21700! el cual ocupa 86400 digitos. Esencialmente el guion que hicimos basados en la clásica función recursiva de cálculo factorial es aumentar el límite de pila de Python de manera recursiva para luego abrir un archivo de texto y guardar allí el resultado.

El delicado tema de los typos de variables y la memoria disponible.

Consultamos muy diversos reportajes sobre el tema del manejo de la memoria y las variables pero el que fue revelador para nosotros es uno escrito hace más de once años pero que goza de plena vigencia: una comparación sobre cómo trabajan las variables los lenguajes C y Python.

Tiene su teoría y abunda su práctica y probamos los diferentes ejemplos y nos resultó en valore comprobatorios contra lo que se afirma en dicha entrada pero la conclusión es tan excelente que se las traemos en idioma inglés y la traducimos al castellano:

Python removes this confusion, there is only the integer object. Does it have any limits? Very early versions of Python had a limit that was later removed. The limits now are set by the amount of memory you have in your computer. If you want to create an astronomical integer 5,000 digits long, go ahead. Typing it or reading it will be the only problem! How does Python do all of this? It automatically manages the integer object, which is initially set to 32 bits for speed. If it exceeds 32 bits, then Python increases its size as needed up to the RAM limit.

La traducción hecha por nosotros:

Python elimina esta confusión (de variables), hay solo el objeto entero. ¿Tiene algún límite? Muy tempranas versiones de Python tuevieron un límite que luego más tarde fue removido. Los límites ahora son establecidos por el monto de memoria que usted tenga en su computadora. Si quiere crear un entero astronómico de 5 mil dígitos, ¡adelante! ¡Escribirlo o leerlo será el único problema! ¿Cómo Python hace todo esto posible? Pues automáticamente dirige el objeto entero, el cual inicialmente estaba configurada a 32 bits por motivos de velocidad. Si excede los 32 bits, entonces Python incrementa su tamaño tanto como se necesite hasta llegar al límite de la memoria RAM.

Así como lo podéis leer, en el año 2006 se consideraba “astronómico” una cifra de 5000 dígitos, ¡PUES HE AQUÍ QUE CALCULAMOS UN FACTORIAL CON 86400 DÍGITOS! Para nosotros es todo un logro digno de dedicarle una entrada y una pequeña nota en las Wikipedia(s).

Sometido a consideración por la comunidad de programación y comunidad matemática.

De inmediato subimos el guion y su resultado (utilizando el idioma inglés) a Gist mantenido en línea por GitHub.com (¡gracias!) y “tuiteado” con la etiqueta #Python y #1linepy tal como recomienda el sr. Merelo:

Experimento social.

Como experimeto social hemos cometido una torpeza en la fórmula cuando establecemos:

if num<=1:
  return 1

El objetivo es detectar cuántas personas realmente analizan nuestra propuesta y nos hacen llegar sus observaciones (se especula que el mismísimo Leonardo DaVinci codificaba mal sus planos a propósito por si caían en manos enemigas) ya que el cálculo de factoriales está supeditado al campo de los números positivos, ya sean reales o imaginarios (esto es así porque el cálculo factorial es clave en la determinación de combinaciones y permutas, todas ellas en el campo de los números positivos).

También hemos publicado en Wikipedia en inglés nuestra experiencia (y próximamente en castellano, francés, italiano, portugués, alemán y ruso en la medida de lo posible y de nuestro tiempo libre) para determinar cuales sociedades unidas por un idioma común aceptan o rechazan nuestra propuesta (cada idioma Wiki tiene sus wikipedistas que algunas veces nos han “echado para atrás” nuestras ediciones por diversos motivos variopintos).

 

Conclusión: no hemos llegado aún al infinito, menos más allá.

Una inquietud que tenemos es la gran cantidad de ceros al final del resultado y una cosa que nos tranquiliza es la serie de resultados hasta 20! que va aumentado la cantidad de ceros a la derecha. Lo lógico es que si estamos multiplicando pues “corremos la coma hacia la derecha” y se debe, desde luego, rellenar con ceros para ello.

Aún falta por determinar hasta qué punto alcanza nuestro hardware su límite, podremos hacer un ciclo “for” que arranque con este último valor de 21700! e irlo incrementando y guardando en archivos cuyos nombres tengan el valor calculado apara identificarlos hasta que simplemente falle Python, ¡PERO ESPEREN, HAY MÁS!

Pensamos que arrancando nuestro sistema operativo Ubuntu 16.04 LTS en modo terminal, sin cargar interfaz gráfica y “tumbando” los servicios diversos -Apache server, MySQL, etc.- y los más que se puedan de systemd ganaremos más memoria y compararemos resultados a ver si influye y si es así, cuánto influye, ¡SOMOS TODO OÍDOS A VUESTRAS IDEAS AL RESPECTO POR MEDIO DE NUESTRA CUENTA EN TWITTER @KS7000!

Fuentes consultadas.

En idioma castellano.

En idioma italiano.

En idioma inglés.

PHP Simple HTML DOM Parser

Para abrir el mes de junio seguimos el hilo en nuestros artículos que buscan difundir el conocimiento libre del Patrimonio Tecnológico de la Humanidad. En anterior oportunidad estudiamos PHP curl, una herramienta basada en cURL y por ende en libcurl (¡ea, esto último no lo mencionamos allá!). Como en ese caso obtuvimos un método para descargar páginas web enteras, incluso si hay que pasarle datos con el método POST y/o hay que introducir usuario y contraseña. Esta entrada busca extraer, analizar e incluso modificar dichos datos ¡vente con nosotros!

PHP Simple HTML DOM Parser.

Presentación.

Buscábamos una “parser” o analizador código HTML y aunque PHP tiene su modelo establecido nos decantamos por algo más fácil pero con el inconveniente que debemos apoyar la licencia de uso del Instituto Tecnológico de Massachusetts (“MIT license”) y que NO viene integrado al lenguaje PHP. Lo bueno es que apenas son 65037 bytes en un archivo con un guion escrito en lenguaje PHP para que funcione (la licencia nos obliga a distribuir completo los archivos de ejemplos y manuales, todos escritos en idioma inglés).

El analizador de HTML (y XML) que veremos y aprenderemos a usar tiene el pomposo nombre de “PHP Simple HTML DOM Parsercon todas las implicaciones que derivan de llamar “simple” al D.O.M. (“Document Object Model”).

Document Object Model.

El Modelo de Objeto Documento es una norma propuesta por el Consorcio World Wide Web o W3C que son quienes hacen las recomendaciones y sientan las bases, de facto, del Web creado por el Doctor Tim Berners-Lee. En dicho papel de trabajo, a nuestro modo de ver las cosas, se propone que una página web es un documento y todo lo que está contenido en ella está representada por nodos. Si nos ponemos a ver tiene sentido porque la norma HTML5 establece unas sub divisiones que a su vez contienen títulos, sub títulos, párrafos, listas, etc.

Este concepto es mucho más amplio porque contempla, aparte de propiedades, también métodos que por definición HTML5 no contempla y para respetar la neutralidad hacen de la vista gorda del JavaScript (¿definirán algún día al CSS para suplantarlo? Sí, los sabemos, nuestro pensamiento siempre es profano).

El DOM está estructurado sobre tres pilares básicos:

  • “Core DOM”: modelo normativo para todos los tipos de documentos.
  • “XML DOM”: para documentos XML (febrero, 1998).
  • “HTML DOM”: no menos importante, aunque aparezca en tercer lugar, para documentos HTML.

Autores.

La idea original proviene de José Solorzano quien comenzó un proyecto bautizado como “HTML Parser for PHP 4” (dale con esto de los nombres largos ¿será que estoy leyendo muchos artículos en inglés y me estoy contagiando? Porque el idioma castellano es bastante prolijo…) que como podemos ver funciona con PHP 4 y pues va a ser que ya está descontinuado (incluso tienen un avisito recomendando el proyecto que vemos hoy acá).

Basado en ello S.C. Chen (me578022@gmail.com) programó una versión actualizada y basada en DOM con ayuda de Yousuke Kumakura y publicada en SourceForge, un alojador de contenido de software de código abierto que alberga más de 430.000 proyectos (3,7 millones de usuarios y 42 millones de clientes). Solo sabemos que S.C Chen es famoso a nivel mundial por su ópera prima que trajimos en este momento a colación.

Core DOM.

(pronto desarrollaremos este tema).

XML DOM.

Para poder entender el HTML DOM debemos primero estudiar y aprender el XML DOM y a continuación haremos nuestro racionamiento y sustento.

Concepto de XML.

“eXtensible Markup Language” o Lenguaje de Marcado Extensible (lo siento por el castellano pero lo seguiremos identificando como XML dado su impacto de facto en el mundo entero) es un lenguaje que “describe” como hacer las cosas y que además se puede ampliar en cualquier momento conservando una retrocompatibilidad. Fue diseñado para almacenar y transportar datos y que, además, pudiera ser leído por ordenadores y humanos por igual.

Si queréis leer sobre nuestra disertación acerca de lo que es un lenguaje de marcado, os invitamos a leer nuestro tutorial en línea sobre HTML. XML es guardado en ficheros codificados, generalmente, en UTF-8 para lograr compatibilidad con los diversos idiomas del mundo, nuestro tutorial sobre HTML5 también habla  y describe al respecto en forma detallada.

Normas XML.

Hay unas normas destacadas que mencionaremos y que a futuro, en la medida que tengamos tiempo para ello, le publicaremos sus diferentes entradas en nuestro humilde blog.

  • XML AJAX
  • XML DOM
  • XML XPath
  • XML XSLT
  • XML XQuery
  • XML DTD
  • XML Schema
  • XML Services

¿Qué es y qué NO es XML?

Aparte de lo que ya definimos, hay otros detalles que decir acerca del XML: fue diseñado para ser autodescriptivo, ya que a diferencia del HTML tiene muy pocos “comandos” o etiquetas y el XML como tal no hace absolutamente nada por sí solo. Esa es entonces la principal diferencia con HTML, que se enfoca en presentar los datos mientras que XML se enfoca en transportar datos.

Decimos que se puede extender ya que nosotros mismo “inventamos” nuestros propias etiquetas, así que no tenemos limitación pero una vez hallamos agregado más etiquetas a una información preexistente ésta seguirá siendo completamente leída y manipulada por distintas aplicaciones sin ningún tipo de problema.

Por supuesto, hacemos la advertencia que hablamos de extender, no de contraer: al eliminar algún dato por supuesto que las aplicaciones ya no podrán realizar su trabajo completo, y en muchos casos se negarán a realizarlo de plano.

Elementos de un documento XML.

Un documento XML está constituido por un elemento raíz el cual tiene elemento ramas o nodos que a su vez pueden contener subelementos y así sucesivamente. Cada elemento a su vez puede contener atributos.

De manera obligatoria un documento XML debe tener un elemento raíz, y aunque un prólogo no es obligatorio ni forma parte del documento es muy recomendable agregarlo; siempre va al principio del documento.

La función del prólogo es denotar la versión XML del documento y, de manera adicional, la codificación de caracteres el cual ya dijimos UTF-8 es lo más recomendable. La sintaxis del prólogo comienza con un símbolo “menor que” o mejor dicho, un corchete angular de apertura, ya que no estamos hablando de matemáticas en este caso (pero ayuda muchísimo a entender el concepto de aperura y cierre). Debe cerrar con un símbolo “mayor que” o corchete angular de cierre. Además de los dos símbolos anteriores se necesitan dos signos de interrogación de cierre y los contenidos deben estar entrecomillados para lo cual recomendamos las comillas simples, esto nos ahorra problemas para cuando vayamos a programar. Veamos un ejemplo de prólogo:

<?xml version='1.0' encoding='UTF-8'?>

El prólogo es un caso especial, y ya dijimos que no forma parte del documento, por lo tanto tiene distintas reglas que las aplicadas a los elementos, los cuales pasamos a describir en la siguiente sección.

Sintaxis de los elementos XML.

  • Cada uno de los elementos debe tener su correspondiente cierre pero con una barra invertida, por ejemplo:
    • <elemento> texto </elemento>
  • Los nombres de los elementos distinguen mayúsculas de minúsculas por lo tanto <elemento> no es igual a <Elemento>.
  • Los nombres de los elementos deben comenzar con una letra o en su defecto con un guion bajo ” _ “.
  • Los nombres de los elementos no pueden comenzar con “XML” o sus combinaciones de mayúsculas y/o minúsculas.
  • Los nombres de los elementos no puden contener espacios (de hecho un espacio denota que comienza un atributo, por eso no pueden contener espacios).
  • Los subelementos deben estar correctamente anidados dentro de los elementos, ejemplo:
    • <elemento><subelemento>valor</subelemento><elemento>
  • Los atributos de los elementos deben estar entrecomillados (lo mismo que dijimo para el prólogo se aplica en este caso), ejemplo:
    • <elemento principal=’si’> dato </elemento>
  • Como tal vez hayan captado, hay unos caracteres especiales en los documentos XML que no podremos usar directamente porque se presta a confusión para los ordenadores a la hora de leer el documento XML por lo tanto debemos sustituirlos por otros caracteres si queremos usarlos como datos:
    • Corchete angular de apertura “<” lo sustituimos por “&lt;” (recordad “lt”= “less than”, menos que).
    • Corchete angular de apertura “>” lo sustituimos por “&gt;“(recordad “gt”= “greater than”, mayor que).
    • Ampersand o “et” (proviene del latín, como en “etcétera”): “&” lo sustituimos por “&amp;“.
    • Apostrofo ” ” lo susituimos por “&apos;“.
    • Comillas dobles ” ” las sustituimos por “&quot;” (“quotation mark”).
  • Si queremos o necesitamos dejar un comentario para nosotros los seres humanos y que sea ignorado por el ordenador hacemos lo mismo que en el lenguaje HTML, lo encerramos entre los siguientes signos:
    • <!– comentario –>
    • Nota: dentro de un comentario no podemos escribir dos guiones juntos ya que dos guiones juntos indican inicio y fin de comentario, así que se prestaría a confusión para los ordenadores.
  • En los documentos XML debemos tener en cuenta que todo espacio es considerado como tal, es decir, los espacios se conservan y son un dato en sí mismo y así será leído ya quedará de parte de la aplicación el cortar o comprimir espacios “innecesarios”. Este comentario lo hacemos porque los documentos XML pueden ser leídos -y editados- por nosotros los humanos y un espacio en blanco mal colocado de nuestra parte hará que la aplicación que va  a leer los datos le suceda una excepción pero nosotros no veamos el error al abrir el archivo nosotros mismos.
  • Parecerá una tontería pero el caracter que indica el final de una línea es el caracter LF o “Line Feed” OSEA al caracter ASCII 10 y debemos tener siempre presente que en el sistema operativo Windows se utiliza LF más CR (ASCII 10 y 13 respectivamente) y en los viejos sistemas operativos Mac solo CR.

Características de los elementos de un documento XML.

  • Un elemento comienza desde el primer corchete angular de apertura hasta el último corchete angualr de cierre.
  • Un elemento puede contener:
    • Nada (pues eso, vacío, ni siquiera un espacio -si tuviera un espacio no sería vacio-).
    • Ya que introducimos el concepto de elemento vacio -y esto debería estar en la sintaxis- un elemento tácitamente vacio lo podremos denotar de la siguiente manera y ambos son iguales y válidos:
      • <elemento />
      • <elemento></elemento>
    • Texto -datos, para los ordenadores-.
    • Otros elementos -recordad anidar correctamente-.
    • Cualquier combinación de los tres anteriores, las combinaciones son infinitas y por ende decimos que son extensibles -y retrocompatibles-.

Una breve aclaratoria sobre los atributos.

Hay que tener especial cuidado con los atributos que le coloquemos a los elementos. Para no caer en abstracciones les haremos un caso práctico: consideremos un elemento llamado “persona” y lo que eso significa para nosotros los castellanohablantes.

<?xml version='1.0' encoding='UTF-8'?>
<persona></persona>

Ahora consideremos colocarle un atributo de género femenino o masculino:

<?xml version='1.0' encoding='UTF-8'?>
<persona sexo='masculino'>
    <nombre>Pedro</nombre>
</persona>
<persona sexo='femenino'>
   <nombre>María</nombre>
</persona>

Como vemos podemos “cargar” en memoria de ordenador solamente los hombres -o las mujeres- pero la aplicación que lee dichoa rchivo debe estar programada, de manera previa, a buscar esos dos géneros solamente ¿Qué sucedería si surgiera un tercer tipo de sexo, como por ejemplo hermafrodita?

<?xml version='1.0' encoding='UTF-8'?>
<persona sexo='masculino'>
    <nombre>Pedro</nombre>
</persona>
<persona sexo='hermafrodita'>
 <nombre>Michelle</nombre>
</persona>
<persona sexo='femenino'>
   <nombre>María</nombre>
</persona>

No habría forma ni manera que la aplicación pudiera “ampliarse” para que leyera datos adicionales ampliados, así que es una mejor idea plantearlo de la siguiente manera:

<?xml version='1.0' encoding='UTF-8'?>
<persona>
    <sexo>masculino</sexo>
    <nombre>Pedro</nombre>
</persona>
<persona>
    <sexo>hermafrodita</sexo>
    <nombre>Michelle</nombre>
</persona>
<persona>
    <sexo>femenino</sexo>
    <nombre>María</nombre>
</persona>

Como veís, colocado de esta manera la aplicación puede ir generando una matriz con los distintos nuevos tipos de valores tal como lo hace con los valores en sí mismos. Aparte de esta ventaja debemos recordar también que los atributos NO pueden contener múltiples valores y tampoco pueden tener estructuras tipo árbol, entonces ¿para que diantres sirven los atributos? Antes de responder esta pregunta queremos dejar en claro algo más sobre los atributos: los atributos son elemento fuertemente tipados -como decimos en los lenguajes de programación-, son estructura rígidas que son difíciles de cambiar a futuro pero que debido a esto podremos tomar ventaja; veamos la siguiente sección.

Eliminando ambigüedades en el nombrado de los elementos.

Como ya bien sabemos los documentos XML nos sirven para almacenar datos y debido a que nosotros los seres humanos asignamos un nombre para todo en nuestro universo -y a medida que lo seguimos descubriendo- no siempre escogemos nombres únicos. Tomemos por caso la palabra “banco”: tal vez primero pensemos en una institución financiera pero es que también un “banco” es un objeto sobre el cual podemos sentarnos.

Si por alguna idea peregrina nos damos a la tarea de guardar datos de ambos conceptos en un mismo documento XML debemos hallar una manera de diferenciarlos para que no haya lugar a dudas. Para ello podemos -y debemos- asignar un prefijo para eliminar cualquier duda, pero ¿qué prefijo usaremos? Pongamos por caso que los bancos -instituciones financieras- le colocamos el prefijo “i:” y los bancos -objetos- los prefijamos con “o:” (notemos que no violan la sintaxis de nombres de elementos ya que comienzan con una letra, no comienzan con “xml” ni contiene espacios):

<?xml version='1.0' encoding='UTF-8'?>
<raíz>
    <i:bancos>
        <i:nombre>Banco de Venezuela</i:nombre>
        <i:nombre>Banco Mercantil</i:nombre>
        <i:nombre>Banco Bicentenario</i:nombre>
    </i:bancos>
    <o:bancos>
        <o:nombre>banco de madera</o:nombre>
        <o:nombre>banco de metal</o:nombre>
        <o:nombre>taburete</o:nombre>
    </o:bancos>
</raíz>

Rapidamente notamos, si fueramos un lector ajeno que recibiera este documento XML, ¿qué diablos significa ambos prefijos, aparte de separarlos sintacticamente? Bien podríamos colocar un comentario para hacer alusión a qué nos referimos (“i:”institución financiera, “o:”obejto), pero eso funciona solo para nosotros los humanos, los ordenadores obvian estas observaciones ¿qué otra solución podemos echar mano?

Espacios de nombres en XML: XMLNS.

Los espacios de nombres (“Name Spaces”) en XML (juntos serían XMLNS) es el concepto para definir los prefijos que querramos usar en cualquier documento XML. Este “Name Spaces” son unos atributos y como tales debemos colocarlos en el elemento “padre” con un valor bajo la forma de URI (Uniform Resource Identifier) que bien puede ser a su vez un URL (Uniform Resource Locator) o un URN (Uniform Resource Name).

Para este nuestro caso vamos a usar el modelo de comentario y el modelo de URL todo esto apuntando siempre a que sea un ser humano el que va a leer la información (y luego veremos el caso de si es un ordenador el que “procesará” la información):

<?xml version='1.0' encoding='UTF-8'?>
<!--
  prefijo 'i:' se refiere a instituciones financieras.
  prefijo 'o:' se refiere a muebles, objetos.
-->
<raíz>
    <i:bancos xmlns:i='https://es.wikipedia.org/wiki/Banco'>
        <i:nombre>Banco de Venezuela</i:nombre>
        <i:nombre>Banco Mercantil</i:nombre>
        <i:nombre>Banco Bicentenario</i:nombre>
    </i:bancos>
    <o:bancos xmlns='https://es.wikipedia.org/wiki/Banco_(mueble)'>
        <o:nombre>banco de madera</o:nombre>
        <o:nombre>banco de metal</o:nombre>
        <o:nombre>taburete</o:nombre>
    </o:bancos>
</raíz>

También podemos declarar dichos atributos en el elemento raíz para darle mayor claridad a nuestro código y es igualmente válido:

<raíz
    xmlns:i='https://es.wikipedia.org/wiki/Banco'
    xmlns='https://es.wikipedia.org/wiki/Banco_(mueble)'
>

Recordemos que los documentos XML permiten los espacios en blanco para precisamente indentar para clarificar, por ello este formato de elemento raíz.

HTML DOM

Fuentes consultadas.

En idioma castellano.

En idioma inglés.

PMWiki tutorial

En el MarkDown tutorial que hicimos explicamos de manera rápida la manera de escribir una página web con un formato desenfadado y sin tantas pretensiones. También publicamos acerca de Marp, un software libre capaz de realizar presentaciones y exportar a PDF a partir de un fichero hecho con MarkDown. Analizando el software de familias Wikis nos topamos con PMWiki que tiene una peculiar manera de escribir código “pseudo HTML” y por ello comenzaremos explicando las reglas de sintaxis y luego veremos como se instala y mantiene una página web con dicha solución en software libre, ¡adelante!

PMWiki text markup.

PMWiki utiliza un lenguaje de marcado a diferencia del paradigma actual del siglo XXI: «lo que usted ve es lo que obtiene» (“What You See Is What You Get” o por sus iniciales WYSIWYG). Esto último consiste en utilizar herramientas de modelado que presentan en tiempo real la apariencia del trabajo que hacemos sin importarnos cómo se logra ya que el “interprete” nos abstrae del código subyacente. El asunto es que nosotros nunca dejamos de estar conscientes que los ordenadores solo entienden de unos y ceros (y ni siquiera eso, ya que es una abstracción que nos hacemos: solo entiende con apagado o encendido, hay o no hay en el último de los casos).

Reglas básicas de edición en PMWiki.

Hay seis reglas básicas para editar las páginas web cuyo motor web es la PMWiki:

  1. Para comenzar un párrafo solo basta con una simple línea en blanco.
  2. Para comenzar una lista enumerada comenzamos cada línea con un caracter numeral”#”; una lista no enumerada cada línea utiliza un asterisco “*” (numerada NO quiere decir ordenada, cuidado con los “falsos amigos” en las traducciones del inglés al castellano).
  3. Para un título principal comenzamos cada línea con signo de cierre de admiración “!” seguido de un espacio y luego el texto deseado. Cada subtítulo lleva dos o más signos de cierre de admiración “!!”, “!!!”, etc.
  4. Para texto en cursivas lo encerramos con dos comillas simples (”) y para texto en negritas tres comillas simples (”’).
  5. Para realizar un enlace web en nuestra propia wiki lo encerramos con dobles corchetes rectos “[[ nombre ]]” donde nombre es el archivo que contiene nuestra página, en realidad es un enlace relativo (muy útil si luego queremos “mudar” nuestra wiki).
  6. Si queremos enlaces web hacia otros sitios web también lo encerramos entre corchetes rectos doble y debemos escribir el enlace completo -vamos, dejad la pereza, escribid con todo y “http://“. También sirve para otros tipos de enlaces como el usado para enviar correo electrónico “mailto:“.

Párrafos y saltos de líneas.

Los párrafos se delimitan dejando una línea en blanco, por lo tanto todo lo que escribamos en varias líneas será presentado como un solo párrafo. Para los que amamos el utilizar la venta terminal para trabajar nos ofrece la ventaja de escribir con un máximo de 40, 80 o 90 caracteres de anchura lo cual nos permite una cómoda edición sin preocuparnos del ancho de pantalla que utilizarán nuestros usuarios.

papel pijama
papel pijama

Generalmente monitores con relación 16:9 que es apto para ver películas pero incómodo para ver párrafos muy anchos ya que dificulta seguir la línea que estamos leyendo -recordad el famoso papel pijama del siglo XX , pero bueno, ese no es nuestro problema sino del usuario de la página, je, je, je 🤓 ).

Este párrafo aunque
tiene varias líneas
será mostrado como uno solo.
Este párrafo aunque tiene varias líneas será mostrado como uno solo.
Para unir una línea con otra \
usaremos la barra invertida \
(a pesar que este es el comportamiento \
predeterminado, unir líneas).
Para unir una línea con otra usaremos la barra invertida (a pesar que este es el comportamiento predeterminado, unir líneas).
Sin embargo, si necesitamos que el párrafo
tenga múltiples líneas,
como por ejemplo un diálogo,
debemos usar al final dos barras
invertidas en cada línea, ejemplo: \\
-"¿Qué dijo ella acerca del tema?". \\
-"Que eso no era problema de ella". \\
Sin embargo, si necesitamos que el párrafo tenga múltiples líneas, como por ejemplo un diálogo, debemos usar al final dos barras invertidas en cada línea, ejemplo:
-"¿Qué dijo ella acerca del tema?".
-"Que eso no era problema de ella".
Para forzar fin de línea y dejar
una línea de por medio \\\
usamos tres barras invertidas.
Para forzar fin de línea y dejar una línea de por medio


usamos tres barras invertidas.
Para forzar la separación de una línea
usaremos [[<<]] para indicar el corte.
Para forzar la separación de una línea usaremos
para indicar el corte.
Para indentar un párrafo
(que sirve para hacer citas o resaltar ideas)
usaremos "->"
"Citas Citables."
Mientras más guiones usemos más indentado el párrafo.
Para indentar un párrafo (que sirve para hacer citas o resaltar ideas) usaremos "->":
"Citas Citables"

Mientras más guiones usemos más indentado el párrafo.
Una cita que comienze con
una línea prominente es una
forma atractiva para ello
usaremos "-<"
"Cita con línea prominente muy larga para que se note"
Una cita que comienze con
una línea prominente es una
forma atractiva para ello
usaremos
"Cita con línea prominente
muy larga para que se note"
Para comentarios usaremos los
símbolos mayor que y menor
>>comment<<
este es un comentario
>><<
que por pares.
Para comentarios usaremos los
símbolos mayor que y menor
que por pares.

En la tabla anterior os mostramos de manera práctica los comandos y cómo se vería, sin embargo es un artilugio de programación que le hicimos a WordPress para ilustraros el temas, hay algunos detalles que no se ven igual en PMWiki (lo mejor sería hacer un subdominio y correr una pequeña wiki allí para que veaís bien claro el resultado).

Listas.

Ya sabemos que para hacer una lista debemos comenzar con un asterisco “*” cada línea, y si acaso quiséramos asignarle una numeración automática debemos usar un numeral “#”. Cualquier línea a continuación que NO comience con asterisco o numeral es implícito que finaliza la lista.

Acá ampliamos un poco con las sublistas: una línea que comienze con dos asteriscos (despúes de una línea que comienze con un asterisco) se visualiza como una sublista:

* Esta es una lista.
* Segundo elemento de lista.
** Comienza sublista.
** Segunda línea de sublista.

Producirá el siguiente resultado:

  • Esta es una lista.
  • Segundo elemento de lista.
    • Comienza sublista.
    • Segunda línea de sublista.

Se pueden combinar:

* Lista
## Sublista.
## Dos.
## Tres.

Salida:

  • Lista.
    1. Sub lista uno
    2. Dos.
    3. Tres.

Algo que gusta mucho a los autores es la numeración romana o con letras del abecedario, ya sea en maypusuculas o minúsculas; esto se logra colocando las siguientes palabras claves luego de el o los asteriscos y/o numerales de cada línea (por supuesto, no se mostrará al usuario dichas palabras claves al momento de “servir” el artículo wiki):

  • %roman%
  • %ROMAN%
  • %alpha%
  • %ALPHA%

Ejemplos de códigos:

* %roman% Lista con números romanos.
* Línea dos en números romanos.
## %ALPHA% Sublista con letras del abecedario en mayúsculas.
## Segunda línea de sublista.

Y arrojaría lo siguiente:

WikiSandbox listas con numeracion romana y alfabetica
WikiSandbox listas con numeracion romana y alfabetica

Estos “trucos” necesarios para mostrar en WordPress listas y sublistas a “nuestra manera personalizada”  tendrán su artículo aparte y será un complemento a nuestro tutorial HTML5 para no hacer ese tutorial más voluminoso de lo que ya es -y enseñar a usar WordPress, que ni un temita le hemos dedicado a nuestro “motor” de blog.

Este concepto de palabras claves se repite si debemos forzar la numeración u orden: “%item value= número%“.

También si queremos parar la numeración y reiniciarla solo debemos insertar una línea con la siguiente palabra clave: “[==]“:

# %item value=7000% Línea siete mil.
# Siete mil uno.
[==]
# Reinicia numeración.

Salida:

  1. Línea siete mil.
  2. Siete mil uno.
  1. Reinicia numeración.

Nota: el indentado que veís lo hace WordPress para alinear las listas con diferentes numeraciones, se agradece para nosotros los maniáticos del orden.

Listas con párrafos explicativos.

Para cada elemento de una lista podemos anexar un párrafo a continuación para ampliar o definir un concepto o descripción. El estilo indica que ha de ser lo más breve y conciso posible para mantener el panorama de la lista en sí misma. Dijimos que cualquier línea a continucación que NO comience con asterisco o numeral significa el fin de la lista pero he aquí que si una línea comienza con un espacio se considera esa línea como perteneciente al elemento de la lista que lo precede pero no se enumera -no es un elemento de la lista en sí-. Para lograr el indentado se debe finalizar la línea elemento de lista con “\\” (que aunque no es esctrictamente necesario, mejora el aspecto).

Un ejemplo:

'''Grandes venezolanos'''
* Simón Bolívar, Caracas 1783, Santa Marta 1830.\\
 ''«Llamarse jefe para no serlo es el colmo de la miseria»''.
* Francisco de Miranda, Caracas 1750, Cádiz 1816.
 ''«¡Le Venezuela est Blessée au coeur!»''.
* José Antonio Páez.

Produce lo siguiente:

Grandes venezolanos:

  • Simón Bolívar, Caracas 1783, Santa Marta 1830.

«Llamarse jefe para no serlo es el colmo de la miseria».

  • Francisco de Miranda, Caracas 1750, Cádiz 1816.

«¡Le Venezuela est Blessée au coeur!».

  • José Antonio Páez.

Línea horizontal.

Si escribimos el comando “—-” (cuatro o más guiones seguidos) en una sola línea de texto nos produce una línea horizontal gráfica que sirve para separar párrafos o denotar importancia como una advertencia -o el uso que queráis-.


Texto sin formato, tal cual.

Supongamos que en nuestra PMWiki queremos hacer un tutorial en castellano sobre todo esto que estamos explicando acá vía WordPress: para indicarle que no proceso nuestros código ejemplos y los muestre tal cual, cómo código que son debemos “escapar” el texto de código con “[@ texto código @]”. Puede ser utilizado para un párrafo completo o para una o más palabras en un párrafo.

Para un “escapado” estricto utilizamos “[= texto código =]”, la diferencia esta que con arroba se respetarán los saltos de líneas y espacios pero con el signo de igualdad se escribirá todo junto como un párrafo .

Texto con fuente monoespaciada.

Si además necesitamos una fuente monoespaciada, es decir, un tipo de fuente cuyas letras todas y cada una tienen el mismo ancho simplemente debemos comenzar la línea con un espacio (que no esté después de una lista, ojo con eso). Imaginad (o recordad) los famosos cuadernos cuadriculados para matemáticas, una letra por retícula.

cuaderno cuadriculado
cuaderno cuadriculado

Tablas.

Para las tablas emplearemos el caracter doble “tubería” o “||”:

  • La primera línea con doble tubería seguido del tipo de borde: “|| border=1”.
  • La segunda línea con la primera fila de la tabla y cada elemento de columna separado con doble tubería.
  • Si es un encabezado de tabla, luego de doble tubería un signo de admiración de cierre.

Una tabla sin borde se logra con “border=0”, de uno en adelante produce un borde doble con un sombreado que aumenta según aumenta el valor entero que le demos.

Existe una sintaxis alterna para tablas más avanzadas pero en honor a la verdad dicha sintaxis es igual de compleja que escribir en código HTML. Pensamos que solamente vale la pena para un cuadro de navegación como el siguiente:

(:table border=1 width=30% align=right bgcolor=#cccc99 cellspacing=0 : )
(:cellnr: )
'''Páginas de buscadores'''
(:cellnr: )
*[[https://duckduckgo.com/ | DuckDuckGo]]
*[[https://fr.wikipedia.org/ | Wikipédia L'encyclopédie libre]]
(:tableend:)

En esta imagen podemos ver la tabla avanzada mezclada con los ejemplos últimos, debajo de la imagen coloamos TODO el código completo que produce ese resultado en PMWiki:

PMWiki formatos de texto listas y tablas
PMWiki formatos de texto listas y tablas
(:table border=1 width=30% align=right bgcolor=#cccc99 cellspacing=0 :)
(:cellnr:)
'''Páginas de buscadores'''
(:cellnr:)
*[[https://duckduckgo.com/ | DuckDuckGo]]
*[[https://fr.wikipedia.org/ | Wikipédia L'encyclopédie libre]]
(:tableend:)
'''Grandes venezolanos'''
* Simón Bolívar, Caracas 1783, Santa Marta 1830.\\
 ''«Llamarse jefe para no serlo es el colmo de la miseria»''.
* Francisco de Miranda, Caracas 1750, Cádiz 1816.
 ''«¡Le Venezuela est Blessée au coeur!»''.
* José Antonio Páez.
|| border=0
||! head 1 ||! head 2 ||! head 3 ||
|| cell 1 || cell 2 || cell 3 ||
|| border=1
||! head 1 ||! head 2 ||! head 3 ||
|| cell 1 || cell 2 || cell 3 ||
|| border=2
||! head 1 ||! head 2 ||! head 3 ||
|| cell 1 || cell 2 || cell 3 ||
|| border=3
||! head 1 ||! head 2 ||! head 3 ||
|| cell 1 || cell 2 || cell 3 ||

Nota: la tabla avanzada se colocará siempre a la derecha, tal como instruimos en código pero al mismo nivel de los elementos que tenga a continuación -uno al lado del otro-

Formato de caracteres.

Otros comandos nos permiten dar formato al texto para representar fórmulas, citas, etc

* Texto con '^superíndices^'.
* Texto with '_subíndices_'.
* Texto {-tachado-}.
* Texto {+subrayado+} (poco utilizado, se confunde con hipervínculo).
* Texto [+grande+], [++más grande++].
* Texto  [-pequeño-], [--más pequeño--].

En la siguiente sección colocamos una imagen tomada del WikiSandBox: es un área donde podremos libremente practicar nuestros códigos, podremos hacer y deshacer sin problema alguno, programamos y visualizamos resultado mientras agarramos práctica, la idea es luego escribir rápidamente artículos completos y publicar de una vez sin mayor dilación.

Sandbox” significa “cajón con arena” que nunca falta en los parques de los Estados Unidos y donde colocan a los pequeños y pequeñas para que desarrollen sus habilidades motoras sin peligro alguno; acá en Venezuela hacemos algo mucho mejor: los llevamos a las playas maravillosas de nuestro país.

Alineación de texto, color de fuente.

Por defecto el texto está alineado a la izquierda, pero podemos centrarlo comenzamos la línea con “%center%” y “%right%” para alinearlo a la derecha.

Para que el texto “flote” a la derecha sobre el siguiente párrafo que haya a continuación iniciamos con “%rfloat%” y si lo queremos en un marco “%rframe%“.

Para aplicar color simplemente escribimos el color, en inglés, encerrado entre signos de porcentaje. Esto se aplicará por defecto al resto del párrafo a partir del código, si necesitamos solamente colorear una palabra escribiremos “%blue% palabras a colorear %black%“. Por defecto el color de fuente es negro, por eso escribimos %black% pero eso no es necesariamente cierto, todo depende del estilo general de la PmWiki (tema avanzado). Lo correcto para restablecer el color es cerrar con doble signo de porcentaje “%%”.

También se pueden combinar los comandos, por ejemplo centrado y en color rojo: “%center red%”.

Formato de texto en WikiSandBox - PmWiki
Formato de texto en WikiSandBox – PmWiki

Alcance de los estilos.

No necesariamente se deben colocar los códigos al inicio de un párrafo, por ejemplo, a mitad de un párrafo podremos escribir “%p red% indicando que el párrafo, representado por la letra “p” sea rojo “red” sin importar dónde lo ubiquemos: al principio, en el medio o al final. Similar comportamiento aplica para otros elementos:

  • Imágenes: %img … (otros comandos)%
  • Texto de código: %pre (otros comandos)%
  • Lista: %list (otros comandos)%
  • Elemento de lista: %item (otros comandos)%

Estilos con nombres en castellano.

Podremos definir clases de estilos, definidos por nosotros mismos. En mejor uso es poder escribir en castellano, especialmente para aquellos u aquellas que no dominan ese idioma. Para ello al comienzo de un artículo podríamos escribir lo siguiente:

%define=amarillo color=yellow%
%define=fondo_amarillo bgcolor=yellow%
%define=azul color=blue%
%define=fondo_azul bgcolor=blue%
%define=rojo color=red%
%define=fondo_rojo bgcolor=red%

%amarillo%Conocerás los principios básicos%% de la programación en PHP como su sintaxis, estructuras de control, etc. %azul%Además explorarás un nutrido conjunto de características%% y funcionalidades, las necesarias para desarrollar la mayoría de las aplicaciones, %fondo_rojo%como el acceso a la base de datos%%, el sistema de archivos, etc.
Clases definidas en PmWiki
Clases definidas en PmWiki

Así entonces será más fácil recordar los comandos, pero supone escribir guiones al principio de cada artículo. Es mejor definir estilos globales, que funcionen en toda la página PmWiki alojada, eso es avanzado y más adelante lo estableceremos en la configuración de instalación.

Caracteres especiales.

Pues con nuestros teclados o copiando y pegando podemos escribir los caracteres “especiales”: las vocales acentuadas, el símbolo de la moneda euro €, etcétera y para ello rigen las mismas normas del HTML: la “á” se escribiría “&aacute;” el símbolo del €: &euro;.

Imágenes.

Por increíble que parezca, para mostrar una imagen en nuestra PmWiki simplemente colocamos el enlace hacia la imagen web… ¡y listo! (en WordPress es igual, aunque no lo creáis, pero este tutorial es de PmWiki y no otra cosa, disculpad).

El meollo del asunto es que normalmente gustamos de darle formato a las imágenes, texto alterno si el navegador no puede mostrar imágenes -o las tienen bloqueadas de alguna manera-, títulos, tamaños, bordes,  etc. Comencemos a realizar una lista con las principales características:

  • Comenzemos por establecer que una imagen ocupa una línea completa, imaginad que estamos escribiendo un párrafo. Luego cuando cojamos práctica podremos mezclar imagen entre párrafos para lograr bonitos acabados, verbigracia, como una enciclopedia merece; pero vayamos aprendiendo poco a poco.
  • Simplemente una imagen, sin más, colocamos una URL completa con alguno de los siguientes formatos de imágenes: gif, jpg, jpeg, png, svg, svgz. Dicha imagen debería residir en nuestro servidor por principios de ética de no “robar” el ancho de banda de los demás sitios web. Aunque PmWiki permite subir imágenes, dicha función, por seguridad, viene desactivada por defecto. En la sección de instalación y configuración tomaremos de nuevo el tema.
    • Ejemplo de imagen:
      1
      http://pmichaud.com/img/misc/pc.jpg
    • La anterior imagen está alojada en el servidor web del autor de PmWiki, el Doctor Patrick Michaud, la imagen fue tomada de Flickr y tiene licencia “Creative Commons”.
  • Cuando uno ubica, sin hacer click, el puntero del ratón (y nos disculpáis la redundancia) sobre una imagen web por más de 500 milisegundos (generalmente) nos aparece una ventanita con un texto que describe la imagen: para lograrlo en PmWiki debemos escribir a continuación y sin dejar espacio alguno, encerrado entre comillas dobles el texto deseado. También este texto es mostrado si por razón alguna el navegador NO puede mostrar la imagen, y los navegadores web modernos que narran las páginas web también toman este texto para los discapacitados visuales.
    • Ejemplo de “tooltip”: http://pmichaud.com/img/misc/pc.jpg”CLIPS”
  • Si queremos establecer un título a la imagen, después de las comillas dobles y sin espacio alguno insertamos un caracter “tubería” “|” e inmediatamente el texto deseado. En honor a la verdad si acepta espacios entre el caracter tubería pero recomendamos escribir todo junto para ayudarnos a recordar el proceso (y pulsar menos teclas para escribir más rápido).
    • Ejemplo de título a imagen: http://pmichaud.com/img/misc/pc.jpg”CLIPS”|”Clips coloridos”
  • Si queremos que la imagen en sí sea un enlace web debemos prestar mucha atención: debemos encerrarla entre corchetes rectos dobles pero dejando fuera el título de imagen, si es que la hubiere.
    • Seguimos con el mismo ejemplo, ahora más larga la línea:
    • [[http://pmwiki.org/|http://pmichaud.com/img/misc/pc.jpg”CLIPS”]]|”Clips coloridos”
  • Al igual que un texto, podemos alinear la imagen al centro o derecha colocándole de principio de línea los comandos %center% o %right% (por defecto se alinea a la izquierda):
    • %center%[[http://pmwiki.org/|http://pmichaud.com/img/misc/pc.jpg”CLIPS”]]|”Clips coloridos”
    • Ahora vamos viendo el porqué recomendamos eliminar los espacios, va larga la cosa. 🙂
  • Hasta ahora la imagen que queremos mostrar es tal cual, sin ninguna modificación al tamaño. Rogamos encarecidamente que subáis imágenes ligeras, en formato jpg preferiblemente y que midan menos de 50 mil bytes. Para redimensionar debemos usar:
    • A un ancho específico: %width=150px% (a 150 píxeles de ancho).
    • A un alto específico: %heigth%=100px% (a 100 píxeles de alto).
    • A una miniatura (66 x 32 píxeles, formato gif): %thumb%.
    • Intentamos seguir con el ejemplo planeado pero las múltiples combinaciones impiden que PmWiki redimensione la imagen, bien puede ser un excepción de PmWiki o nosotros desconocemos la sintaxis correcta pero nos decantamos -humildemente- por el error “bug” de PmWiki.
  • Para que al hacer click en la imagen se abra en una pestaña o ventana nueva debemos encerrar todo el enlace y sus opciones adicionales entre “%newwin% enlace_web %%” teniendo la precaución de colocarlo todo junto y justo antes de los corchetes dobles. Si quisieramos centrar la imagen primero debemos escribir %center% y luego el resto del comando y no al revés porque no lo tomara de forma debida y esperada.
  • Un interesante efecto para un párrafo es insertar la imagen a la izquierda o a la derecha de un párrafo que la describa o hable de ella, para lograr esto simplemente colocamos %rframe% o %lframe% antes del código de la imagen y luego al finalizar el código en otra línea el párrafo, sin dejar líneas vacías de por medio.
    • %rframe%http://www.ks7000.net.ve/wp-content/uploads/2017/05/PmWiki-logo-1.jpg párrafo
    • De nuevo, las opciones de redimensionamiento tampoco logramos hacerlas funcionar con %rframe%.
    • Imagen en cuadro flotando sobre texto alineado a la derecha
      Imagen en cuadro flotando sobre texto alineado a la derecha
  • Existen muchísimas más opciones para elt ratamiento de imágenes pero escapan a la simplicidad que queremos lograr y se aproximan más a la sintaxis de CSS y HTML, y es justo lo que queremos evitar, escribir en esos dos lenguajes de marcado.
  • Las imágenes se pueden combinar con tablas pero de nuevo, no son nada sencillo y queremos evitar su uso.
  • PmWiki es tan poderoso como queráis, no lo subestiméis, al modificar “config.php” tendremos cientos de personalizaciones, pero mantengamos la simplicidad, por favor -no todos nuestros usuarios serán tan avanzados en programación, con que aprendan unos cuantos comandos bastará para que escriban en nuestra Wiki.

Historia de PmWiki.

La palabra wiki proviene del idioma hablado en la isla de Hawaii, quincuagésimo estado federal de los Estados Unidos de América. Significa rápido y wiki wiki súper rápido (ya en los años 80 acá en Venezuela vendíamos un tinte para ropa llamado “wiki-wiki”: no teníamos dinero para comprar pantalones nuevos y los pintábamos de negro y listo, “pantalones nuevos” rápidamente).

Las páginas web que tienen un motor wiki son como cualquier otra página web pero tienen dos características únicas:

  • Tienen un botón con la palabra “editar” para que cualquiera colabore en ellas (y podemos subir o bajar los requerimientos de seguridad en la medida que nos sintamos cómodos).
  • No se necesita de conocimientos profundos sobre desarrollo web, con unos cuantos comandos como los que vimos arriba en el resumen de 6 pasos bastan para que se comienze a plasmar el aporte de cada quien.

Autor de PmWiki.

El caso concreto de PmWiki el Doctor Patrick Michaud (la letra “d” NO se pronuncia) es el autor con más de 40 años de experiencia en computación (graduado con “Post High Degree” en la University of Southwestern Louisiana -aquí le decimos Doctorado-) y podéis acceder a su página web http://www.pmichaud.com/ donde, faltaría más, faltaría menos con el motor PmWiki donde mantiene un resumen de su vida profesional y formas de contactarlo ya sea por correo eletrónico o redes sociales.

Dr. Patrick Michaud
Dr. Patrick Michaud

Filosofía de trabajo de PmWiki.

Fueron establecidas durante el desarrollo de PmWiki y aunque el Dr. Michaud comparte muchas de ellas no son exclusivas de su persona, de hecho mantienen un foro abierto a nuevas ideas y sugerencias para mantener activo este software a los requerimientos modernos de la humanidad.

Los pilares son:

  1. Preocupados sobre los autores más que por los lectores: buenos autores son difíciles de conseguir y “mantenerlos” en el proyecto priva sobre cualquier lector de la enciclopedia (crudo pero es la realidad).
  2. PmWiki no trata de reemplazar al HTML: ya hemos hablado sobre esto, se enfoca en ser algo simple y sencillo para los autores, sin embargo tiene poderosos sustitutos que pueden llegar a realizar casi lo mismo que el HTML pero no es nunca ese su objetivo.
  3. Pragmatismo sobre todo: se busca la utilidad por encima de la moda, algo bien estructurado en vez de ir a lanzarse a la primera por cualquier tendencia.
  4. Soporte colaborativo para el mantenimiento público de páginas web: autores y grupos de autores pueden ir construyendo un sitio para luego llegar a un punto de madurez y empezar a proteger con contraseñas ya sean páginas individuales o secciones o grandes secciones que busquen preservar los títulos, subtítulos e incluso párrafos e imágenes mientra otras áreas están libres y abiertas para captar nuevas ideas o registrar el simple pasar del tiempo. Precisamente éste es un ejemplo: un registro de cambios de un artículo (NO el registro de cambios de la página en sí) debería estar protegido al cabo de cierto tiempo, días o semanas, proque eso es historia y ya no cambiará (incluso se pueden dejar las referencias abiertas en pie de página si alguien quiere agregar algo al tema).
  5. Fácil de instalar, configurar y mantener: del dicho al hecho, las siguientes secciones hablan sobre ello.

Instalación de PmWiki.

Primero debemos descargarlo de forma comprimida desde PmWiki, solo pesa menos de medio megabyte, la versión estable 2.2.98 -ya os dijimos: PmWiki es sencillo y simple pero muy útil-.

Como un servicio a la comunidad por acá también la ponemos a la orden, si la queréis descargar desde acá.

Se ofrece paquetes adicionales para diferentes idiomas en esta dirección de la misma PmWiki.org pero deja mucho que desear por ahora para nuestro trabajo la vamos a dejar así, en purito inglés pero no creáis que nos hemos rendido con el castellano, de hecho tenemos en mente unas ideas laboriosas por realizar y una vez terminemos la publicaremos por acá.

Una vez descargado lo descomprimimos en nuestra carpeta /var/www/html -en nuestro caso usamos un servidor web Apache2 con PHP5 en nuestro ordenador en VirtualBox- y debemos darle los derechos adecuados de escritura para que se puedan grabar nuestras preferencias.

Se recomienda crear una carpeta llamada pmwiki en la carpeta pública de nuestro servidor web y redirigir debidamente modificando el .htaccess (o por otros métodos). No es la tarea de esta entrada y tomando en cuenta que tenemos un servidor de pruebas y por propósitos didácticos NO LO HAREMOS ASÍ sino que simplemente colocaremos los ficheros y directorios como si el servidor fuera dedicado a retribuir una sola página web.

Ficheros y carpetas de PmWiki.

Una vez hayamos copiado los archivos tendremos la siguiente estructura que pasamos a traducir directo del propio tutorial en inglés:

  • README.txt: un documento introductorio y contiene la licencia de uso GNU:
  • pmwiki.php: el archivo principal, el hace las veces del “index.php” en nuestro servidor Apache2.
  • local/: Carpeta que contiene los guiones de configuración local.
  • cookbook/ : Carpeta con”recetario” con programas agregados que enriquecen a PmWiki (suplementos).
  • docs/ : Documentación y guiones de ejemplo.
  • pub/ : archivos de acceso público.
    • pub/css/ : Archivos con hojas de estilo en cascada de los temas (suplementos).
    • pub/guiedit/ : (¡aún no hemos estudiado este directorio!).
    • pub/skins/ : “temas” para cambiar la apariencia y comportamiento de PmWiki.
  • scripts/ : Guiones que son partes de PmWiki.
  • wikilib.d/: Paquete de páginas predeterminadas de PmWiki.

Por ahora esos son los ficheros y directorios iniciales, los cuales, por seguridad, solo necesitamos que tengan derecho de lectura más no de escritura. Para poder guardar nuestras configuraciones y futuros artículos debemos tener derechos de escritura en una carpeta especial llamada “wiki.d/“.

¡Atención! no confundir con la carpeta wikilib.d

  • Dentro de esta carpeta wiki.d se guardarán nuestros artículos con el prefijo “PmWiki.” más el nombre del título que le pongamos al crearla.
  • Junto a estos archivos automáticamente PmWiki llevará de manera sincronizada otros ficheros donde se registran los cambios hechos, la configuración de la barra lateral izquierda e incluso un índice de páginas. No debemos preocuparnos por estos archivos, excepto respaldarlos regularmente fuera de nuestro sitio web y/o servidor de producción (si respaldamos en nuestro ordenador podremos llevar un respaldo adicional junto con un control de cambios al utilizar GitHub el cual es sin costo para proyecto públicos -proyectos privados se paga mensual en US$-).
  • El otro directorio que debe tener derechos de escritura si es que llegamos a habilitarlo es la carpeta “uploads” que viene a albergar los ficheros que subamos a nuestro servidor. Se le harán las mismas consideraciones del punto anterior.

Si nuestro servidor permite acceso vía SSH por ventana terminal usaremos el comando “chmod” para otorgar permisos de escritura, si es un servidor web compartido generalmente tenemos acceso vía softwfare CPANEL que permite lanzar un navegador de archivos y otorgar derechos de escritura a esas dos carpetas. También recordemos que el comando “chmod” funciona en muchos programas clientes FTP, así que cuando “subamos” los archivos de PmWiki podríamos cambiar de una vez los derechos de escritura.

Dado el caso que NO hayamos configurado lo anterior y nos decidimos por ejecutar directamente de una el fichero principal pmwiki.php éste nos lo recordará amablemente con un mensaje de que no podemos seguir adelante.

Ejecutando por primera vez pmwiki.php

Pues bien, acá se mostrará la página de bienvenida con tutoriales e indicaciones -en inglés- de todo lo que explicamos acá en idioma castellano.

Estableciendo “index.php” o “index.html”

Dependiendeo de como tengáis configurado vuestro servidor, necesitaréis un archivo llamado “index.php” o si tenéis configurado tratar los archivos con extensión .html como .php debeis escribir en él lo siguiente:

1
2
3
4
&lt;?php
include("pmwiki.php");

?&gt;

Modificando “config.php”.

Lo que nos toca por hacer es configurar el archivo config.php en la carpeta “local/“. Dicho archivo es de solo lectura pero debemos tener permisos de escritura para copiarlo desde la plantilla llamada “sample-config.php” (carpeta “docs/”) la cual modificaremos a nuestro gusto y conveniencia: en nuestro ordenador donde hayamos descargado y descomprimido PmWiki copiamos el archivo con el nombre “config.phplo modificamos para luego subirlo (vía https o sftp) a nuestra carpeta “local/”.

Este fichero contiene las configuraciones comunes pero vienen inactivas gracias a un caracter numeral al principio de cada línea de comando, eliminando dicho caracter las “descomentamos” y ponemos a nuestro servicio.

  • La primera línea que modificaremos es el título de nuestra página, por defecto reza “$WikiTitle = ‘PmWiki’;” cambiando solamente lo que está entre comilla simples.
  • La segunda línea a cambiar permite cambiar nuestro logotipo a una imagen tipo gif de 32 píxeles que diseñemos y con el nombre que querramos, cambiamos la siguiente línea QUE DEBEMOS DESMARCAR como comentario (fijaos en la ruta donde vamos a subir dicho archivo):
    • $PageLogoUrl = “$PubDirUrl/skins/pmwiki/pmwiki-32.gif“;
  • ¡Muy importante! la contraseña administrativa en la línea siguiente la cambiaremos a nuestro criterio:
    • $DefaultPasswords[‘admin’] = pmcrypt(‘secret‘);
  • Si quisieramos activar la subida de archivos, modificar la línea que activa (descomentarla) y fijar una nueva contraseña a nuestra conveniencia (y descomentarla también):
    • $EnableUpload = 1;
    • $DefaultPasswords[‘upload’] = pmcrypt(‘secret‘);
  • PmWiki permite unos botones gráficos para darle un pequeño toque “colorido” a nuestra página web, si deseais lo activaís descomentando la siguiente línea:
    • $EnableGUIButtons = 1;
    • PmWiki botones gráficos
      PmWiki botones gráficos

¡LISTO! Guardamos y copiamos a su ubicación final y vemos los cambios recargando la página.

Seguridad en PmWiki.

Al modificar config.php establecimos nuestra contraseña como administrador, nuestra llave para crear, modificar o  eliminar contraseñas, es el más alto nivel efectivo en nuestro sitio. La reservamos para nosotros, los programadores y encargados del mantenimiento y funcionamiento de la página web en sí ya que la mayor del tiempo serán los autores los que estarán a cargo de proteger sus propios trabajos.

El enfoque que utilizaremos, siempre pragmáticos, es de ir de menos a más, según nuestras necesidades, analizemos:

Grupo de 1 a 3 autores.

Siendo un grupo pequeño solo se necesita que a nivel global todos los botones de edición de página tengan una simple contraseña. Para lograr esto debemos descomentar y modificar (o agregar) la línea siguiente en /local/config.php

$DefaultPasswords['edit'] = pmcrypt('nuestra_contraseña_de_edicion');

Acá no hay más complicaciones, solo es cuestion de comunicarse entre ellos y verbalmente dirimir sus diferencias, en teoría no debería haber mayor problema y si lo hubiera nosotros como administradores deberemos tener la última palabra y “reiniciar” la contraseña a nivel global para excluir a algún miembro de la edición de artículos -caso extremo-. Luego veremos que tal vez tengamos unas tareas adicionales que realizar, tened paciencia y os explicamos, vamos a continuar con la idea de grupos.

Grupo de 3 a 12 autores.

Manejar a esta cantidad de personas la cosa se complica un poco. Tratar de reunirlos todos a la vez va a ser difícil y si se lograra se nos va a ir el tiempo en reuniones grupales, lo cual es mucho trabajo para el poco dinero que nos pagan por la tarea. 😉

El mejor enfoque en este caso es establecer nosotros mismos normas de publicación (grupo de páginas) de caracter privado por lo que tendremos que establecer contraseñas para poder leer este particular grupo de páginas. Establecidas las normas, ya saben a qué atenerse. Una vez “tamizados” los autores podremos elegir a dos sub administradores que nos ayuden en nuestro trabajo, pero ¿cómo lograr esto sin dar nuestra contraseña de edición a los subadministradores? A nivel global se pueden establecer matrices de contraseñas (esto ya es lenguaje PHP en sí) de nuevo en el ya famoso archivo config.php:

$DefaultPasswords['read'] = array(pmcrypt('alfa'), pmcrypt('beta'));
$DefaultPasswords['edit'] = pmcrypt('beta');

alfa” y “beta” serán dos contraseñas distintas, para elevar un autor a subadministrador (ojo, esta figura no está canonizada en el sistema PmWiki, la estamos “inventando” en este artículo práctico) pues le daremos una nueva contraseña que será “beta“. Es más, si son dos subadministradores, como proponemos ,nada nos impide generar una contraseña “gamma”:

$DefaultPasswords['read'] = array(pmcrypt('alfa'), pmcrypt('beta'), pmcrypt('gamma'));
$DefaultPasswords['edit'] = array(pmcrypt('beta'), pmcrypt('gamma'));

Luego veremos que tal vez tengamos unas tareas adicionales que realizar, tened paciencia y os explicamos, vamos a continuar con la idea de grupos.

Grupo de autores de hasta 100 autores.

Acá la cosa se pone “color de hormiga”: ya en este punto debemos habilitar usuario y contraseña (léase “login” y “password”) para todos y cada uno de los usuarios a fin de determinar quién hizo qué y tomar las medidas correspondientes. ¿Recordáis la figura de subadministradores? Pues bien, ¡vamos a necesitar entre 3 y 6! Esto es así porque el mantener cuentas y contraseñas de usuario se va a llevar bastante trabajo y necesitamos

El primer paso para habilitar esta característica es agregar (o descomentar) la siguiente línea en /local/config.php:

include_once("$FarmD/scripts/authuser.php");

Demás está decir que ya habremos establecido nuestra contraseña de “admin”, lógicamente, en vez de la que trae por defecto la instalación de PmWiki (un hacker -buenas intenciones- o un cracker -malas intenciones- lo primero que haría sería intentar entrar con esa contraseña por defecto).

La manera de registrar a los usuarios es editar una página llamada pmwiki.php?n=SiteAdmin.AuthUser, es decir, al guión principal llamado pmwiki.php le “pasamos” en la barra de direcciones un signo de cierre de interrogación y solicitará nombre de usuario y contraseña al editar (usaremos la superclave de admin) y agregaremos cada cuenta con la siguiente sintaxis:

nombre_de_usuario: (:encrypt contraseña🙂

Guardamos la página y la contraseña se mostrará encriptada. Dichas cuentas, por manía de orden, la colocamos justo después del subtítulo “Login accounts” y más abajo veremos el subtítulo “Authorization groups” donde podramos definir los grupos de usuarios que inventamos, a saber: autores y subadministradores.

@autores: Kevin, Jimmy
@subadministradores: Kevin

Al crear este tipo de grupos de usuarios se nos facilita enormente la tarea de administración si invertimos el enfoque: nombramos a cada usuario a los grupos que puede pertenecer, el ejemplo anterior pero por usuarios:

Kevin: @autores, @subadministradores
Jimmy: @autores

¿En qué nos beneficia todo esto? En que en cada página podemos definir cuales grupos tienen acceso e incluso podemos delegar -con sumo cuidado- de poder editar la mismísa página SiteAdmin.AuthUser. A primer vista esto parecería una locura pero es que para definir cuentas de usuarios y grupos de usuarios la otra manera de hacerlo permitir editar el fichero config.php y esto no es para que lo haga todo el mundo, cualquier cosa  podría salir mal y tendríamos nosotros mismo que enmendar el capote.

Luego veremos que tal vez tengamos unas tareas adicionales que realizar, tened paciencia y os explicamos, vamos a continuar con la idea de grupos.

Grupos de 100 o más autores.

Manejar tal cifra de personas ya no es posible hacerlo así, “de manera manual”, tendremos que recurrir al uso de protocolos y normas adecuados y que manejen bases de datos para llevar cuenta de todo. PmWiki ofrece acceso mediante el protocolo LDAP pero escapa al alcance de este tutorial. También existe apoyo para htpasswd: el cual utiliza el servidor Apache2 pero no supone ventaja alguna porque al igual que PmWiki se basa en texto plano -incluso encriptado- y no utiliza base de datos además deja por fuera a Ngix que es otro poderoso servidor web, así que no le vemos futuro a esa alternativa.

Además, para manejar tal cantidad de usuarios, se espera una gran cantidad de artículos y por ello debemos hacer uso de un manejador de base de datos que no exija demasiado recursos de cómputo: SQLite es el elegido para ello. Para habilitar su uso debemos descargar y ejecutar este guion creado por Petko Yotov con el cual creamos la base de datos, tablas, índices y relaciones y una vez hecho esto si que debemos modificar de nuevo el consabido config.php en alguna de sus primeras líneas lo siguiente:

1
2
3
4
5
6
7
include_once("$FarmD/cookbook/sqlite.php");
$WikiDir = new PageStoreSQLite($WorkDir.'/pmwiki.sqlite.db', 1);
$WikiLibDirs = array(
&amp;$WikiDir,
new PageStore('wiki.d/{$FullName}'),
new PageStore('$FarmD/wikilib.d/{$FullName}')
);

El fichero pmwiki.sqlite.db será entonces el único que conservará las página que creemos y será el que dabamos respaldar llegado el momento necesario. Esto apenas es un resumen ya que todo programador sabe muy bien que no hay base de datos “rebeldes” sino mal administradas. Por ejemplo, de tanto en tanto deberemos ejecutar la orden

1
pmwiki.php?action=vacuum

; también podremos establecer un valor automático para que ejecuta esta acción por nosotros si lo establecemos en config.php:

$SQLiteAutoVacuum = 300;

Incluso si le colocamos el valor de cero (no ejecutar), siempre podremos hacerlo cuando necesitemos con ?action=vacuum.

Tareas adicionales.

Pues que varias veces nombramos unas dichosas “tareas adicionales” que debíamos realizar para “cerrar el círculo de seguridad” para ello los siguientes datos:

  • Las páginas y grupos de páginas les pueden ser establecidas, individualmente,
    • Contraseña de lectura read.
    • Contraseña de escritura write.
    • Contraseña de acceso a configurar las dos anteriores mediante attr.
  • Para modificar las contraseñas de lectura y escritura a una página debemos adicionar “?action=attr” al final en la barra de direcciones y así introducir nuestra contraseña de administrador (admin).
  • Para modificar las contraseña de lectura y escritura a un grupo de páginas debemos adicionar al final en la barra de direcciones lo siguiente (susitutid “GroupName” por el nombre del grupo de páginas:)
    • ?n=GroupName.GroupAttributes?action=attr
  • Las contraseña son visibles para no pedir confirmación pero al ser guardadas serán debidamente encriptadas (cuidado con las miradas encima por encima de tus hombros).
  • En cada campo -lectura y escritura- de una página o grupo de páginas podremos:
    • Agregar una o más contraseñas simplemente separándolas por un espacio.
    • Agregar uno o más grupos nombrandolos precedidos de una arroba -ejemplo @subadministradores- y separándolos por un espacio entre ellos.
    • Si queremos que todos los miembros de un grupo tengan acceso usaremos “@nombre_grupo: *“.
    • Si de ese grupo necesitamos  exceptuar un usuario -que pertenece a ese grupo-:
      • @nombre_grupo: *, -nombre_usuario“.
    • Establecer uno o más usuarios con la palabra clave “id:” y a continuación los nombres de los usuarios deseados separados por comas.
    • Para incluir todos los usuarios: “id:*”
    • Dejar la contraseña en blanco no guarda los cambios para ese campo.
    • Si queremos quitar la(s) contraseñas debemos usar la palabra clave “clear” solamente.
    • Evidentemente ningún usuario podrá llamarse “clear” (no hemos probado si admite tal usuario)-
    • Si queremos dejar sin contraseña, así esté establecida a nivel global usaremos “@nopass” solamente.
    • Si al contrario, solo queremos que nosotros como administrador seamos los únicos con derechos sobre una página o grupo de páginas usaremos la palabra clave “@lock” solamente.
    • Si previamente aplicamos “clear” o “@nopass” podemos restaurar las contraseñas globales con las correspondientes a continuación: “@_site_edit“, “@_site_read” or “@_site_upload” (si este último está establecido).

Nosotros como administradores podemos…

  1. Establecer contraseñas globales para páginas y/o grupo de páginas que no tengan contraseñas.
  2. Usar attr para controlar quien es capaz de establecer contraseñas en las páginas.
  3. Si está habilitada las subida de archivos, establecer contraseñas para ello.
  4. Usar nuestra contraseña de administrador para eliminar o cambiar las contraseñas de lectura y/o escritura establecidas para cada página o grupo de páginas.
  5. Usar “SiteAdmin.AuthList” para visualizar las páginas o grupos de páginas que tengan contraseñas establecidas.

Jerarquía de contraseñas.

  • Las contraseñas de páginas privan sobre las contraseñas de grupos de páginas.
  • Las contraseñas de grupos de páginas privan sobre las contraseñas globales.
  • Las contraseñas de administrador privan sobre las contraseñas globales, contraseñas de grupos de páginas y contraseñas de páginas.

Tapando los agujeros de orden y seguridad.

  • Por  defecto cuando editamos una página es opcional el colocar nuestro nombres para indicar autoría, esto es especialmente útil si nuestra wiki está abierta a todo público, completamente libre. Pero si estamos en el punto de haber creado cuentas de usuario debemos obligar a que utilizen su nombre en cada edición, esto se logra en el archivo config.php:
    • $Author = $AuthId; # after include_once()
  • También podemos permitir al usuario escribir el nombre que desee pero siempre aparecerá primero un prefijo que lo identifica como autor. Esto es útil si el autor desea compartir su clave con otro autor que nosotros no hemos autorizado y se desea saber quien hizo qué. En todo caso el autor/usuario con la cual se modificó la página o grupo de páginas será plenamente responsable de dichos cambios, sin importar si otra persona lo hizo.
  • Otra forma más estricta es inhabilitar el campo “autor” en el formulario de edición de cada página, pero eso cierra la posibilidad de dejar abiertas ciertas páginas o grupos de páginas (partiendo del principio de que cada quien desea ser conocido por los cambios realizados).
  • Si tenemos varias wikis corriendo en un mismo servidor (diferentes dominios o subdominios) debemos decirle a PHP que cada wiki tiene su propia y particular sesión agregando al principio de config.php la siguiente línea (por supuesto, generad vuestr propia clave aleatoria, y una por cada wiki que tengáis):
    • session_name('XYZSESSID');
  • Podemos establecer varias contraseñas para ‘admin’ con array() en el archivo config.php recordando el habilitar cuentas de usuario y contraseñas, forzando el grabado de autorías (ver párrafos anteriores) para saber quién hizo qué.
  • Podemos predefinir los grupos de páginas que contendrá nuestra PmWiki (más bien muchos verán esto como una restricción pero todo está en el diálogo entre los autores) por medio de insertar en config.php la siguiente clave: “$GroupPattern = ‘(?:Sitio|PmWiki|Principal|Ventas|Compras)’;” y si necesitamos ampliarla pues le agregamos otro caracter tubería seguido de los nuevos grupos.

Manejando la “internacionalizaciones”.

Las llamadas “internacionalizaciones” (“i18s“por su abreviatura en inglés de las 18 letras -22 en castellano-) son las traducciones a otros idiomas de PmWiki. Como bien sabemos el lenguaje PHP fue escrito en idioma inglés y PmWiki no es la excepción. La solución que planteó el Dr. Patrick Michaud está plasmada en dos aspectos fundamentales: la traducción de los “diálogos comunes” y la creación por parte de la comunidad de las respectivas páginas “tutoriales” que describen la instalación, uso y mantenimiento de PmWiki. Por ello divideremos esta sección en dos temas “apartes”.

Traducción de los “diálogos comunes”.

En PmWiki “normalizaron” los diálogos comunes, que son las instrucciones que visualiza el usuario. Las más visibles de ellas son “View Edit History Print Backlinks” que vemos en la parte superior derecha de cada página. El mecanismo es el siguiente: existe un archivo principal, el núcleo o corazón de PmWiki llamado “pmwiki.php” el cual nuestro servidor web ejecuta y carga los diversos componentes -que no vienen al caso por la complejidad del asunto-.

Lo que queremos ejemplarizar es cuando se carga el archivo “Site.PageActions” en la carpeta wililib.d allí tenemos unos cuantos mensajes al usuario, uno de ellos un enlace para modificar la página que esté en ese momento visualizando, otro para ver su historial además de las paǵinas relacionadas (y hay más enlaces/opciones).

En forma de matriz llamada text() se cargan los diferentes mensajes predefinidos por una estructura (de nuevo, estamos simplifanco al máximo) hasta llegar a los simples mensajes que acompañan una “acción”, cargar pmwiki.php más el parámetro a ejecutar (cuando el usuario hace click en la opción/enlace correspondiente):

  • “Edit” -> “pmwiki.php?action=edit
  • “History” -> “pmwiki.php?action=diff
  • “Backlinks” -> “pmwiki.php?action=search&q=link={*$FullName}” (donde $FullName es una variable: el nombre de la página que estamos visualizando y sus páginas relacionadas -no existen jerarquías en PmWiki, solo existe en nuestros cerebros-)
PmWiki Site.PageActions
PmWiki Site.PageActions

Aquí es que vamos a llegar al meollo del asunto: dichas palabras “Edit”, “History” y “Backlinks” aparecen  en el código no como texto en sí, sino como “variables”: “$[Edit]”, “$[History]” y “$[Backlinks]” de manera tal que esas variables definidas se puedan especificar en un archivo con la extensión “.XLPage” con el siguiente contenido según nuestros ejemplos seleccionados:

  • ‘Edit’ => ‘Editar’
  • ‘History’ => ‘Historial’
  • ‘Backlinks’ => ‘Retroenlaces’

Resulta ser que para nosotros en supuesto “idioma español” nos asignaron dos letras “Es” de esta manera nuestro idioma vienen ser definidos los mensajes comunes en un archivo llamado “PmWikiEs.XLPage“. Pensamos que deberíamos diferenciarnos porque en España se hablan varioas idiomas: gallego, castellano, catalán, vasco y portugués… que está bien, Portugal se independizó y cogió otro rumbo y otro idioma pero forma parte de lo que los romanos al civilizar llamaron “Hipania” (perdón por la lección de historia, je, je, je). Somos de la idea de que deberíamos tener OTRAS letras como, se nos ocurre “cas” (ya “ca” está tomado por el idioma catalán) pero en fin, todos llevamos dentro nuestro pequeño “Don Quijote de la Mancha” y en cada molino vemos fieros gigantes ¡ja!

Traducción de las páginas en sí.

Al abrir la página principal de PmWiki sin haberla internacionalizado (a eso vamos) en el panel izquierdo (“slide panel”) aparecerá varias opciones -en inglés- de las cuales las tres primeras (hay site opciones en esa sección) dirán:

  • “Initial Setup Tasks”
  • “Basic Editing”
  • “Documentation Index”.

Si colocamos el puntero sobre ellas, sin hacer click, veremos que sus enlaces web (llamados a pmwiki.php acompañados de un parámetro) serán los siguientes -coloreamos para que veáis las diferencias, no colocamos el enlace completo porque cada dominio web es diferente-:

  • pmwiki.php?n=PmWiki.InitialSetupTasks
  • pmwiki.php?n=PmWiki.BasicEditing
  • pmwiki.php?n=PmWiki.DocumentationIndex

Lo coloreado en color marrón son “páginas del sistema” de PmWiki y son las que debemos traducir ¿recordáis las dos letras de código de nuestro idioma? Pues las debemos intercalar para que apunten a los archivos que vamos a descargar con las traducciones:

  • pmwiki.php?n=PmWikiEs.InitialSetupTasks
  • pmwiki.php?n=PmWikiEs.BasicEditing
  • pmwiki.php?n=PmWikiEs.DocumentationIndex

Del siguiente enlace podréis descargar los idiomas disponibles en incluso un “megapaquete” con todas las traducciones. Nosotros solo descargaremos el archivo “i18n-es.zip” el cual descomprimiremos y “subiremos” a nuestro servidor teniendo cuidado de darle los permisos de lectura necesarios y los ubicaremos todos en la carpeta wikilib.d

Activando el idioma deseado.

En este punto debemos editar de nuevo el dichoso fichero llamado “config.php” que está ubicado en la carpeta /local y modificar y adicionar las siguientes líneas:

include_once("scripts/xlpage-utf-8.php"); # optional
XLPage('es','PmWikiEs.XLPage');

La primera línea en realidad la descomentamos porque viene así de la plantilla por defecto, y ese comentario que indica “optional” osea opcional para nosotros es obligatorio (ya eso lo explicamos en nuestro tutorial HTML). La segunda línea indica el llamar a la función XLPage y tiene dos parámetros:

  • El primer parámetro son las letras que mostrará en el cintillo inferior en el caso que instalemos varios idiomas, no tiene nada que ver con la codificación ISO de dos letras. Por razones estéticas y debido a la cantidad de idiomas y que ninguno destque de los demás se escoge ese formato pero nada nos impide colocarle “español” o “castellano”; queda a vuestro criterio -si manejais pocos idiomas-.
  • El segundo parámetro es el nombre exacto del archivo porque los servidores GNU/Linux distinguen mayúsculas de minúsculas. Aquí queda de parte de nosotros mantener la clave ISO “Es” para claridad de nuestros archivos, debemos ser conscuentes en esto porque nuestros grupos de páginas llevarán siempre el perfijo PmWikiEs.

Mejorando la selección de idioma.

No sabemos quien visitará nuestra página en este mundo tan globalizado, pero si utilizan un navegador web que se haya programado según las normas del W3C lo mejor que podemos hacer es incluir en config.php el siguiente guion:

1
2
3
4
5
6
7
8
9
10
11
12
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
switch ($lang){
case "es":
XLPage('es','PmWikiEs.XLPage');
break;
case "en":
XLPage('en','PmWikiEn.XLPage');
break;
default:
XLPage('en','PmWikiEn.XLPage');
break;
}

En la primera línea por medio de PHP le preguntamos al servidor web el encabezado con que solicita la página nuestro visitante y extraemos las dos primeras letras para luego seleccionar de los idiomas disponibles que tengamos instalados, y por defecto, si no se consigue, pues lo mostramos en ingéls, el lenguaje “materno” de PmWiki. Lo hemos probado con Mozilla Firefox 53 y funciona.

Visualizando por primera vez nuestra página en nuestro idioma.

Pues tan simple como recargar la página y los mensajes comunes estarán en nuestro idioma… pero hasta allí llega nuestra “alegría de tísico” (por lo poco que dura antes de entrar en un atque de tos). Resulta que igual nos aparece en inglés todo lo demás y he aquí que debemos comenzar a trabajar.

PmWiki página principal por defecto -idioma español establecido-
PmWiki página principal por defecto -idioma español establecido-

La primera página que modificaremos es precisamente la principal llamada “Main.HomePage” la cual, por ahora, no hemos encontrado manera de cambiar al castellano. Lo que es cierto es que podemos -y debemos- modificarla borrando todo el contenido en inglés e ir creando nuestro propio contenido para luego modificar el panel izquierdo (“edit SideBar”).

Nuestro primer grupo de páginas.

Aunque suene extraño vamos a aventurarnos a crear dos grupos de páginas de una vez. Para ello ya estamos modificando la “Main.HomePage” (luego de haber introducido nuestra contraseñade edición, si la hubiéramos establecido) y escibiremos el siguiente código:

[[WikiAeroplanos | Aviones]]
* [[WikiAeroplanos.Cazas | Uso militar]]
* [[WikiAeroplanos.Pasajeros | Transporte]]
* [[WikiAeroplanos.Hidroaviones | Mixto]]

[[WikiTrenes | Trenes]]
* [[WikiTrenes.Electricos | Siglo XXI]]
* [[WikiTrenes.Vapor | Siglo XX]]

Le damos guardar y al recargar la ápgina veremos lo siguiente:

PmWiki creando grupos de páginas
PmWiki creando grupos de páginas

¿Observáis los signos de interrogación que nosotros no escribimos? Pues es la maner de PmWiki indicarnos que dicho tema no ha sido escrito. Aquí radica la sencillez y rapidez de PmWiki: cuando hacemos click se abre inmediatamente para editar cada una de las págins que queremos desarrollar. He aquí que le vamos agregar un poco de complejidad a cada una de ellas.

Fuentes consultadas.

En idioma francés.

En idioma inglés.

PTT: Python Twitter Tools by Mike Verdone

Desde hace tiempo venimos utilizando nuestro propio robot (o “bot” como es la moda ahora mentarlos) para promocionar esta nuestra y vuestra humilde página web por Twitter y la verdad es que no habíamos prestado mayor atención al trabajo hecho con la librería que permite hacerlo. Utilizamos Twitter por su simplicidad y el soporte que tenía por medio de mensajes de texto “Short Message Service SMS“a los móviles celulares: sencillo y elegante. Pero mejor estructuremos esta entrada para explicaros (y compartir) nuestro conocimento acerca del tema ¡Vengan con nosotros en este nuevo registro en la bitácora!

Breve historia del Twitter.

Que no os vamos a aburrir mucho con esto, pero por algo se empieza. Como preludio consideramos justo reconocer que los creadores de Twitter debe haberse inspirado en algún momento en el famoso protocolo de comunicaciones llamado “Internet Relay Chat IRC” el cual fue creado en 1988 por Jarkko Oikarinen y que tuvo su apogeo en el año 2004 con el popular juego de acción QuakeNet (240 mil usuarios -solo esa red, a nivel mundial hay muchas otras redes de usuarios-). Desde ese año el IRC ha ido declinando en el número de usuarios y llegado el año 2006 Jack Dorsey, Noah Glass, Biz Stone y Evan Williams fundan Twitter y en seis años consiguen 100 millones de usuarios que “tuiteaban” 340 millones de mensajes diarios. Inicialmente no fue pensada como una red social sino como un blog que utilizaría los mensajes de texto por teléfono móvil y debido a su limitación de 140 caracteres se convirtió de facto en un microblogging.

Nosotros usamos Twitter desde el año 2011, justo un año después de haber comenzado a utilizar la tecnología OAuth -desarrollada en las entrañas de Twitter desde el mismo año de su nacimiento en el 2006- para ganar seguridad y libertad de programación a aplicaciones de terceros con una “Application Programming Interface API“. Acá en Venezuela el operador Movistar (antes conocida como Telcel) daba soporte para enviar mensajes al Twitter por medio de mensajes de texto al número 89338 (TWEET) y funcionaba de maravillas pero actualmente no prestan el servicio, imaginamos que por falta de arreglo económico entre ambas empresas, recordad que nadie trabaja gratis (sin embargo se ganan una buena pasta vendiendonos megabytes de datos que usamos en Twitter). Otro aspecto del impacto de Twitter en nuestra vida diaria es la inclusión del verbo “tuitear” en el Diccionario Castellano de la Real Academia Española así que si en adelante no lo incluimos entre comillas pues ya veis que es “legal” usarlo así ya que es un anglicismo formalmente reconocido (¡qué fuertes son los Poderes Fácticos del siglo XXI!).

Para aquellos que queréis saber más de la historia y funcionamiento del Twitter -en inglés, publicado en el año 2016 por Amelia Norton y creado por Andreas Schreiber en 2009- navegad hasta este sitio donde publica unas diapositivas digitales donde la primera mitad explica todo esto y más adelante entra en materia más profunda; está profusamente ilustrado y va paso a paso:

¿Que cómo era el Twitter antes del OAuth? Podéis leer este artículo publicado en el año 2009 donde dan cuenta de como “tuitear” por medio del comando curl:

curl -u usuario:contraseña -d status="Tu mensaje" http://twitter.com/statuses/update.xml

¡Increíble! Fijaos que Twitter ni siquiera era una página segura (https) y el usuario y contraseña viajaban libres por la red ¡eran otros tiempos, éramos más confiados (y con menos preocupaciones)! (Gracias Nacho por tu explicación, como veís 8 años después tus palabras aún resuenan en el ciberespacio). Acá otro artículo comentan como, incluso, como “tuitear” con PHP y curl y analizar la respuesta en formato tanto en formato XML como JSON.

Pero he aquí que ya el Sr. Nacho explicaba como utilizar el lenguaje Python con las librerías del sr. Mike Verdone creador de la “Python Twitter Tools PTT“, un software de código abierto y apoyado plenamente por la Fundación Python, y éste es el artículo principal de esta entrada.

“Python Twitter Tools PTT” por Mike Verdone.

Funcionamiento básico de la red Twitter.

Twitter siempre ha utilizado el software libre para lograr sus propósitos y en un principio utilizaba MySql como manejador de base de datos, pero pronto le quedó pequeña para sus propósitos.

Lo que aquí expresamos es a grandes rasgos, no esperéis una explicación al detal de la tecnología usada por Twitter; lo expresamos a nuestra forma y entendimiento y lo plasmamos de la manera más simple posible y si cometemos algún error hacednolos saber por nuestra cuenta Twitter @ks7000.

Ahora Twitter utiliza Ruby on Rails en servidores Java con “Content Delivery Network CDN” distribuidos en todo el mundo y cada identificador de mensaje es único y tiene información acerca de su geolocalización para poder manejar la gran cantidad de información que se genera segundo a segundo. En el acortador de direcciones ubicado en http://t.co aparte de ahorrar espacio en los mensajes también revisa y detiene los enlaces maliciosos (páginas falsas, páginas con código dañino, etc) y en el servicio https://twimg.com/ permite almacenar las imágenes que acompañan el mensaje. También han incluido soporte para emoticons que en realidad es soporte para todos los caracteres que soporta el UNICODE, así como soporte para “gifs animados” (que en realidad son convertidos a formato MP4), así como transmisión de vídeo en vivo por Periscope y a futuro vienen muchos cambios más para mantener con vida esta red. Uno de los más redituables son los “Twitter Ads” que es publicidad personalizada ¡repetimos, nadie trabaja gratis!

Twitter y el software desarrollado por terceros.

El equipo de Twitter creó y desarrolló de manera abierta la tecnología OAuth para que aplicaciones de terceros puedan acceder a ciertas características de nuestra cuenta en Twitter sin necesidad de darle nuestra contraseña de cuenta. Esto se logra de la siguiente manera:

  • Un equipo de desarrolladores se unen y crean una cuenta en Twitter. Deben colocar, al menos, un número de teléfono celular para recibir por mensaje de texto la confirmación de apertura de la cuenta deseada, así es que al menos es una persona real a quien le pertenece el número telefónico y es responsable de dicha cuenta.
  • Si es un proyecto muy grande el siguiente paso más probable es que contacten a Twitter -en San Francisco si viven y trabajan en los Estados Unidos de América o en Dublín, Irlanda, para el resto de los países del mundo- para solicitar una cuenta verificada (las cuentas que son identificadas con un símbolo azul y tooltip que las anuncia). Twitter recomienda que para proyectos pequeños -que por supuesto tienen su propio dominio web- publiquen en su página web la cuenta twitter oficial -tal como nosotros hacemos acá-. Esta norma rige también para personalidades, artistas, políticos, páginas de los gobiernos, etc.
  • Una vez hayan configurado sus datos en Twitter hay un apartado que permite crear dos token llamados “Consumer Key” (Clave de Consumidor) y “Consumer Secret” (Secreto de Consumidor) que deben ser almacenados de forma segura por los desarrolladores de la futura aplicación (en PTT está almacenada en donde alojan el código fuente, GitHub). Un token no es más que una larga secuencia alfanumérica de caracteres regidos por fórmulas matemáticas que permiten identificar de manera unívoca un objeto de software.
  • Una vez obtenida la Clave del Consumidor la aplicación debe proveer un enlace hacia Twitter con la siguiente orden:  «https://api.twitter.com/oauth/authorize?oauth_token=Consumer_Key». Si no hemos iniciado sesión en Twitter introduciremos nuestro usuario y contraseña la cual se la estamos entregando a Twitter por medio de una página web segura https, no a la aplicación en sí.
  • Una vez entramos en Twitter nos redirigirá a una página donde explica qué privilegios solicita la aplicación y y botón para aprobarla. Muy importante que leamos bien que derechos de acceso otorgamos, si estamos de acuerdo le damos aceptar.
  • Una vez que aprobamos Twitter genera a su vez otros dos token que son enviados a la aplicación que desea acceder a ciertos elementos de nuestra cuenta. Si la aplicación web está instalada en nuestro ordenador o dispositivo móvil por medio de un PIN que nos muestra Twitter por pantalla lo copiaremos y suministraremos a la aplicación para que ella obtenga por sus propios medios los dos token personalizados para nosotros y procederá a guardar en nuestra máquina. Si es una aplicación web se redirijirá la página y obtendrá ella misma los dos token necesarios.
  • El punto anterior funciona de dos maneras diferentes: en la aplicación instalada en nuestro ordenador o celular los token se almacenarán en nuestros equipos. Si es una aplicación web los token se almacenarán en el o los servidores de la aplicación. En el primer caso nosotros usaremos los 2 token personalizados -público y privado-, en el segundo caso será la aplicación de manera autónoma quien los usará -y nosotros nunca sabremos los valores de los token generados, a diferencia del primer método-.
  • En cualquier momento podemos eliminar el acceso a la aplicación si nos dirigimos a «https://twitter.com/settings/applications» y pulsamos el botón de revocar: esto simplemente hace que Twitter inactive los dos token que generamos y así negará el acceso a las partes de nuestra cuenta que habíamos autorizado.
  • Las partes de nuestras cuentas que podemos otorgar acceso son las siguientes (caso PTT):
    • Acceder a nuestra línea de tiempo (los tuits de las cuentas que seguimos).
    • Enviar mensajes públicos y/o privados con nuestra cuenta.
    • Permitir leer nuestros datos: avatar, nombre e incluso nuestro correo electrónico.
    • Seguir y/o dejar de seguir otras cuentas en Twitter.
  • Se ha hecho ya costumbre el crear estas aplicaciones simplemente para permitirnos emitir comentarios en las páginas web o por medio de varias páginas web que se afilien a esa aplicación: Disqus es un buen ejemplo de ello, son aplicaciones con una API basadas a su vez en las herramienta API de Twitter con el esquema de autorización OAuth.
  • Aunque logren acceder a nuestro ordenador o si nos roban o se pierde nuestro teléfono celular siempre podemos iniciar sesión en Twitter en cualquier otro equipo confiable y revocar el acceso a dichas aplicaciones: eso inutiliza los token personalizados que fueron generados.
  • De igual manera si el sitio que aloja la aplicación web que autorizamos les roban dichos token personalizados hacemos lo mismo del punto anterior. Un ejemplo de pérdida de datos fue lo sucedido con TweetGif.

Instalando PTT.

Ya hemos publicado como instalar el lenguaje Python en nuestras máquinas, así que aquí solo escribiremos como instalar las utilerías desarrolladas por el sr. Mike Verdone. Debemos entonces referiros a otro de nuestros posts donde explicamos la clasificación de las funciones en Python: las que provienen de terceros deben instalarse con PIP. Hacemos notar por experiencia propia que GNU/Linux Debian Jessie 8.8 no trae instalado por defecto el pip. No hay problema, lo que debemos hacer es escribir -con derechos de administrador root ganados con su-:

apt-get install python-pip

Tras lo cual no solicitará que introduzcamos el DVD N° 1 (el 2° y el 3° contienen aún mucho más software pero menos utilizados) por lo que nos ahorramos el conectarnos a internet (por eso decimos que viene “instalado por defecto” en las distribuciones GNU/Linux). Una vez tengamos instalado el pip debemos lanzar la siguiente instrucción:

sudo -H pip install twitter

El parámetro -H en sudo (o, si gustan, –set-home) especifica que la política de seguridad sea fijada en el usuario actual que ejecuta el comando a efectos de registrar una entrada en la base de datos de contraseñas del usuario, aunque es la opción por defecto hay que recalcarsela cuando instalemos cualquier otro paquete con PIP. Acá podéis ver el resultado del comando, nos instala la última versión disponible a la fecha, la 1.17.1:

sudo -H pip install twitter
sudo -H pip install twitter

Comentarios de Mike Verdone sobre la versión 1.9.1

En enero de 2013 anunció la liberación de la versión 1.9.1 con las nuevas características para el momento pero lo que nos llamó la atención fue el siguiente comentario en el último párrafo en su blog:

At this point I rarely do dev work on Python Twitter Tools. I merely evaluate and merge the pull requests submitted by other talented developers. A great big thank you to all of them! Their names reside safely in the Git project history, for all eternity.

Que traducido al castellano sería más o menos lo siguiente:

En este momento raramente desarrollo trabajo en “Python Twitter Tools”. Yo simplemente evaluo y uno las propuestas enviadas por otros talentosos programadores. ¡Un grandioso agradecimiento a todos y cada uno de ustedes! Sus nombres reposarán de forma segura en la historia del proyecto (en formato Git), por toda la eternidad.

Esto, para nosotros, es poesía para nuestros oídos y una muy buena apología al Software Libre, ¡Libertad!

Configurando PTT por primera vez.

El Python Twitter Tools viene conformado por dos componentes: las librerías en si mismas -que podremos usar si tenemos nuestras propios token otrogados por Twitter a traves de nuestra cuenta allí creada- y un archivo ejecutable llamado twitter que podremos llamar por medio de una ventana terminal.

Primero explicaremos como usar el ejecutable compilado con ayuda los token pertenecientes a Mike Verdone, es decir, vamos a autorizar única y exclusivamente al programa twitter que instalamos por medio de PIP para que interactue con nuestra cuenta en Twitter.

twitter authorize
twitter authorize

Lanzamos una ventana terminal y escribimos simplemente “twitter authorize” lo cual hará que dicho software lance un navegador por el siguiente enlace:

Authorise Command-line Tool to use your account?
Authorise Command-line Tool to use your account?

Notad que la página web es segura, “candado verde” (si no hemos iniciado sesión e Twitter, pues ingresad y la página se redirige) y que nos explica brevemente que accederá a leer los tuits que publican a quienes seguimos -esto es conocido como línea de tiempo o “timeline” en inglés-, ver la lista de quienes seguimos -y el permiso de seguir nuevas cuentas-, actualizar nuestro perfil cosa que nos sorprende ya que no vemos opciones documentadas para hacer esto (cambiar nuestro nombre, avatar, etc) lo cual investigaremos en detalle para qué quiere tener acceso a este renglón, y por último la habilidad de tuitear por nosotros de una manera automatizada (vamos a comenzar por esto último, enviar un mensaje al ciberespacio).

Una vez hallamos autorizado a la aplicación en la página del Twitter nos mostrará un PIN el cual fue pensado para aplicaciones que no tienen una interfaz web -léase aplicaciones de líneas de comandos- al cual el PTT llama con un argumento distinto al comando oauth_callback (toma el valor oob “out-of-band”). Dicho PIN debemos introducirlo en la entrada que requiere PTT tras lo cual se comunicará -vía curl, imaginamos con Twitter para obtener nuestros token personalizados que serán almacenados en la siguiente ubicación: ~/.twitter_oauth (un archivo oculto en nuestra carpeta personal “home”).

Una vez hallamos configurado adecuadamente la aplicación, no tenemos mas que escribir nuestro primer mensaje por medio de PTT: “twitter set” tras lo cual pedirá que ingresemos nuestro mensaje, presionamos intro y listo, se fue al universo del microblogging nuestra prueba:

Usando PTT (agradecimiento incluido):

Este mensaje lo enviamos el día 20 de mayo de 2017, cuando publicamos esta entrada (nosotros publicamos cuando consideramos tenemos algo suficientemente redactado, luego lo refinamos y con el paso del tiempo lo mantenemos actualizadas cada una de nuestras entradas en nuestro blog). En ese mensaje recibimos un “me gusta” por parte del usuario @sixohsix (ya comentamos que toda aplicación web de Twitter debe tener, por supuesto, una cuenta en Twitter).

Revisando cada una de las acciones de PTT.

Seguimos revisando la aplicación compilada twitter por la línea de comando, luego veremos el uso de las utilerías y programaremos. Para PTT es necesario tener instalado argparseque ya os hemos explicado como funciona– y es la que permite introducir “twitter -h” para saber sus acciones y preferencias. De número uno la opción por defecto es la que estudiaremos.

“twitter” ó “twitter friends”.

Al escribir “twitter” estamos invocando en realidad “twitter friends“: esto devuelve por pantalla los mensajes o tuits -incluyendo los retuits- de las cuenta a las cuales seguimos. Recordad que vuestra velocidad de conexión al internet influirá en la respuesta, paciencia que puede tomar cierto tiempo.

Como nosotros vamos de programación, y por ende de tareas automatizadas, el primer uso que le vamos a dar es filtrar resultados con grep mediante el comando tubería. Lo que vamos a buscar son los tuits que contengan la palabra -valga la publicidad- “Samsung” utilizando la salida stdout al comando de filtrado grep de la siguiente manera:

twitter friend | grep "Samsung"
twitter friends | grep “Samsung”

Primero notad que debemos acostumbrarnos a entrecomillar siempre la clave a buscar ya que Twitter utiliza etiquetas cuyo prefijo es el caracter numeral “#” el cual significa comentario en el shell bash.

“twitter help” ó “twitter -h”.

Por supuesto esta opción es insoslayable: retribuye las opciones documentadas o declaradas (como tenemos acceso al código fuente podremos estudiar y buscar opciones no documentadas debidamente).

“twitter follow” y “twitter leave”.

Recordemos que le dimos permiso a la aplicación de seguir o dejar de seguir otra cuenta en Twitter, así que para seguir una cuenta escribimos “twitter follow @nombre_de_la_cuenta” y para dejar de seguirla “twitter leave @nombre_de_la_cuenta“. Nosotros la probamos con @cementerio una cuenta argentina que se dedica a emitir día a día el fallecimiento tanto de personajes famosos a nivel mundial como a nivel local, mirad la imagen:

twitter follow y twitter leave
twitter follow y twitter leave

“twitter list” y “twitter mylist”.

Una lista en Twitter simplemente es un conjunto de cuentas que agrupamos según un criterio definido, en nuestro caso clasificamos a los desarrolladores de software por cada país del mundo. Las listas pueden ser públicas como privadas así que si vemos alguna cuenta que NO sigue a nadie no necesariamente quiere decir que sea una cuenta inactiva, tal vez tenga una lista privada para recibir información de manera discreta. Con “twitter list @nombre_de_usuario” podremos obtener los nombres de las listas públicas de un usuario de Twitter, lo estemos siguiendo o no (por supuesto, si no lo seguimos y su perfil es público). De lo contrario, si la cuenta está “protegida” (perfil privado) devolverá el error 34 con el mensaje “‘Sorry, that page does not exist.“; esto es así por la máxima privacidad al usuario: cuando le preguntamos al Twitter éste lo niega, incluso su existencia (es decir, no anuncia que la cuenta es privada). De esta opción hicimos pruebas pero no publicamos las cuentas protegidas que consultamos para conservar la privacidad pero hemos de deciros que funciona a la perfección (si acaso podríamos hacer un “fork” para el tratamiento de mensajes de error, -vamos a ver hasta dónde llegamos-). Con la opción mylist y como son nuestras propias listas, obtendremos tanto listas públicas como privadas.

“twitter replies”.

Con este comando nos retribuye las últimas respuestas a nuestros tuits -primero los más antiguos-, valga decir que son mensajes que se hilan en una nueva conversación o en una existente. En Twitter esto es como un árbol con la raíz invertida: si solo son dos usuarios es una linea directa de conversación pero si varios usuarios intervienen entonces se convierte en un árbol. Es de notar, por supuesto, que si uno opta por silenciar “mute” una conversación, ya no recibiremos aviso alguno de la misma.

“twitter search”.

Al nosotros utilizar esta opción de inmediato nos devolvió error (y no, no es por incluir el “octothorpe” o símbolo numeral que tiene un signficado especial en Python). El error está “denunciado” en este enlace y en la medida de lo posible estamos revisando el código para ver si podemos ayudar en algo.

“twitter shell”.

Todos los argumentos que acabamos de ver los ejecutamos directamente de la consola de nuestra distribución GNU/Linux pero si usamos “twitter.shell” entraremos en el prompt del propio PTT: así podremos escribir “set ‘mensaje'”, presionar intro y enviamos nuestro mensaje. Es decir, nos ahorramos la palabra “twitter” en cada llamado.

twitter shell
twitter shell

Para salir del shell del PTT solo debemos pulsar la tecla CTRL+D tras lo cual preguntará la aplicación “You really want to Leave (Y/n)? ” y pulsamos la tecla “Y”, presionamos intro y “salimos” al shell de nuestro ordenador.

“twitter rate”.

Así como hay un límite máximo de 100 tuits por hora para cada cuenta en Twitter (si emitimos 100 tuits en 100 segundos -un minuto y cuarenta segundos- estaremos bloqueados por una hora más o menos) también hay unos límites en las tareas automatizadas. Cada límite está establecido para cada uno de los métodos establecidos en la API y sería largo de enumerar aquí; algo relevante es que dichos valores se “reinician” cada 900 segundos, osea cada 30 minutos. Como veís, es muy similar al límite que comentamos al principio, solo que el bloqueo dura media hora en vez de una hora completa.

“twitter repl”.

Con este comando entraremos en una ventana normal de Python pero con un mensaje de bienvenida que es más que elocuente:

twitter repl
twitter repl

En el anuncio nos indica que por medio del objeto “twitter” (declarado y conectado por un script o guion previo) podremos interactuar con la REST API lo cual consideramos algo avanzado y creemos con propósitos de depuración a bajo nivel. Para salir usamos CTRL+D, recuerden que estamos en Python terminal. Por ahora no le encotramos mayor utilidad y lo dejamos tranquilo para pasar al otro comando que nos parece tremendamente útil.

“twitter pyprompt”

Esto si lo consideramos muy útil y sirve como paso previo antes de comenzar nuestros ejemplos y pruebas con las librerías en sí mismas: si con twitter shell podemos escribir solo los comandos (set, rate, etc.) con este comando tendremos un objeto “twitter” declarado y conectado con el cual podremos programar aspectos más vanzados, como por ejemplo tuitear incluyendo imágenes. La diferencia principal es que estaremos conectados con los token que autorizamos (¿recuerda “twitter authorize”?) y podemos programar a nuestras anchas, en cambio al lanzar Pythom e importar la librería debemos nosotros mismos sumistrar los 4 elementos completos:

  • token (del lado de la aplicación registrada en Twitter).
  • token_secret (del lado de la aplicación registrada en Twitter ¡estricto cuidado NO difundir!).
  • consumer_key (del lado nuestro, los token que solicitamos y autorizamos).
  • consumer_secret (del lado nuestro, los token que solicitamos y autorizamos ¡estricto cuidado NO difundir!).

Si a la final metemos la pata y hacemos pública nuestro token privado de cliente, pues iniciamos sesión en Twitter y revocamos el acceso a la aplicación. Si somos desarrolladores y hacemos pública nuestro token privado de aplicación (tal como hizo PTT) pues vamos con la cuenta twitter con que creamos la aplicación y le revocamos el acceso. Como veís la seguridad está en parte garantizada y Twitter feliz de la vida delegando esas responsabilidades en nosotros: ellos ponen la maquinaria, nosotros la mano de obra.

Preferencias u opciones de PTT.

De las acciones que estudiamos anteriormente, estas preferencias son compatibles con todas ellas, comenzemos por “–refresh”.

Opción “-r” ó “–refresh”.

Cuando utilizamos el comando grep para filtrar resultados -de una manera “rudimentaria” bien pensamos agregar el comando al crontab de nuestro sistema GNU/Linux pero no es necesario llegar a tanto. Para ello contamos con la opción “-r” ó “–refresh” para que el comando que corriendo indefinidamente hasta que presiones CTRL+C para interrumpir el proceso. De manera predeterminada el intervalo es de 5 minutos (300 segundos) pero con la opción “-R” ó “–refresh-rate” podemos especificarle un valor en segundos que querramos -e incluso programar para que sea un valor aleatorio-. De las pruebas que hicimos nos dimos cuenta que valores inferiores a 60 segundos devuelve error el Twitter: recordad que no debemos sobrecargar a los servidores de dicha empresa con solicitudes tan frecuentes.

twitter friends --refresh
twitter friends –refresh

Opción “-l” ó “–length”.

Otro valor por defecto es el número de mensajes retribuidos, el valor normal es 20 pero podemos pedir uno solo o el que queramos pero con un maximo de 200 mensajes o tuits. Como por consola es difícil ver dónde termina y dónde comienza cada mensaje la siguiente opción nos permitirá contar de lo lindo el número de tuits retribuidos a ver si es verda que se ejecuta tal como lo pedimos.

Opciones “-t” ó “–timestamp” y “-d” ó “–datestamp”.

Con estas opciones podremos colocar tanto la hora y minuto como la fecha de cada mensaje, algo útil si queremos guardar los datos en una tabla de base dedatos y ordenarlos luego de forma cronológica. Atención: la hora y fecha de cada mensaje es, por supuesto, cuando lo emitieron originalmente pero cuando alguien a quien nosotros seguimos lo retuitea -o reenvía- nos mostrará fecha y hora del retuiteo, no de la hora y fecha original.

Opción “–no-ssl”.

Esta opción de facto está eliminada: toda transacción hoy en día con los servidores de la empresa Twitter solamente están disponibles en formato segor https: toda nuestra información viaja cifrada entre nosotros y Twitter.

Opción “c” ó “–config”.

Si decidimos almacenar nuestro usuario y contraseña en un archivo con esta informacón la podemos cargar con esta opción. No se nos ocurre un uso práctico, sin contar que los datos, de manera implícita, estarán almacenadas en texto plano, un riesgo de seguridad para nosotros. Por esa razón es que dudamos -como dice la ayuda- que es para guardar usuario y contraseña. En más detalle indica que dicho archivo de configuración permite guardar consultas personalizadas siempre y cuando dentro del archivo tenga el encabezado “[twitter]” y a continuación en una línea que comienza con la etiqueta “format:” le colocamos las opciones que ya revisamos y en otra línea algo nuevo: un prompt personalizado en texto y colores. Esta opción es la más adecuada “para despertar al nerd que hay en tí” ja, ja, ja 😉 .

Opción “–oauth”.

De igual manera que la anterior pero con nuestras propias crdenciales como es nuestro caso. os explicamos mejor, nosotros registramos una aplicación en Twitter que generó los cuatro tokens que explicamos párrafos atrás. Si los colocamos en un archivo ocn esta opción nos conectaremos por nuestra aplciación y no por la de PTT.

Opción “–format”.

Si lo que queremos es ver nosotros mismos de una manera agradable por pantalla podemos optar entre los siguientes:

  • default: bueno, es como si no hubieramos escrito nada, una línea por mensaje.
  • verbose: múltiples líneas por mensaje.
  • json: devuelve los datos en este popular formato.
  • urls: si solamente queremos ver los enlaces (recordad que Twitter usa acortador de direcciones).
  • ansi: la mejor opción, colores a diestra y siniestra.

 

Licencia de uso de PTT.

Python Twitter Tools se rige por la Licencia del Instituto Tecnológico de Massachusetts (Massachusetts Institute of Technologies MIT) del año 2008 y donde aparece el sr. Mike Verdone como único propietario:

Copyright (c) 2008 Mike Verdone

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

La Licencia del MIT permite uso privado, modificación, distribución y uso comercial con la condición de que la licencia sea distribuida junto con los demás ficheros de la aplicación y la advertencia de que no se hacen responsables del mismo (en el software libre los únicos responsables somos nosotros mismos, esta parte de la licencia es muy dura de entender por los usuarios acostumbrados al software privativo).

Equipo de desarrollo de PTT.

He aquí una lista de las personas que participan -y mantienen al día- el proyecto “Python Twitter Tools” -una lista actualizada la podeis encontrar en este enlace en GitHub, al momento presente son los siguientes:

Developers:
Mike Verdone <mike.verdone@gmail.com>
Hatem Nassrat <hnassrat@gmail.com>
Wes Devauld <wes@devauld.ca>

Contributors:
Horacio Duran <horacio.duran@gmail.com> (utf-8 patch for IRC bot)
Rainer Michael Schmid (bugfix: crash when redirecting output to a file in 1.1)
Anders Sandvig (cmdline -l, -d, and -t flags)
Mark Hammond (OAuth support in API)
Prashant Pawar (IRC bot multi-channel support)
David Bittencourt (python 2.3 support)
Bryan Clark (HTTP encoding bugfix, improved exception logging)
Irfan Ahmad <http://twitter.com/erfaan> (Fixed #91 rate limit headers and #99 twitter API timeouts)
StalkR (archiver, follow)
Matthew Cengia <mattcen> (DM support, ISO timezone support, more API 1.1 support)
Andrew <adonoho> (Fixed streams support for HTTP1.1 chunked answers)
Benjamin Ooghe-Tabanou <RouxRC> (Helped fix streams support for HTTP1.1 chunked answers, added image support and more API 1.1 support)

Fuentes consultadas:

En castellano:

En idioma inglés:

PHP tutorial

Un lenguaje importante y que hemos dejado de lado por años es el ya muy famoso lenguaje PHP. En desagravio publicamos esta entrada y le queremos dar características especiales: no insisteremos en ser detallistas al extremo, se trata de una introducción, un tutorial que lleve paso por paso a cualquier persona que desee aprender dicho lenguaje de programación. Por ello no publicaremos su historia, configuración del servidor, etcétera. Os recordamos que para aprender PHP sería bueno tener conocimientos mínimos de HTML, CSS y JavaScript.

PHP de manera “sucia y rápida”.

No nos asustéis con la traducción al castellano del popular refrán en idioma inglés “quick and dirty”, que siempre se recuerda cuando se necesita desarrollar algún software que goce de pragmatismo al extremo. Lo que queremos decir es que cuando uno necesita resultados rápidos pues conviene saltarse los “paso a paso” que siempre usamos para aprender algo nuevo.

Elementos básicos en PHP.

El lenguaje PHP bien puede utilizarse en comandos por una venta terminal o bien lo podemos usar un proceso por lotes almacenados en un archivo de texto al cual le colocaremos una extensión “.php” para identificar de manera rápida su contenido. Siendo entonces un fichero en texto plano procedemos a escribir dentro de él lo siguiente:

<?php
  // aquí va el código
?>

Estas tres simples líneas le indican al servidor dónde comienza y termina las instrucciones que va a ejecutar en lenguaje PHP. Esto es así porque dentro de un archivo “.html” podremos incluir código especial que muy probablemente emita código en lenguaje HTML de manera dinámica (por ejemplo, una consulta en una base de datos para mostrar los valores seleccionados por el usuario). Las dos barras inclinadas “//” indica que todo lo que está a la derecha y hasta el final de la línea son comentarios y que no deben ni serán ejecutados. Tambien sirve “#” para comentar una línea, pero si necesitamos comentar varias líneas escribimos “/* comentario(s) */“.

Con excepción de las líneas de comentarios, inicio y cierre, toda las demás líneas deben terminar con un punto y coma “;“.

Variables en PHP.

Toda variable comienza con “$” y un caracter A-Z (mayúsculas y/o minúsculas) y/o el guión bajo “_“, luego se pueden usar números y/o caracteres sin dejar espacios. Se pueden clasificar en:

  • Número entero (positivos o negativos).
  • Número flotante (número decimal positivos o negativos).
  • Booleano (verdadero o falso).
  • Cadena de caracteres (las almacenamos con comillas simples).

Hay cuatro tipos más de variables avanzadas que veremos en su debida oportunidad. Una vez hallamos guardado un valor en una variable se pueden mostrar por pantalla por medio de las ordenes echo o print(), las cuales tiene muchas opciones que veremos más adelante pero detallaremos que no es lo mismo usar comillas simples que dobles con dichas funciones, mirad este ejemplo:

<?php
  miValor = 5;
  echo '<p>El valor es $miValor .</p>';
  echo "<p>El valor es $miValor .</p>";
?>

Y devolverá lo siguiente (código HTML recibido por el navegador, en Mozilla Firefox pulsad las teclas CTRL+U):

<p>El valor es $miValor.</p><p>El valor es 5.</p>

Así vemos que el comando echo bien puede “pasarle” al navegar el texto (en este caso texto + lenguaje HTML) o bien puede mediante instrucciones especiales “pasar” el valor almacenado en una variable. Notad que aunque los comandos en PHP es indistinto si los escribimos en mayúsculas y/o minúsculas las variables son sensibles: no es lo mismo $miValor que $MiValor, mucho cuidado con eso que causa bastantes dolores de cabeza a nosotros los programadores.

Otro uso en el campor de las variables, aunque poco utilizado, es declarar una segunda variable por referencia con otra variable. Para esto usamos el caracter “&” justo delante de la variable que queremos pasar. Ejemplo:

$a = "texto"; $b = &$a; echo $b;

Suma de variables en PHP.

Para sumar dos variables, ya sea para presentarla por pantalla o para almacenarla en otra variable, utilizamos los operadores matemáticos de costumbre, mirad:

<?php
 $a = 5; $b = 10; $c = $a + $b;
 echo "a + b =";
 echo $a + $b;
 echo "<br>c=";
 echo $c;
?>

Concatenar variables en PHP.

Decimos concatenar en el caso de variables de texto, en PHP con un simple punto unimos la variables:

<?php
 $a = "Inicio"; $b = " fin.";
 echo $a.$b;
?>

Declaración y alcance de las variables en PHP.

Como estudiamos hace poco, no es necesario decirle a PHP qué tipo de variable vamos a trabajar, simplemente ponemos los valores y el lenguaje se encarga de almacenarlo en el lugar adecuado. Cuando vayamos a realizar operaciones con dichas variables éstas se convertirán de a un valor correcto, por ejemplo:

<?php
 $a = "palabra"; $b = 5;
 echo $a + $b;
 echo "<br>";
 echo $a.$b;
?>

El resultado por pantalla será “5”, es decir, el valor de $a es una cadena de texto cuyo valor numérico es cero y así lo convierte para sumarlo a $b. Por el contrario, en la siguiente línea $a.$b estamos concatenando cadenas de texto y el valor de $b se convierte en el caracter “5” para mostrar lo siguiente:

5
palabra5

En PHP podemos “forzar” que una variable sea de un tipo específico que necesitemos, para ello usar el comando settype() con dos argumentos entre paréntesis separado por una coma: nombre de la variable y luego el tipo de variable (“integer”, “double”, “string”, “booelan”), ejemplo: «setttype( $a , “integer”)».

Otra manera de forzar a un tipo de variable es de la siguiente manera: «$variable = (int) $variable;» en este caso (int) o (integer) indica que lo cambie a tipo entero pero podemos usar también (real), (double), (float), (boolean) o (bool).

Otra cosa es el alcance de las variables: si están en el módulo principal las variables serán globales y si están dentro de una función serán locales y solamente podrán ser accesibles dentro de la función donde fueron “creadas”. Si necesitamos que una variable dentro de una función esté disponible para otras funciones (y en el módulo principal) usaremos la palabra global y a continuación le asignaremos el valor; de facto estamos declarando la variable al asignarle un valor.

Cuando declaramos una variable como global ésta se adiciona a la matriz $GLOBALS[‘nombre_de_variable’] y podemos acceder a ellas de esta manera nemotécnica, especialmente es útil para usarla dentro de funciones; ejemplo: «echo $GLOBAL[‘cadena’]». Aunque aún falta mucho para ver las funciones, podemos adelantar el siguiente código que ilustra el alcance de las variables locales y globales:

<?php
 $variable1 = 'ABC';
 $variable2 = 123;
 function mi_funcion(){
  $variable1='perro';
  echo $variable1.'<br>';
  echo $GLOBALS["variable1"].'<br>';
  echo $GLOBALS["variable2"].'<br>';
 }
 mi_funcion();
?>

Si necesitamos que una variable dentro de una función conserve su valor entre llamadas, debemos declararla con el comando static dentro de la función a la que pertenece y asignarle un valor, por supuesto.

Incrementos y decrementos en variable numéricas.

Como es popular en lenguaje C++ los incrementos se logran colocándole “++” (o “–” si es un decremento) luego del nombre de la variable. En este ejemplo ambas líneas son equivalentes pero en una escribimos más que en la otra:

<?php
 $a = 10;
 $a = 10 + 1;
 echo $a."<br>";

 $a = 10;
 $a++;
 echo $a."<br>";
?>

Pero fijaos que al mostrarlo en pantalla, cuando el incremento (o decremento) lo colocamos ANTES o DESPUÉS de la variable se comporta de manera diferente, cambia el orden de como se ejecutan las instrucciones:

<?php
 $a = 10;
 echo "Incremento posterior:<br>";
 echo $a++."<br>";
 echo $a."<br>";
$a = 10;
 echo "Incremento anterior:<br>";
 echo ++$a."<br>";
 echo $a."<br>";
?>

Operaciones artiméticas en PHP.

Aparte de las cuatro operaciones básicas (suma “+”, resta “-“, multiplicación “*” y división “/”) debemos señalar también al módulo “%” (devuelve el residuo de la división, si es cero la división es exacta) y la exponenciación “**”.

Otros operadores importantes son la suma y asignación “+=”, resta y asignación “-=”, multiplicación y asignación “*=”, división y asignación “/=”, módulo y asignación “%=” y concatenación y asignación “.=”. Esencialmente lo que hace es aplicar el operador aritmético al valor ya almacenado en la variable con el otro valor a la derecha del signo de igualdad. El siguiente código ilustrará mejor:

<?php
 $x=10;$x+=5;echo $x."<br>"; # resultado 15
 $x=10;$x-=5;echo $x."<br>"; # resultado 5
 $x=10;$x*=5;echo $x."<br>"; # resultado 50
 $x=10;$x/=5;echo $x."<br>"; # resultado 2
 $x=10;$x%=5;echo $x."<br>"; # resultado 0
?>

Operadores de comparación.

Necesitamos oepradores que permitan comparar dos variables, pero en PHP hay ciertas condiciones a evaluar. Para empezar ya sabemos que las variables puede almacenar valor numérico y en la siguiente línea le podemos almacenar una cadena de texto, es por ello que necesitamos comparar, incluso, si son el mismo tipo de variable. Por ejemplo, para nosotros 5 es igual que 5,00 paro para PHP el primer valor es un número entero positivo y el segundo es un valor decimal positivo (nosotros en este sitio web nuestro separador decimal es la coma pero a nivel de lenguajes de computación el separador decimal es el punto). Veamos los que disponemos:

  • ==“: Comprueba si son iguales.
  • !=“: Comprueba si son distintos.
  • ===“: Comprueba si son iguales y de exactamente el mismo tipo.
  • !==: Comprueba si son distintos o de distinto tipo.
  • <>: Diferente (igual que !=).
  • <: Menor que, comprueba si un valor es menor que otro.
  • >: Mayor que.
  • <=: Menor o igual que.
  • >=: Mayor o igual que.
  • <=>: Comparador de orden (PHP 7).
  • ??: uno o el otro (PHP 7).

Trabajando con variables de texto.

PHP contiene comandos (funciones no declaradas por nosotros, funciones implícitas) que nos facilitan grandemente nuestro trabajo con cadenas de texto, ya vimos echo y print() veamos otras más.

Contando el número de caracteres.

Usaremos el comando strlen() pasando como argumento nuestra variable (osea colocamos nuestra variable dentro de los paréntesis del comando). Por ejemplo, el siguiente código devolverá el valor de treinta y cinco letras:

<?php
  $cadena = "República Bolivariana de Venezuela";
  echo strlen($cadena);
?>

Pero el problema aquí es que no son 35 caracteres sino 34: la letra u acentuado es contada como 2 caracteres porque se necesitan 2 bytes para representarla. En realidad esta función devuelve el número de bytes, no el número de caracteres. Ya vemos que nuestro hermoso idioma castellano, normado por nuestro brillante Don Andrés Bello, nos da y seguirá dando trabajo a nosotros los programadores.

Contando el número de palabras en una cadena de texto.

Teniendo en cuenta que una palabra esta delimitada antes y después por uno o más espacios y esté constituida por caracteres A~Z y/o a~z, el comando que usaremos es str_word_count(). Siguiendo con el ejemplo anterior:

<?php
  $cadena = "República Bolivariana de Venezuela";
  echo str_word_count($cadena);
?>

Y el resultado será simplemente cinco ¿Qué sucedió si sólo hay cuatro palabras? Pues lo mismo de siempre: los lenguajes de programación están escritos por gente de habla inglesa para los cuales los acentos, la letra eñe -y demás caracteres no pertenecientes al idioma inglés simplemente no existen. Pero esperen, aún hay más: los números tampoco cuentan como caracteres así que por lo menos no nos podemos quejar de que ellos allá en el departamente de programación de PHP no son estrictos con ellos mismos. Veremos de forma ampliada que este comando acepta un segundo parámetro llamado format que permite el resutlado de manera distinta: si es cero es el valor por defecto, uno devuelve una matriz conteniendo cada una de las palabras y dos devuelve la posición numérica de cada una de las palabras, veamos:

<?php

  $cadena = "República      Bolivariana
       de     Venezuela";
  echo "<br>Palabras encontradas:";
  echo str_word_count($cadena);
  echo "<br><br>Valor FORMAT por defecto cero:<br>";
  print_r(str_word_count($cadena, 0));
  echo "<br><br>Matriz con cada una de las palabras:<br>";
  print_r(str_word_count($cadena, 1));
  echo "<br><br>Matriz con la ubicación de cada una de las palabras:<br>";
  print_r(str_word_count($cadena, 2));

?>

Lo cual devuelve lo siguiente:

Palabras encontradas:5

Valor FORMAT por defecto cero:
5

Matriz con cada una de las palabras:
Array ( [0] => Rep [1] => blica [2] => Bolivariana [3] => de [4] => Venezuela ) 

Matriz con la ubicación de cada una de las palabras:
Array ( [0] => Rep [5] => blica [16] => Bolivariana [35] => de [42] => Venezuela )

Fijaos que la cadena de texto hemos introducido más espacios adicionales, la hemos escrito en dos líneas pero PHP la interpreta como una sola ya que al final de la segunda línea es que se encuentra el punto y coma que indica el final. También ya sabéis que la letra u acentuada cuenta como dos caracteres (ya que esa característica del juego de caracteres UTF-8 permite “ampliar” el número de bytes para representar los más de 65 mil caracteres que componen el UNICODE) y es por ello que “blica” comienza en 5 y no en 4.

Pensando ellos allá en lo anterior, a partir de la versión PHP 5.1.0 se le agregó un tercer argumento que permite especificar una excepción a los caracteres que nosotros consideramos no delimita una palabra. Esto conlleva definir un valor constante a lo largo de todo nuestro programa por medio del comando define() que toma dos argumentos separados por una coma: primero el nombre de la variable en sí y segundo el conjunto de caracteres que consideramos NO delimita una palabra y encerrados entre comillas, mirad el siguiente ejemplo:

<?php

  define( Castellano, 'áéíóúÁÉÍÓÚüÜñÑ');

  $cadena = "República Bolivariana de Venezuela.
En Güigüe se siembra mucho el ñame y el limón.";
  echo "<br><br>Valor FORMAT por defecto cero:<br>";
  print_r(str_word_count($cadena, 0, Castellano));
  echo "<br><br>Matriz con cada una de las palabras:<br>";
  print_r(str_word_count($cadena, 1, Castellano));
  echo "<br><br>Matriz con la ubicación de cada una de las palabras:<br>";
  print_r(str_word_count($cadena, 2, Castellano));

?>

Importante hacer notar que los valores constantes NO necesitan el signo “$” delante: ya PHP sabe que es un valor “especial” a tomar en cuenta. La función include() acepta un tercer parámetro: podemos especificar que el nombre de la variable NO sea sensible a mayúsculas y minúsculas. Esto quiere decir que si colocamos true en el tercer argumento, podremos llamara a nuestra constante a lo largo del programa como “Castellano” o “CASTELLANO” o “cASTELLano”, etc. Toda constante declarada es de tipo GLOBAL. A partir de PHP 7 acepta valores de matrices, solo como nota informativa.

Cadenas reversadas.

Si queremos encontrar palíndromos esta función está adecuada para ello: strrev() devuelve una cadena de texto al revés, un ejemplo en idioma latín:

<?php
 // Latín: "Damos vueltas en la noche y somos consumidos por el fuego"
 echo "in girum imus nocte et consumimur igni<br>";
 echo strrev("in girum imus nocte et consumimur igni");
?>

Encontrar una subcadena en una cadena de texto.

Función bastante usada: necesitamos saber si en una cadena de texto existe una subcadena: strpos() devolverá un valor numérico, cero o mayor si consigue la subcadena, de lo contrario devolverá un valor falso. Debemos tener en cuenta que falso=cero y cualquier otro valor es verdadero, como esta función puede devolver cualquier valor entonces debemos evaluar con el triple signo de igualdad para estar seguros que no se consiguió la subcadena. Ejemplo:

<?php
 $cad=strpos("Ministerio del Poder Popular para la Comunicación e Información.", "Comunicación"); //
 if ($cad===false){
 echo "falso";
 }else{
 echo $cad;
 }
?>

Sustituir una subcadena de texto.

Dada una cadena de texto necesitamos sustituir, si se consigue dentro de ésta, por otra cadena de texto: str_replace() hará el trabajo si le colocamos como primer argumento la subcadena a buscar, el segundoa rgumento la cadena que sustituirá -de ser encontrada- y la cadena de texto en donde se buscará. Ejemplo:

<?php
 $cad=str_replace("Sulia", "Zulia", "Maracaibo, estado Sulia.");
 echo $cad;
?>

Extraer una subcadena de texto.

Muchas veces necesitamos extraer un subcadena de texto a partir de su posición numérica hasta el fin de la cadena de texto: substr() con tres argumentos: cadena de texto, comienzo y longitud. Si se omite la longitud pues devolverá hasta el final de la cadena de texto. Si el número de comienzo es negativo devolverá la cadena contando como primer caracter el primero de la derecha, osea el final. Si no consigue la cadena devolverá un valor falso o una cadena de texto vacía.

<?php
 # Muestra "para no serlo"
 echo substr("Llamarse jefe para no serlo es el colmo de las desgracias.",14,13);
?>

Instrucciones condicionales.

Si condicional.

Para evaluar una variable y un valor o dos variables (o dos valores, algo menos común) usaremos el si condicional. En PHP tiene la siguiente estructura:

if (condición a evaluar) {instrucciones a ejecutar}

if (condición a evaluar) {
  instrucciones a ejecutar;
}

De la segunda manera resulta más ordenada y estructurada pues permite multilíneas comodamente. Si necesitamos ejecutar instrucciones diferentes según la condición verdadera o falsa:

if (condición a evaluar) {
  instrucciones a ejecutar;
} else {
  instrucciones a ejecutar;
}

Lo coloreado en verde se ejecuta si la condición es verdadera y lo coloreada en morado de ser falso. Cuando necesitamos evaluar varias condiciones, “filtro de múltiples tamices” utilizaremos esta estructura:

if (condición a evaluar) {
  instrucciones a ejecutar;
} elseif (condición a evaluar) {
 instrucciones a ejecutar;
} else {
 instrucciones a ejecutar;
}

Con el siguiente ejemplo ilustraremos mejor la estructura: con la función date() obtenemos la hora y fecha del equipo pero si le pasamos la máscara “H” nos devuelve solamente la parte de la hora y en formato militar (hora de 24 horas); se pasa por un tamiz dicho resultado y según la hora saluda de manera adecuada:

<?php
  $hora = date("H");
  if ($hora < "12") {
   echo "Buenos días.";
 } elseif ($hora < "19") {
   echo "Buenas tardes.";
 } else {
   echo "Buenas noches.";
 }
?>

Como vemos con tres condiciones revista ya cierta complejidad por lo que es necesario un operador más poderoso: el comando switch().

Interruptores condicionales.

Acá debemos abrir un poco la mente: muchas veces necesitamos comparar una variable contra diferentes valores para ejecutar una o más instrucciones e incluso necesitamos que dicha variable sea evaluada más de una vez. Para ello existe el comando switch() que evalua exactamente cada valor y si coincide exactamente ejecuta la(s) instrucción(es) y sale del ciclo con un comando break():

<?php
$i=0;
switch ($i) {
    case 0:
        echo "i vale 0<br>"; break;
    case 1:
        echo "i vale 1<br>"; break;
    case 2:
        echo "i vale 2<br>"; break;
    default:
      echo "i es mayor a 2<br>";
}
?>

El ejemplo se establece el valor en cero y solo se ejecuta la primera instrucción y sale del ciclo. Cualquier valor que NO sea 0, 1 ó 2 imprimirá “que i es mayor a 2” incluso si $i tiene un valor negativ0. Es por ello que este comando debe ser ejecutado con precaución. Otro detalle a tomar en cuenta es que si queremos ejecutar varia líneas de instrucciones debemos encerrarlos entre corchetes.

Comandos de ciclo.

Ciclo mientras “while”.

Con el ciclo while() si se cumple la condición evaluada se ejecutarán una y otra vez cada una de las instrucciones contenidas y se espera que dentro del ciclo hayan eventos que cambien el valor y poder salir del bucle, sino decimos que el ordenador “está colgado”, así que mucho cuidado con esto último:

while (condición evaluada) {
     instrucciones a ser ejecutados;
 }

Como ejemplo utilizaremos la variable k con un valor inicial de 1 y lo incrementaremos de dos en dos hasta que supere a diez:

<?php
  $k = 1;

  while($k < 10) {
    echo "Valor de <i>k</i>: $k <br>";
    $k += 2;
}
?>

Ciclo hacer mientras “do … while”.

El ciclo mientras “while” evalúa la condición y de ser cierta ejecuta el bloque de instrucciones deseado en cambio el ciclo hacer-mientras entra al ciclo, ejecuta y luego evalúa la condición: si se cumple vuelve a ejecutar de lo contrario sale del ciclo y continúa el flujo del programa. Para ilustrar bien este punto colocamos el siguiente ejemplo muy a propósito para demostrarlo:

<?php
  $k = 10;
  do {
    echo "The number is: $x <br>";
    $k++;
  } while ($k <= 5);
?>

Este código mostrará “El valor de k es: 10″ que sabemos que es mayor que 5 sin embargo el bloque de instrucciones se ejecuta al menos en una oportunidad.

Ciclo para “for”.

El anterior hacer-mientras se hace más fácil de ejecutar con el ciclo para el cual tiene tres parámetros: el que inicializa la variable, la condición que evalua la variable y el incremento en cada ciclo que le vamos a aplicar a la variable:

for (inicia_contador; evalua-contador; incrementa_contador) {
  código_a_ejecutar;
}

Con valores numéricos puede ser más “fácil” de comprender:

<?php
  For ($fuente=1; $fuente<=7;$fuente++) {
    echo "<font size=$fuente>Tamaño de fuente $fuente</font><br>";
  }
?>

Ciclo para cada “for each”.

Este comando se utiliza con matrices, se estudiará más adelante cuando veamos este tipo de objetos.

Funciones personalizadas.

Ya tocamos el tema de bastantes “comandos” o funciones implícitas en PHP: no es necesario declararlas, ya están implementadas y aunque podemos hacer bastante con el trabajo hecho de manera previa esto no es suficiente para desarrollar nuestros programas. Por esta razón PHP (y la mayoría de los lenguajes de programación) permiten hacer nuestras propias funciones, aquellas que esperamos usar de manera repetitiva en nuestros programas.

function nombre_de_funcion(argumento) {
}

Las funciones NO son sensibles a minúsculas y/o mayúsculas: no importa como la escribamos ellas son llamadas y ejecutadas. Con valores:

<?php
  function muestra_mensaje() {
    echo "Ejemplo de funciones de PHP.";
  }

Muestra_Mensaje(); // Hace el llamado a la función.
?>

Acá comprobamos que no importa como llamemos la función, ésta es ejecutada. Por ahora a esta función no le pasamos ningún argumento pero a continuación la modificamos y dentro de ella con el valor que le pasamos podemos trabajar y procesarlo para mostrarlo o devolver algún resultado en memoria:

<?php
  function muestra_mensaje($mensaje) {
    echo "Ejemplo de funciones de PHP.<br>";
    echo $mensaje;
  }
Muestra_Mensaje("¡Aprendiendo a programar en PHP!"); 
?>

También podemos pasar un argumento con un valor por defecto, dado el caso no le pasemos un valor:

<?php
  function muestra_mensaje($mensaje = "Ejemplo de funciones de PHP.<br>") {
    echo $mensaje;
  }
Muestra_Mensaje();
Muestra_Mensaje("¡Aprendiendo a programar en PHP!");
?>

Por último con la orden return variable podremos beneficiarnos del uso más poderoso de las funciones: devolver valores:

<?php
  function suma($a, $b) {
    $total = $a + $b;
    return $total;
  }

echo "5 + 10 = " . suma(5, 10) . "<br>";
echo "7 + 13 = " . suma(7, 13) . "<br>";
echo "21 + 4 = " . suma(21, 4);
?>

Fuentes consultadas.

En idioma inglés:

¿Cómo funciona Mozilla Firefox? Motor Gecko y el Proyecto Quantum

Interesante es saber sobre cómo funciona el navegador web Mozilla Firefox (para nosotros, nuestro favorito) y vamos a diseccionar y explicar de manera sencilla, sin mayores pretensiones, sus diversos componentes. Para ello comenzaremos de atrás para adelante: el último Proyecto de Mozilla Firefox llamado “Quantum“, ¡Investiguemos juntos!

Introducción.

Quantum” es, como dijimos, el último proyecto que hace de Mozilla Firefox 53 una versión destacada sobre las anteriores. Tan grande es el proyecto que hubo la necesidad de ir abonando el camino para ello con el Proyecto “Electrolysis” apuntando así a un objetivo más alto. Nosotros, por estos lares, hemos seguido de cerca la evolución de los procesadores de 32 bits a 64 bits y ha sido nuestro mayor “trauma” a la hora de programar y compilar en diferentes ambientes. Pero he aquí que en los programadores de Mozilla están más bien preocupados por los dispositivos con múltiples procesadores y, de paso, en diferentes hardwares (ordenadores de mesa, dispositivos portátiles, móviles celulares y paren ustedes de contar).

Ellos primero están apostando a los procesos paralelos: cada pestaña o ventana es un hilo de programación y si colapsa solo reiniciamos el que falló, no todo el proceso principal de Firefox. Por supuesto, no solo esto lo han mejorado, nosotros por acá hemos explicado la novedosa Norma de Diseño de Cuadrícula sin contar que incluyeron temas “compactos”, nuevas extensiones para el navegador, “máscaras” de CSS, mejor experiencia con archivos multimedia, y los usuarios en Microsoft Windows pueden seleccionar si instalan la versión de 32 ó 64 bits.

Componentes principales de Gecko.

Para finalizar con la introducción diremos que muchos de los componentes del proyecto “Quantum” están desarrollados en lenguaje Rust, solo por mencionar ya que no profundizaremos en el asunto (abajo están los enlaces si queréis ir más lejos). Los componentes a la fecha son los siguientes:

  • rust-bindgen: es el “conector” entre el lenguaje C++ {con el que está(ba) escrito el código de Firefox} y el lenguaje Rust.
  • Quantum CSS ‘Stylo’: maneja las Hojas de Estilo en Cascada pero de manera “paralela”.
  • Quantum Render: se encarga de “dibujar” en pantalla.
  • Quantum DOM: se encarga de estructurar el archivo recibido en HTML.
  • Quantum Flow: para analizar el rendimiento y para mejorar la aplicación.

Más adelante explicaremos los componentes considerados básicos, mantendremos al mínimo este tutorial.

Nociones básicas.

Un navegador web es un software que lee un archivo escrito en lenguaje HTML y lo interpreta según normas recomendadas y preestablecidas para mostrarlo a nosotros de una manera interactiva. Dicho archivo reposa en un servidor web y asumiremos que simplemente es un fichero que reposa en dicho sitio -esto no es rigurosamente cierto ya que hoy en día las págnas web son dinámicas, es decir se presentan de diferentes maneras según el navegador, usuario, datos solicitados e incluso según la ubicación y dispositivo-.

Decimos que un navegador web tiene un motor web (“browser engine”) y en el caso de Firefox este motor es llamado Gecko el cual tiene muchos componentes de lo cuales nombramos algunos en la introducción.

Aclaratoria necesaria.

Todo lo que aquí presentamos es cierto para la versión Firefox 53 el cual esperamos tengáis instalado ya que hay varios elementos gráficos que solo se mostrarán correctamente en esa versión (o superior).

Simplificando al máximo.

Haciendo un panorama general, toda página web se puede dividir en tres partes principales:

Documento HTML (estructura).

Como establecimos y es un hecho cierto al nosotros ejecutar cualquier navegador web y solicitar en la barra de direcciones un dominio cualquiera lo que recibimos es simplemente un fichero con instrucciones en HTML. Un vez recibido es cuando realmente comienza el proceso de leer, analizar e interpretar dicho código. En inglés a esta pieza de software le llaman parser por su derivación del idioma latín “pars orationis” (parte del discurso, estructura gramatical) y que ellos simplemente abrevian pars, lo toman como si fuera un verbo y lo convierten en sustantivo agregandole el sufijo “er”: es así que tenemos el parser y que nosotros lo llamaremos analizador (ya la web abunda en inglés, debemos construirla también en castellano ¡ayúdanos siguiendo el ejemplo!).

Modelo de Objeto Documento («Document Object Model ‘DOM’»).

Acá es donde interviene el primer analizador: se encarga de categorizar y formar un árbol a partir de las etiquetas claves en HTML: head, body, div, footer y va más allá con cada uno de los párrafos, titulares, etiquetas personalizadas, etc. de cada sección. Lo más importante es que forma un índice de elementos a modo de catálogo para que cuando sea consultado por medio de otros componentes pueda ser retribuido rápidamente. Recordad también que debido al JavaScript dicho DOM puede ser modificado posteriormente y debe ser capaz de registrar y llevar control de dichos cambios.

Nosotros vemos al DOM como una especie de base de datos donde almacenamos el código HTML de una manera normalizada.

Hojas de Estilo en Cascada («Cascading Style Sheets ‘CSS’»).

Ahora tenemos otro analizador: el que se encarga de darle formato al código HTML que está categorizado en el DOM. En teoría cada elemento en el CSS debería tener su correspondiente en el DOM. De igual manera este analizador se encarga de categorizar de manera sucesiva los estilos que estén en el fichero -o sección- CSS. Decimos de manera sucesiva porque tal vez se nombre varias veces al mismo elemento HTML y el último en ser leído será el estilo como será presentado (esto no sucede a menudo por ser un desperdicio de trabajo redundar en el estilizado de componentes). Este último resultado es el que se va a proceder a enviar al motor de diseño.

Motor de Diseño («Layout»).

Ya con el estilo aplicado cada uno de los componentes son preparados para ser dibujados y dejarlo listo en capas para pasarlo al siguiente paso.

Motor de Capas

Recibe las capas y las lleva en orden de jerarquía según se haya determinado y las mantiene ordenadas y listas para ser presentadas al motor de dibujo.

Motor de Dibujo.

Acá se coordina todo dejando los espacios necesarios entre cada capa (que se superpone y que se puede ver y que se oculta) además de estar pendiente de las posibles modificaciones a futuro producidas por el JavaScript.

Motor “Compositor”.

Recibe y abre en procesos paralelos cada página web que visualize el usuario, ya sea en una pestaña o una ventana nueva y si esto falla por alguna razón pues entonces vuelve a abrir otro proceso solicitando de nuevo al motor de dibujo que se mantiene incólume corriendo en un proceso aparte.

Motor de JavaScript.

Acá se establecen los eventos que disparará el usuario y que podrá modificar tanto como el HTML, el CSS o ambos al mismo tiempo (la mayoría de las veces el proceso no es tan “traumático”, podría ser simplemente mostrar un texto distinto lo cual es algo más sencillo de realizar por parte del sistema operativo que por la maquinaría de Firefox en sí).

Conclusiones.

Fuentes consultadas:

En idioma inglés:

En idioma italiano: