GNU Linux Turnkey 14.

Download PDF

GNU Linux Turnkey 14.

GNU Linux Turnkey LAPP 14 es una distribución pensada para instalar-y-usar con un buen conjunto de aplicaciones (LAPP abreviatura de Linux, Apache, Postgresql y PHP) sin descuidar la seguridad (instala claves SSH inmediatamente –algo que deberíamos hacer nosotros mismos-) y un conjunto de valores predefinidos que agilizan nuestro trabajo al montar servidores para la producción, todo esto con las características intrínsecas del Software Libre. CUENTA ADEMÁS (servicio que hay que pagar, eso sí) con DNS y respaldos «en la nube» ya que de algo tienen -tenemos- que vivir los programadores.


Yo sigo la cuenta Twitter del sr. S. Vaughan-Nichols quien siempre tiene interesantes reportajes (y abundantes críticas) sobre el mundo de la informática, muy especialmente en los temas de servidores y lo que está de moda ahora: «la nuuuuuuube» (imaginen tamborileo en paralelo). Él siempre alega la SIMPLICIDAD (muchos lo llamamos «K.I.S.S. principle«) y no sólo critica por criticar sino que ÉL TAMBIÉN APORTA SOLUCIONES.

Es por tanto que me llamó poderosamente la atención el siguiente «trino (tweet)»:

Sigo el enlace, leo el artículo, sigo el otro enlace hacia los creadores de la distribución TURNKEY, noto que en cada artículo colocan el enlace para descargar la imagen ISO con la «distro» más la aplicación deseada -amd64, por supuesto, estamos hablando de servidores-, todo muy bien explicado y detallado (en idioma inglés) y en 5 minutos la descargo y en 2 minutos más la ejecuto en un ambiente VirtualBox y listo, tengo corriendo un servidor LAPP en modo live CD y casi listo para producción. ¿NO ME CREEN? Veánlo «con sus propios ojos»:

La genial idea de los programadores de Turnkey estriba en adaptar una distribución Linux para que, siguiendo los preceptos de la licencia GNU, sea libre y sin embargo si uno desea seguir adelante con un servidor DNS y respaldo de datos en los servidores Turnkey de manera paga y con una genial API KEY en poco tiempo estemos en línea y produciendo dinero.

Esas cosas las admiro profudamente: simplicidad, apoyo inicial y si quieres CRECER allí están para convertirse en socios de manera instantánea. Además  observo que Turnkey no trabaja sola, también vende servicios Amazon para alojamiento, si es que uno no tiene máquina propia para montar lo requerido.


Instalación de Turnkey.

En otras publicaciones he descrito cómo instalar un servidor PostgreSQL y cómo administrarlo con phpPgAdmin paso a paso. Siempre es bueno saber hacerlo todo uno mismo y luego que uno ya haya aprendido no está mal que obtener ayuda extra como la concebida en esta maravillosa distribución Linux Turnkey. A pesar que en los enlaces anteriores describo en detalle el entorno que utilizo, describo un resumen: uso VirtualBox en Ubuntu 64 bits, le asigné 512 megabytes en RAM, 1 CPU, 12 megabytes para vídeo y la única tarjeta de red virtual la configuro como «puente» para que la máquina virtual Turnkey se comunique con mi enrutador inalambrico (y de allí a la internet) quien se encarga del trabajo DHCP y le asigna la dirección 192.168.1.131 con los Norton DNS.

La instalación en sí la vieron arriba en el video que subí -alojamiento cortesía de Youtube- y el detalle adicional es que RECUERDEN BIEN que la distribución del teclado es en inglés [yo hace años que dejé de usarlos, ni siquiera en español tengo ya, sólo distribución Latinoamericano, ojito al meter las contraseñas 😉 ]


Primera vista a Turnkey.

Para el sr. S. Vaughan-Nichols, quien lleva años trabajando con PhpMyAdmin, probó el Adminer y le resultó agradable; en mi caso veo una sencilla interfaz que va directo al grano y sin complicación alguna: yo la recomendaría para aprendizaje previo al PhpMyAdmin y/o PhpPgAdmin.

La primera diferencia que hallo es que para poderme conectar por el explorador de internet (en mi caso Mozilla) debo utilizar el prefijo https. Como les comenté, la seguridad no ha sido descuidadada en esta distribución, ya que genera sus propias claves al instalar la distro Turnkey (en nuestro caso «correr» live CD). Si quieren conocer al detalle los de las claves SSH y su administración recomiendo leer el siguiente post del Maestro Twitter @Phenobarbital Sr. Jesús Lara.

Como dichas claves SSH no están avaladas por un tercero de confianza el navegador hace la debida advertencia de seguridad a la cual le estableceremos unas indicaciones para nuestras pruebas en el servidor virtual Turnkey (si adquirimos una llave API tipo TKLBAM con Turnkey NADA de lo siguiente que explico haría falta hacer).

Turnkey 01
Conectando por primera vez para administrar Turnkey en una máquina VirtualBox.

Como ven el en gráfico anterior haremos click en «comprendo los riesgos» y luego «agregar excepción». Esto sólo lo haremos con nuestras máquinas que corren en nuestra propia red de área local, jamás ni nunca lo haremos con otros sitios web en internet (sigamos los consejos de seguridad de SUSCERTE).

Turnkey 02
NO agregaremos como permanente la excepción de seguridad.

NO agregaremos como permanente la excepción de seguridad ya que sólo hacemos esto con propósitos didácticos, recuerden que corremos el servidor en RAM -live CD- y cada vez que lo reiniciemos imagino genera nuevas claves SSH así que no embasuremos nuestro querido navegador web ADEMÁS que si hacemos pruebas con otras máquinas virtuales y el enrutador les asigna la misma dirección IP local nos saldrán otros mensajes de advertencia de seguridad, OSEA no nos embaserumos nosotros mismos a la hora de aprender a programar.

Turnkey 03
Portada principal para administrar Turnkey.

Lo primero que vamos a ver es el Adminer LAS FLECHAS ROJAS en las imágenes son de mi autoría para guiarnos paso a paso, hacemos click a donde ellas apuntan.

Turnkey 04
Usando Adminer,
login «posgres».

El usuario -o «login»- es la palabra «posgres» y la contraseña la que hallamos colocado al instalar -o correr- el Turnkey.

Turnkey 05
Administrando PostgreSQL con Adminer.

En fin, hagan uso de su albedrío y creen bases de datos, agreguen tablas y/o índices, clonen, jueguen y aprendan. Recuerden que como estamos ejecutando un live CD al reiniciar la máquina se perderán todos los datos. Mi imaginación vuela en este caso: si adquirimos una API key que nos permita respaldar con los servidores de Turnkey y una vez hecho eso, apagamos y pudieramos levantar otro servidor virtual en cualquier otro sitio restaurando los datos desde Turnkey, aunque imagino que eso tendrá su costo adicional, respaldar y restaurar con frecuencia. No soy el único en Venezuela que conoce TurNkey ya hay varios usuarios «corriéndolo» en Venezuela: Maracaibo, Barquisimeto, Araure [ ¿? ], Valencia, Puerto Cabello, Maracay, Cumaná y, ¡cómo no!, Caracas.

Turnkey 10
Servidores (al día de hoy 27sep2015) corriendo Turnkey en Venezuela.

Mi imaginación va mucho más allá: la manera como programaron a Turnkey se puede prestar para montar servidores maliciosos. El pequeño detalle es que deben pagarle a Turnkey con una tarjeta de crédito cuyo dueño es localizable por los bancos de manera rápida y si usan una tarjeta robada o extraviada igual es delito federal en los EE.UU. así que esa opción, como ven, queda descartada.


Administrando a Turnkey.

Turnkey 00
Pantalla de bienvenida a Turnkey.

En esta pantalla de bievenida que veremos por cónsola nos muestra un resúmen sobre cómo conectarnos vía remota y ya analizamos como entrar en el apartado anterior. Hago hincapié en la publicidad: si adquirimos una API key TKLBAM la debemos introducir en el cuadro de diálogo anterior y esperar que se realicen las actualizacions y/o instalaciones para montar BIEN EN SERIO UN SERVIDOR PARA PRODUCIR DINERO. Ese tema, por ahora ni lo tocaremos ni lo revisaremos.

Turnkey corriendo en VirtualBox.
Turnkey corriendo en VirtualBox.

Lo que si que vamos a hacer es echar un ojo a las opciones para administrar nuestro futuro servidor:

Turnkey 03
Portada principal para administrar Turnkey.

¿Recuerdan la portada principal? PUES ESTA VEZ HACEMOS CLICK EN EL ÍCONO QUE DICE WEBMIN, olvídense por un momento de la flecha roja [qué pichirre soy con el alojamiento web, NO voy a subir otra imagen nada más que para apuntar con otra flecha roja ja ja ja 😉 ]

Turnkey 06
Entrando a Webmin como usuario «root».

Usaremos las credenciales de usuario raíz -«root»- y si éste fuera un servidor para producción lo primero que haríamos es crear los usuarios correspondientes y no volver a tocar la dichosa cuenta. Acá como estamos aprendiendo y jugando pues no haremos nada de eso. La contraseña pues, halá, la que introdujimos al instalar -o correr-:

Turnkey 07
Menú principal Webmin.

Sinceramente quedé abrumado por la cantidad de opciones del Webmin lo único que se me ocurre para describirles la aplicación es que es como si estuvieramos sentados en la cónsola del servidor, pero con una interfaz gráfica de la cual carece -excepto de esta manera remota-. Podemos agregar los usuarios que les dije, reiniciar o apagar el equipo (partimos de que estamos conectados por https o SSH y bien seguros), instalar o quitar aplicaciones, configurar la red (ojito con desconectarnos nosotros mismos) y cualquier otra cantidad de cosas. Incluso para nuestro aprendizaje (nunca para un servidor en producción) podemos instalar «Google Gears» -un proyecto que aunque abandonado desde marzo de 2011 seguirá existiendo por SVN – e incluso lo podemos exportar y mantenerlo en nuestro propio espacio GitHub (nada malo ha pasado con el alojamiento de proyectos de código abierto ofrecidos por este gigante, sólamente reconocen que GitHub es mucho mejor e incluso ellos se mudaron también; YO DIGO QUE ES OTRA VICTORIA PARA LINUS TORVALDS Y RICHARD STALLMAN, un proyecto abandonado de software libre puede ser mantenido perfectamente por otros que aún lo consideren importante):

Turnkey + Webmin + Google Gears
Turnkey + Webmin + Google Gears.

Como son muchas las opciones que tiene el Webmin sólamente les mostraré las capturas de pantallas de las opciones del menú:

Webmin opción principal
Webmin opción principal
Webmin opción "system".
Webmin opción «system».
Webmin opción "servers".
Webmin opción «servers».
Webmin opción "tools".
Webmin opción «tools».

 

Webmin opción "networking".
Webmin opción «networking».
Webmin opción "hardware".
Webmin opción «hardware».

Apagado de Turnkey virtual.

Espero hayan disfrutado de este post tanto como yo, hoy aprendimos algo nuevo y sólo queda apagar la máquina virtual por (faltaba más faltaba menos) por medio de Webmin:

Apagado de servidores remotos por Webmin.
Apagado de servidores remotos por Webmin.

 

<Eso es todo, ¡por ahora!>.

Download PDF

Cambiar refresco de pantalla en Debian.

Download PDF

Con el paso de los años mi visión se ha debilitado. Por eso decidí desempolvar mi viejo monitor Samsung LCD 740n que tiene una estupenda tasa de refrescamiento vertical de 75 Hertz, es decir, «dibuja» el monitor 75 veces por segundo lo cual hace más placentero ver un monitor durante horas y horas todos los días. Yo sabía que por defecto viene fijado en 60 Hertz aunque no sabía el por qué, investigando un poco encontré este artículo donde dan una explicación histórica, dos grandes verdades que en mi mente no las había unificado hasta ahora. Las razones del por qué cansa menos la vista mientras mayor sea la tasa de refrescamiento por segundo siempre lo he tenido presente pero en este otro artículo está pero que muy bien explicado.

Finalizado el preámbulo vamos al grano, cambiar el refresco de pantalla (y resolución) en Debian (e incluso otras distribuciones Linux pero aún no lo he probado ya que las máquinas virtuales con las que practico pues… ¡usan el mismo monitor todas!). Esto quiere decir que este tema es con HARDWARE REAL pero primero he de hacerles una advertencia, no vayan a decir que no se los advertí:

Establecer una tasa de refrescamiento a un monitor para la que NO ESTÁ DISEÑADO, PUEDE DAÑAR SU MONITOR.

De hecho lo dañará si aún tiene un monitor de rayos catódicos (CRT, del inglés Cathode Ray Tube), en el caso de los monitores LCD y LED pues simplemente se niegan a trabajar y como no confirmamos al sistema operativo el ajuste, pasado cierto tiempo lo devolverá a su estado anterior. Si dudan de mi palabra lean la advertencia de Microsoft y otros foros importantes sobre tarjetas de video.

Actualmente esto no es problema para los monitores «en tercera dimensión 3D» ya que refrescan mínimo a 120 Hertz (60 para cada ojo) y así se produce la ilusión de profundidad, con dos imágenes tomadas desde dos puntos separados por cierta distancia, tal como vería nuestros ojos humanos (suena sencillo ¿verdad?).

Download PDF

Gaceta Oficial Extraordinaria N° 6.181: aumento sueldo 20+10% 1° mayo 2015.

Download PDF

Son 2 hojitas en formato pdf  (agradezco a “pdfsam” y lo recomiendo para dividir y combinar documentos en ese formato); con este aumento el sueldo mínimo en Venezuela se ubica en Bs. 7.421,68 (si tomamos como referencia el SIMADI serían aproximadamente US$ 37 mensuales).

Para descargar dicho ejemplar electrónico de la Gaceta Oficial desde nuestra página web haga click aquí.

Si desea descargarla desde el Tribunal Supremo de Justicia.

<Eso es todo, por ahora>.

Download PDF

Curso básico de HTML 5.

Download PDF

Ya usted, ellos, ellas y yo lo sé: hay infinidad de tutoriales en internet sobre HTML: sería «llover sobre mojado» volver a tratar el tema, pero ¿quién dijo miedo? 😉

En mi caso, el que me ocupa, es actualizarme al HTML 5 y enfrentar a dos viejos «demonios» en esto de la creación de páginas web. Y no, no me refiero a los servicios en GNU/Linux a los cuales llamamos «D.A.E.MON» si no a los dos grandes problemas que debemos enfrentar antes de comenzar a escribir una sola línea de código en HTML:

  1. La multitud de navegadores web existentes y el legado que traemos a rastras, ya que muchas personas se niegan a actualizar sus programas. Agreguemos a eso las particularidades de los nuevos celulares con Android y ni mencionemos los celulares con WAP (y por ende WML) que aún están en uso con sus micronavegadores.
  2. Los gustos de nosotros los seres humanos en cuanto a diseño, colores y funcionalidad de las páginas web (en otra entrada presentaré las hojas de estilo en cascada con las cuales enfrentaremos este aspecto).

Y para no abrumarlos ni abrumarlas más comienzo de una vez el tema.

Seguir leyendo

Download PDF
CAPTCHA con PHP.

Un CAPTCHA fácil y sencillo de implementar.

Download PDF

CAPTCHA

Introducción:

Siempre me ha llamado la atención los CAPTCHACompletely Automated Public Turing test to tell Computers and Humans Apart«) que hay en muchas páginas web y que permiten diferenciar consultas hechas por humanos de las hechas por «arañas» que pululan por internet (son también conocidas como «robots»). La diferencia esencial en este caso con respecto a la prueba de Turing es que se trata de convencer a una máquina que es un humano, osea el inverso de la prueba.

En el idioma inglés existe la filosofía K.I.S.S. y la practico frecuentemente ya que los sistemas complejos tienden al caos de manera natural. Es por ello que buscando por internet (precisamente ayudado por las «arañas» que pretendo combatir, ¡qué ironía!) he encontrado el siguiente artículo que me deslumbró por su simplicidad más al cabo de una hora de estudio observo los elementos implícitos sin los cuales NO funciona. Recomiendo vayan y lean dicho artículo y regresen cuando lo hayan asimilado, yo por aquí les espero. 😎


El artículo data del año 2007 pero considero que no ha perdido vigencia alguna, si administran una página web bancaria o son partidarios del último grito de la moda, recomiendo desistan de seguir leyendo esto. 😉

Pues bien manos a la obra.

Requisitos previos.

Utilizo una máquina virtual con Debian Wheezy con la cual estudio el programa para base de datos PostgreSQL a la cual le he instalado también un servidor Apache con PHP: este tipo de configuración es llamado LAMP por sus siglas en inglés, sólo que en aquí en realidad es un LAPP: Linux, Apache, PostgreSQL y PHP. Hay muchísimos tutoriales para instalar este tipo de servidores por ello partimos de la base que ustedes cuentan con uno en funcionamiento y para pruebas (no utilicen un servidor «en producción» hasta tanto no estén completamente seguros de este código). Importante recalcar que no utilizaremos funciones de bases de datos en esta entrada, pero muy frecuentemente las CAPTCHA se utilizan en este tipo de ambiente, por ejemplo, registrar usuarios en una lista de correo electrónico (tremenda tentación para los «robots spam»), así que allí encaja perfectamente.

Configuración adicional.

Al servidor LAPP anteriormente descrito debemos instalarle unas librerías para el trabajo gráfico bajo el lenguaje PHP. Aquí está muy bien descrito a lo que me refiero, haciendo la salvedad que dichas librerías NO SIEMPRE están instaladas por defecto.

En todo caso debemos crear una carpeta bajo la raíz web del servidor Apache con el nombre «captcha» y donde alojaremos el siguiente archivo «info.php»:

<?php
// Archivo "info.php":
// Muestra toda la información, por defecto INFO_ALL
phpinfo();
?> 
y luego iremos a nuestro navegador web preferido a la dirección IP que le hayamos asignado en nuestra red de área local. En mi caso dicha dirección es 192.168.1.27 en la carpeta «captcha»:
 
captcha01En dicha página debemos buscar si están instalados los siguientes valores:
 
captcha02Dado el caso que no se encuentren instaladas dichas librerías debemos recurrir a la línea de comandos y escribir lo siguiente:
 
sudo apt-get install php5-gd
y verán algo más o menos parecido a esto (en mi caso no necesité el comando «sudo» porque ya había ganado acceso como root con el comando «su»):
 
captcha_003
Dichas librerías son necesarias para el trabajo con imágenes jpg, png y gif, entre otros formatos y funciones.
 

Imagen de fondo para el CAPTCHA:

Necesitaremos un imagen tipo gif con unas dimensiones de 100×30 píxeles con colores adecuados teniendo en cuenta que las letras serán negras buscaremos colores como azul o verde o el que gusten pero no de color negro. Yo elegí la siguiente imagen (aunque al final agregaremos varios elementos para dificutarles la tarea de lectura a los «robots» con técnicas OCR ): bgcaptcha.gifComo ven es una imagen con degradado que busca confundir al OCR pero con legibilidad al ser humano; no obstante usar este mismo fondo siempre y con la ayuda de la «fuerza bruta» se puede descifrar al poco tiempo -pero de eso nos encargaremos luego, de «complicarlo» para tratar de eludir la lectura-. La imagen la guardaremos en la carpeta de trabajo en el servidor web bajo el nombre «bgcaptcha.gif» (nemotécnico ‘BackGroundCaptcha.gif’=’bgcaptcha.gif’).

Para bajar archivos por líneas de comando

recomiendo usar «wget», por ejemplo:

«wget    http://www.e.com/imagen_a_bajar.gif      nombre_imagen.gif»

Creación del archivo «captcha.php».

Dicho archivo se encargará de tomar la imagen anterior y, aleatoriamente, «escribirle» letras encimas, almacenarlas en una variable (que leeremos con luego con el método POST) y mostrarla al navegador; para ello utilizaremos el siguiente código que explicaremos línea por línea:

<?php
  //Archivo 'captcha.php'
  session_start();
  $_SESSION['tmptxt'] = randomText(7);
  $captcha = imagecreatefromgif("bgcaptcha.gif");
  $colText = imagecolorallocate($captcha, 0, 0, 0);
  imagestring($captcha, 5, 16, 7, $_SESSION['tmptxt'], $colText);
  header("Content-type: image/gif");
  imagegif($captcha);
  imagedestroy($captcha);
?>
  • Para que el servidor sepa dónde comienza y dónde termina el lenguaje PHP debemos encerrarlo todo con los siguientes comandos: «<?php (…) ?>» y donde van los paréntesis y puntos suspensivos ubicaremos nuestro código a ejecutar. Todo lo que esté fuera de estos demarcadores será considerado lenguaje HTML e interpretado como tal.
  • Cada final de sentencia le será indicado al servidor con un punto y coma «;».
  • Los comentarios, que son importantísimos para nosotros los seres humanos, para las máquinas carecen de importancia y se identifican con «//» y la derecha el texto explicativo.
  • La función «session_start()» permite crear o recuperar un identificador único que servirá para que el servidor pueda atender varios clientes al mismo tiempo sin confundir las respuestas de cada usuario. No debemos preocuparnos mucho ya que todo es automatizado, si acaso dedicaremos una sentencia «if-then-else» por si acaso devuelve el valor «falso», es decir, no se pudo iniciar sesión (todo el mundo da por sentado que devuelve «verdadero»). Importante, muy importante, el comprender sobre el cómo PHP compara dos variables y/o valores para devolver «verdadero» o «falso», merece su estudio de 10 minutos.
  • La función «$_SESSION[]» permite asignar un valor a una variable en la sesión iniciada en el punto anterior y es un variable de arreglo global. El texto, que será aleatorio, lo proporcionará la función «randomText()» que escribiremos luego.
  • La función «imagecreatefromgif()» nos permitirá «cargar en memoria» la imagen que destinamos como fondo del CAPTCHA y devolverá un «identificador de imagen» representado en una variable que usaremos para agregar el texto que identificará e introducirá el usuario, ser humano. De nuevo digo que deberíamos destinar un «if-then-else» dado el caso la función devuelva «falso».
  • El comando anterior nos permitió establecer el «lienzo» donde vamos a escribir las letras aleatorias; pues el comando «imagecolorallocate()» nos permite fijar el color con que las «pintaremos»: «0, 0, 0» corresponde al color negro en la codificación de valores «RGB», «Red Green Blue» y cuyos valores van del 0 al 255 cada uno y nos permite usar +16 millones de colores. Luego echaremos mano de esta función para confundir aún más a los «robots», por ahora nos conformaremos con el color negro. Es de hacer notar que para esta función CERO es «falso» y cualquier otro valor es «verdadero», si usted considera esto una tontería le invito a leer la disertación sobre el tema, está avisado o avisada.
  • La funcíon «imagestring()» dibuja una cadena de texto en nuestro «lienzo», la imagen gif seleccionada. Los parámetros de esta función son: (image, font, x, y, text, color)  y los detallo a continuación:
    1. image: la que cargamos en memoria con la función imagecreatefromgif() y que llamamos $captcha.
    2. font: numeradas del 1 al 5 y es la fuente nativa predeterminada en la librería GD e incluso nos permite cargar nuestras propias fuentes pero debemos cargarlas y compilarlas de acuerdo a la arquitectura de nuestro servidor. Si se entusiasman a realizar esto último deberán cargar dicha fuente «compilada» con la función imageloadfont() de acuerdo a unos valores binarios. Más interesante hallo utilizar la función imagettftext() NO SIN ANTES VERIFICAR el phpinfo() devuelva que el ambiente del servidor lo soporte (si quieren saber más sobre fuentes True Type en GD visiten este enlace): captcha_004
    3. Coordenadas X e Y: tomadas a partir de la esquina superior izquierda, pónganse de cabeza para que las entiendan (ahhh me recuerdo de la materia Geometría Analítica, ¡qué belleza para Autocad! ¡Y dibujábamos por comandos escritos en papel fuera del laboratorio de computación!).
    4. text: en este caso lo que ya tenemos almacenado en la variable global de sesión «$_SESSION[‘tmptxt’]».
    5. color: el que establecimos a negro con la función «imagecolorallocate()».
  • La función «header()» permite que nuestro servidor se ciña a las normas del lenguaje HTML que consiste en «notificarle» al navegador web (en formato NO html) que le será enviado un flujo de datos, por defecto «application/octet-stream», pero que nosotros utilizaremos para indicarle que es una imagen gif «Content-type: image/gif». Si desean conocer más acerca del nacimiento de la web y sus normas de funcionamiento de la mano del mismísimo Tim Berners-Lee hagan click en este enlace.
  • Por último la función «imagegif()»  instruye a nuestro servidor que le envie la imagen al navegador del usuario, el CAPTCHA que queremos interprete el ser humano.
  • Una función que considero importante y que yo agrego al código mostrado originalmente -y del que desconozco la autoría- es «imagedestroy()» a fin de liberar la memoria utilizada por la variable «$captcha». Aunque toda la memoria se libera cuando el usuario cierra su navegador o cuando nosotros mismos invocamos «session_destroy()» nunca está demás liberar «trabajo» apenas sea posible.

Creación de la función «randomText()».

Ahora explicaré la función que devuelve una cadena de texto de manera aleatoria pero con dos mejoras al código fuente original, el cual es el siguiente:

function randomText($length) {
  $pattern = "23456789abcdefghijkmnpqrstuvwxyz";
  for($i=0;$i<$length;$i++) {
    $key .= $pattern{mt_rand(0,32)};
  }
  return $key;
}
  • Las funciones en PHP se declaran con la palabra clave reservada «function» y los argumentos se pasan entre paréntesis separados por comas.
  • Todo el cuerpo de la función esta demarcado por inicio y fin de corchetes «{ … }».
  • La función toma como parámetro la variable «$lenght» la cual toma el valor de «7» al hacer el llamado de la siguiente manera: «randomText(7)». Por ende nuestro CAPTCHA tendrá 7 caracteres, recuerden que estamos limitados al espacio del «bgcaptcha.gif».
  • En la primera variable «$pattern» establecemos los caracteres que queremos mostrar al usuario, no repetidos, y aquí va la primera mejora que les dije antes: NO incluyo el número uno («1»), ni la letra ele («l») ni tampoco el número cero («0») ni la letra o («O») porque se trata de ponersela difícil al «robot», no al ser humano, quien puede confundir dichos signos.
  • Utilizamos un ciclo «for» similar al usado en lenguaje C, es decir, un valor de inicio, una condición que se evalúa en cada ciclo y un incremento en cada ciclo. Así establecemos que al escribir «for ( $i=0; $i<$length; $i++ ) {…}» estamos ordenando ejecutar un ciclo basado en la variable «$i» que comienza desde cero y que mientras sea menor que la longitud de caracteres de nuestro CAPTCHA se incremente en una unidad para cada ciclo, «$i++».
  • Dentro de los corchetes del ciclo «for» anterior colocamos la variable «$key» que se autoconcatena en cada rizo «.=» con una letra aleatoria del patrón elegido y que llevamos asignado en la variable $pattern.
  • En el lenguaje PHP (e igualmente en Python) cada cadena de caracteres es considerada de manera implícita una matriz de una sola fila, esto nos permite «imprimir» en el navegador del usuario una letra del patrón, por ejemplo «echo $pattern{10}» devolverá «b».
  • ¿Cómo escogemos una letra cualquiera del patrón? Aquí es donde viene la segunda mejora que les comenté: en vez de usar la función «rand()» utilizamos la función «mt_rand()» la cual, aparte de ser más rápida nos permite utilizar números más grandes (de ser necesario). Dicha mejora la propone un usuario llamado «caos30» en los comentarios de la entrada del blog en la cual se inspira este tema. Esta función tiene dos argumentos que nos permiten acotar el número devuelto: para este caso es (0, 32) que es precisamente el largo del patrón que escogimos (el abecedario inglés 26 caracteres más los diez dígitos numéricos son 36 menos 4 que eliminé para evitar confusiones a los humanos).
  • Es necesario el comando «return» acompañado de la variable que debe devolver la función, en nuestro caso es un tipo «cadena de texto».

Guardado del archivo «captcha.php».

Ya suficientemente explicado línea por línea el código unimos ambos algoritmos y con el editor de texto nano (o el que ustedes prefieran) guardamos en la carpeta «captcha» que hicimos en «\var\www» (donde generalmente Apache guarda el sitio web):

<?php
  //Archivo 'captcha.php'
  function randomText($length) {
    $pattern = "23456789abcdefghijkmnpqrstuvwxyz";
    for($i=0;$i<$length;$i++) {
      $key .= $pattern{mt_rand(0,32)};
    }
    return $key;
  }
  session_start();
  $_SESSION['tmptxt'] = randomText(7);
  $captcha = imagecreatefromgif("bgcaptcha.gif");
  $colText = imagecolorallocate($captcha, 0, 0, 0);
  imagestring($captcha, 5, 16, 7, $_SESSION['tmptxt'], $colText);
  header("Content-type: image/gif");
  imagegif($captcha);
  imagedestroy($captcha);
?>

Antes de continuar nos aseguramos que la CAPTCHA se ejecute y muestre correctamente en nuestro navegador conectado a nuestro servidor LAPP de pruebas:

captcha_005

Cada vez que pulsamos CTRL+F5 nos mostrará una CAPTCHA diferente cada vez y asigna a la variable «$_SESSION[‘tmptxt’]» el valor deberá comparar con el valor introducido por el usuario humano. El siguiente paso es hacer la interfaz para la presentación e introducción de los datos.

Formulario web «captchademo.php».

El uso básico de sesiones bajo PHP está explicado en detalle en este enlace. No obstante buscando la simplicidad para la comprensión de todos ustedes, amables y pacientes lectores, haremos un archivo php para mostrar la CAPTCHA e introducir la respuesta del usuario y otro archivo php donde compararemos la respuesta; a este archivo lo llamaremos «captchaanswer.php» y esta explicado más adelante.

Sin más pretensiones de seguridad ni estética escribiremos el siguiente código:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>CAPTCHA con PHP</title>
<meta name="description" content="CAPTCHA con PHP: ejemplo para demostrar la creacion de Captcha con PHP." />
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
 <tr>
   <td align="center">
     <strong>CAPTCHA con PHP </strong><br>
     Ingresar el texto mostrado en la imagen: <br>
     <form action="captchaanswer.php" method="post">
       <img src="captcha.php" width="100" height="30" vspace="3"><br>
       <input name="tmptxt" type="text" size="30"><br>
       <input name="btget" type="submit" class="boton" value="Enviar">
       <input name="action" type="hidden" value="checkdata">
     </form>
   </td>
 </tr>
</table>
</body>
</html>

Al navegar nuestro servidor de prueba podrán ver algo parecido a esto:

captcha_006Todo el código anterior es puro lenguaje HTML y mencionaré brevemente línea por línea y su cierre correspondiente (nota: los términos que usaré para describir lo que sucede probablemente hiera la sensibilidad académica de algún lector, no obstante recuerdenme y escríbanme si estoy equivocado) :

  • Etiquetas «<html>…</html>»: le indica a nuestro servidor dónde comienza y dónde termina el lenguaje HTML, veremos en una entrada futura que esto es esencialmente útil en nuestros «scripts php».
  • Etiquetas «<head>…</head>»: contiene información prioritaria que nuestro servidor tendrá que darle tratamiento especial, leer próximo punto.
  • Etiquetas «<meta (…) />»: estas etiquetas contienen datos que describen datos y están categorizados. La categoría «Content-Type» la describimos anteriormente pero en esta ocasión la usaremos para decirle al navegador del cliente que la vamos a enviar lenguaje HTML y que lo interprete como tal. Envuelve mayor complejidad una solicitud HTTP pues incluye códigos numéricos de respuesta y aceptación pero con saber que esta información es una de las primeras que se envían es más que suficiente.
  • También en los metadatos podemos incluir la codificación de caracteres utilizados en la página web (algún día cuando usemos todo en 128 bits esto caerá en desuso) por medio del comando «UTF-8».
  • Hay ciertas palabras claves reservadas en los metadatos y es lenguaje de alto nivel, el que usamos usted y yo, seres humanos. Uno de ellos es la palabra name=»description» que nos permite especificar a manera general el propósito principal de la página.
  • En este punto es útil preguntarnos ¿para qué es todo esto del encabezado? Para ello debemos recordar que hace 20 años el ancho de banda en internet era «oro en polvo» y el protocolo se diseñó para no cargar la página completa de un solo golpe sino que echaramos «un ojo» antes de descargar completo. Hoy en día se ha vuelto obsoleto (yo escucho una radio por internet, mientras corro una máquina virtual que actualiza su software desde varios repositorios y otra máquina virtual «baja» parches de seguridad mientras escribo estas líneas ‘en línea’ y además de tanto en tanto superviso servidores de datos remotos; el tráfico de datos es asombroso) pero aún sigue siendo útil para las «arañas» o buscadores como https://duckduckgo.com/  a fin de categorizar las páginas web visitadas y de las cuales hasta guardan una copia espejo, datos, datos y más datos; discos duros a reventar (alguien dijo alguna vez «lo que se sube a internet allí se queda», yo lo creo fehacientemente 😯 ).
  • Con las etiquetas «<title>…</title>», valga la redundancia, titulamos nuestra página (el «caption» de la ventana) y algunos navegadores agregan su propio nombre como pueden ver el ejemplo mostrado.
  • Dentro de las etiquetas «<body>…</body>» insertaremos la página web en sí, sólo que en este caso es un formulario para mostrar e introducir los datos.
  • Con «<table><tr><td>…</td></tr></table>» dibujaremos una tabla de un solo cuadro ayudados por el concepto de anidación de etiquetas ¿recuerdan el método de la «doble C» para dividir fracciones? Pues bueno es algo parecido a eso.
  • Con «<strong>…</strong>» podremos poner en negritas lo escrito entre las etiquetas.
  • Con «<br>» le decimos al navegador que termina una línea y comience una nueva.
  • He aquí lo más importante: «<form>…</form>». Allí declaramos y establecemos los elementos del formulario en sí.
  • Con form <form action=»captchaanswer.php» method=»POST»> indicamos que las variables siguientes sean pasadas a otro «script php» con el método «POST» para que el usuario no visualize las variables(a diferencia del método «GET»).
  • He aquí la «magia»: al pasar la orden de visualizar la imagen CAPTCHA realmente le indicamos es que ejecute el «script»: <img src=»captcha.php» width=»100″ height=»30″ vspace=»3″> y que lo muestre como tal (con ayuda de «header()»).
  • Los demás elementos son para dibujar el cuadro de texto y el botón enviar, creo no merecen mayor explicación.
  • Las normas estéticas las agregaremos en una próxima entrada pero de manera normalizada, como el tema es largo y quiero escribirlo desde hace tiempo le dedicaré una entrada aparte.

Actualizado el lunes 22 de febrero de 2016.

Para prevenir que los servidores proxy instalados en redes de área local NO guarden en caché la imagen de nuestro CAPTCHA podemos hacer uso de generar diferentes nombres al «archivo» de imagen misma con, por ejemplo, la función uniquid de la siguiente manera:

<?php
  echo "<img src='";
  echo uniqid("captcha", true);
  echo ".php' width='100' height='30' vspace='3'><br>";
?>

Formulario web «captchaanswer.php»

Como ustedes pueden ver loq ue yo llamo «formularios web» o «páginas web» en este servidor LAPP son en realidad unos «scripts» en lenguaje PHP. El que nos ocupa ahora es el que se invoca cuando el usuario pulsa el botón «Enviar»:

<?php
    session_start();
    if ($_POST['action'] == "checkdata") {
        if ($_SESSION['tmptxt'] == $_POST['tmptxt']) {
            echo "Bienvenido.";
        } else {
            echo "Intentalo nuevamente.";
        }
        exit;
    }
?>

De nuevo lo analizamos línea por línea obviando, por supuesto, las funciones y comandos que de nuevo encontremos y hayamos explicado antes:

  • Es necesario llamar a la función «session_start()», recordemos dicha función también nos permite recuperar los datos de la sesión almacenados en la variable global.
  • La próxima acción es verificar que la variable ‘action’ esté establecida a ‘checkdata’  de no ser así pues simplemente finaliza y sale sin aviso alguno.
  • El punto decisivo es la comparación de la cadena aleatoria creada por el script «captcha.php» y compararla con la enviada por el usuario. De ser iguales emite el mensaje «BIENVENIDO» y aquí es donde podemos ubicar el código que nos interesa: la publicación de un comentario a una entrada de blog, la confirmación a una lista de correos, etc.

Conclusiones.

Esto es sólo un abreboca de lo que podemos realizar con PHP en cuanto a gráficos se refiere, estoy consciente que para las normas actuales es un CAPTCHA bastante débil pero lo podemos mejorar hasta llevarlo a un nivel básico. Para mi caso particular lo voy a implementar de una vez en un «servidor de producción» y que trabaje de una vez.

Lecturas adicionales

En idioma castellano

En idioma inglés

<Eso es todo, por ahora>.

Download PDF
Gaceta 0ficial 40.608 sumario.

Gaceta Oficial N° 40.608: aumento de la Unidad Tributaria a Bs. 150,00.

Download PDF

Son 3 hojitas en formato pdf  (agradezco a “pdfsam” y lo recomiendo para dividir y combinar documentos en ese formato); con este aumento las facturas de compra con monto inferior a 20 U.T. (Bs. 3.000,00) podrán ser ingresadas en «caja chica» sin hacerle retención de IVA (Contribuyentes Especiales); también aumentan automáticamente el Bono Alimentación para los Trabajadores y Trabajadoras, el costo de emisión de los pasaportes, multas y un sinfín de cosas más.

Gaceta 0ficial 40.608 sumario.
Gaceta 0ficial 40.608 sumario.

Para descargar dicho ejemplar electrónico de la Gaceta Oficial desde nuestra página web haga click aquí.

Si desea descargarla desde el Tribunal Supremo de Justicia  deberá luego introducir el número “40608” en el cuadro de búsqueda rápida.

<Eso es todo, por ahora>.

Download PDF

PostgreSQL 9.1: su uso con psql.

Download PDF

Y seguimos aprovechando el receso de Carnaval para continuar nuestro estudio del poderoso motor de base de datos relacional PostgreSQL 9.1.

Nuestra miniserie comienza acá y en la última entrada tocamos el tema de las consultas con uniones las cuales utilizaremos aquí también pero con ayuda del programa psql y tal como lo prometimos vamos a trabajar en profundidad por línea de comandos.

Como recordarán ya habíamos utilizado anteriormente a psql para garantizarle al usuario adminsql acceso íntegro a todas las bases de datos en el servidor PostgreSQL que instalamos.

Breve pausa para hablar sobre seguridad básica.

Normalmente lo que hicimos en el párrafo anterior sólamente se hace si hay un solo usuario y una sola base de datos, un sistema pequeño, tal como era a finales del siglo pasado. Pero ahora con computadoras con procesadores multinúcleo (e incluso hasta computadoras con multiprocesador ) un servidor PostgreSQL puede, tranquilamente, atender muchos usuarios a la vez. Imaginemos que en nuestra Academia de Software Libre de ejemplo cada alumno debe acceder a este recurso único pero debemos de cuidar que cada quien trabaje en su propia base de datos y no toque las ajenas, ya sea por error o a propósito (que se ven casos así). Pues bien PostgreSQL soporta usuarios y grupos internamente, tal como si fuera una computadora con un sistema operativo moderno.

Un usuario pudiera ser cada alumno en clase con su base de datos propia para desarrollar su trabajo y aprobar el curso.

Un grupo, por ejemplo, pudiera ser un sección o curso en determinada aula de clase con derechos de sólo lectura sobre una base de datos perteneciente al instructor de clases y además independiente de otros instructores en otras seccionesde clase; eso nos facilita el trabajo al crear usuarios pues se le asigna al grupo y «hereda» la configuración.

Trabajando con psql.

Lo comentado en la sección anterior lo veremos ahora de forma práctica y de la manera más sencilla posible. En la máquina Debian que corre nuestro PostgresSQL seleccionamos «Aplicaciones->Accesorios->Terminal»:

postgresql_blog01Abrimos así una ventana terminal donde procederemos a ingresar el comando psql pero en esta oportunidad lo haremos acompañado de opciones adicionales:

psql --username=adminsql --password --dbname=GNU_academy

Dichas opciones son:

  • «–username=nombre_de_usuario» permite colocar a continuación el nombre del usuario que se va a conectar; la forma abreviada es «-U nombre_de_usuario» con un espacio entre ambos (y tened en cuenta las mayúsculas y minúsculas, tal cual se escriben).
  • «–password» para que nos pregunte la contraseña («–no-password» será útil en trabajos de procesos por lotes); la forma abreviada es «-W» (notad que las formas largas son con doble guión y las cortas con un solo guión).
  • «–dbname=nombre_de_la_base_de_datos» nos conecta de una vez a donde vamos a trabajar; la forma abreviada es «-d nombre_de_la_base_de_datos» con un espacio entre ambos.

Por ahora ésas son las opciones que utilizaremos por la terminal interactiva pero en realidad psql tiene gran cantidad de agregados los cuales en otras entradas le daremos uso, pero no a todos. Si queréis echar un ojo a la lista completa, pincha aquí.

Una vez hayamos presionado intro y haber tecleado nuestra consabida contraseña al cabo de otro intro nos aparece el siguiente mensaje de error:

psql: FATAL: Peer authentication failed for user «adminsql»

Y no, no es porque hayamos ingresado mal la contraseña, que es harta sencilla sino por el asunto de seguridad que describí hace poco. Para que podamos conectarnos debemos crear un usuario llamado adminsql con su correspondiente contraseña en el sistema operativo Debian (o GNU/Linux que usemos). Esto no sería deseable, ya que los usuarios tendrían acceso al sistema operativo en sí, amén que también si son muchos usuarios recarga inncesariamente el sistema de archivos (que aunque tengamos poderosas computadoras siempre la frugalidad es bienvenida), y no, no necesitamos ése esquema de trabajo.

Es por ello que contamos con la opción peer por defecto, apoyada por el sistema operativo y contamos con la opción md5 que encripta la contraseña para mayor seguridad, así que sólo registraremos usuarios dentro de PostgreSQL. Para ello ganaremos acceso como superusuario y luego usaremos el programa editor de texto nano para editar la configuración. Por favor observen la imagen para que tengan el panorama completo:

postgresql_blog02

nano /etc/postgresql/9.1/main/pg_hba.conf

y buscaremos la sección «is for Unix domain sockets connections only» donde cambiaremos «peer» por «md5» tal como aparece en la siguiente figura:

postgresql_blog03lo siguiente será (recuerden, estamos usando nano) CTRL+X -> «y» -> intro osea guardar y salir en el editor de textos que hayan utilizado ustedes. Una vez hecho esto, necesitamos que el servidor tome la nueva configuración, en realidad el servicio o demonio debemos reiniciarlo, no la máquina en si:

service postgresql restart

y si hicimos bien nuestro trabajo veremos más o menos lo siguiente:

postgresql_blog04De nuevo introducimos el comando descrito para conectarnos a la base de datos pero esta vez si que tenemos éxito en nuestra tarea:

postgresql_blog05Y allí estamos, a la espera de la primera consulta, usaremos entonces la última de la entrada anterior:

SELECT students.name, phone_numbers.number
FROM students
INNER JOIN phone_numbers
ON students.id=phone_numbers.idstudent
WHERE LOWER(students.email) ~ ‘hotmail.com’;

¿Recuerdan la utilidad del punto y coma para indicar el final de la consulta? Acá nos viene como anillo al dedo pues estas terminales son un tanto incómodas al estar generalmente limitadas a 80 columnas, así que presionamos intro y notad que el prompt cambia de «=#» a «-=» para indicarnos que estamos en una sola sentencia a pesar que son varias lineas:

postgresql_blog06¡Y listo! hemos hecho nuestra primera consulta por terminal interactiva, ya sólo queda salir de psql y luego de nuestra terminal para ello bastará con teclear:

/quit

exit

En la próxima entrada seguiremos trabajando por línea de comandos para la creación de tablas e insertado de datos en las mismas y ampliaremos el estudio de consultas por uniones JOIN.

<Eso es todo, por ahora>.

Download PDF
INNER JOIN y LEFT JOIN.

PostgreSQL 9.1: integridad referencial y consultas por uniones.

Download PDF

Esta vez realizaremos unas consultas por uniones no sin antes dar una breve explicación de la integridad referencial, una característica de las bases de datos relacionales, siempre de la manera más sencilla posible.

Para los que el orden es importante esta serie de artículos sobre PostgreSQL 9.1 comienzan acá y la manera de conectarnos al servidor vía phpPgAdmin se describe aquí.

Pues bien, comenzemos ya: tenemos creadas dos tablas llamadas students y phone_numbers y como bien lo describe sus nombres en inglés, sirven para almacenar datos de estudiantes y sus números telefónicos. Como cada persona puede tener varios teléfonos (casa, trabajo, móvil, fax, etc.) y a su vez cada una de esas ubicaciones hoy en día pueden tener varios números diferentes (en mi caso tengo 2 en casa, 3 en el trabajo y uno celular) no tiene sentido crear campos para cada uno de ellos en la tabla students porque no sabemos cuántos va a tener cada inviduo. Cualquiera me puede rebatir diciendo que aunque sea debería suministrar un número de teléfono para alguna emergencia en clase (desde el punto de vista de este ejercicio donde somos una Academia de Software Libre) pero ni con eso contaría yo, es decir, puede darse el caso que no tenga ningún teléfono (hermosa es la película «Enemy of the State» ojalá la disfruten tanto como yo la disfruté en 1999). Es por tanto que en la tabla students no dejamos ningún campo para almacenar el o los que nos suministren y los guardaremos en la tabla phone_numbers teniendo cuidado de guardar de quién es cada cual.

Observemos que al seleccionar la tabla phone_numbers desde phpPgAdmin haciendo click en «constraints» («restricciones») descubriremos el trabajo que hizo Visual Paradigm traduciendo nuestro organigrama a la base de datos:

Postgresql_2015-02-04 09:20:28Como en la entrada anterior agregamos algunos datos de los estudiantes tenemos dicha tabla de ejemplos de la siguiente manera:

Postgresql_2015-02-04 09:22:25De nuevo hacemos click en la tabla phone_numbers e insertamos un registro tal como lo hicimos en la entrada anterior, sólo que en este caso y cuando lleguemos al campo idstudent automáticamente aparecerá una lista de los estudiantes que ya tenemos registrados, en este caso identificados del 1 al 4:

Postgresql_2015-02-04 09:23:06Para probar si la base de datos funciona correctamente en su integridad referencial colocaremos el idstudent = 5 (que aún no está registrado) y le damos click a «insert»:

Postgresql_2015-02-04 09:31:18¡Oh, sorpresa! nos devuelve un mensaje de error y no es para menos ¿para qué querríamos guardar un número de teléfono si no sabemos quién es su propietario? (a menos que trabajeís como detective, hay «caso de casos»).

Desistimos pues en nuestro intento de «embasurar» nuestra base de datos y procedemos a colocarles a los tres números telefónicos que insertemos un idstudent cualquiera entre 1 y 4 y al poco rato tenemos una bonita matrícula lista para clases (aunque falta agregar cursos, aulas, profesores, horarios… «Roma no se construyó en un solo día» reza el refrán, vamos poco a poco).

Una vez hecho esto ya estamos listos para hacer unas consultas entre ambas tablas y con propósitos didácticos ejecutamos la primera consulta (y de manera similar a nuestra entrada anterior):

SELECT students.name, phone_numbers.number

FROM students, phone_numbers

WHERE students.id = phone_numbers.idstudent;

Postgresql_2015-02-04 09:44:09La consulta está en escrita en tres líneas pero la base de datos «sabe» que la misma termina cuando alcanza el punto y coma «;» y dicha manera de escribirla nos proporciona legibilidad para desglosarla y explicarla, línea por línea:

  • La primera línea ordena que seleccione «SELECT» los campos «name» de la tabla «students» (de allí el punto como unión) e igual con «number» que pertenece a la tabla «phone_numbers». Esta sintaxis permite que, por ejemplo, dos campos con el mismo nombre en diferentes tablas sean identificados sin ambigüedad alguna.
  • La segunda línea «FROM» instruye de cuáles tablas sacarán los datos.
  • La tercera línea «WHERE» está el condicional: para cada estudiante que devuelva el o los números telefónico(s) registrado(s) relacionados entre sí por el identificador numérico.

Como sólo insertamos tres números telefónicos pues sólo tres estudiantes con teléfonos será lo que veremos (en este caso para cada estudiante un solo número telefónico que sería el caso más común). ¿Pero y si queremos visualizar TODOS los estudiantes, tengan o no número telefónico registrado?

Uniones o «JOIN»:

En el lenguaje SQL existe el comando JOIN con sus prefijos INNER, LEFT y RIGHT haciendo la salvedad que «JOIN» = «INNER JOIN» y será el primero que veremos para realizar la misma consulta que hicimos con el condicional WHERE:

SELECT students.name, phone_numbers.number

FROM students

INNER JOIN phone_numbers

ON students.id=phone_numbers.idstudent;

Postgresql_2015-02-04 09:44:49

De nuevo desglosamos y analizamos línea por línea (recordad el para qué sirve el punto y coma al final de la consulta):

  • La primera línea solicitamos los campos que nos interesan de ambas tablas, cada uno con su espacio de nombres para evitar confusiones.
  • La segunda línea específicamos la tabla «principal» (esto tendrá sentido más adelante) es decir los estudiantes, ya que ellos son los propietarios de cada número de teléfono.
  • La tercera línea indica hacia cual tabla se hará la unión, osea con cual se combinará.
  • La última linea establece cómo relacionar los datos, en este caso una sola condición posible de relación entre ambas tablas (pudieran haber otras relaciones posibles pero por ahora no complicaremos las cosas).

INNER JOIN
INNER JOIN

Hasta aquí todo bien pero volvamos a la pregunta:

¿Pero y si queremos visualizar TODOS los estudiantes -y su(s) número(s) telefónico(s)-, tengan o no número telefónico registrado?

Es aquí que utilizaremos LEFT JOIN en vez de INNER JOIN, simplemente ese cambio, una sola palabra por otra:

Postgresql_2015-02-04 09:45:02

SELECT students.name, phone_numbers.number

FROM students

LEFT JOIN phone_numbers

ON students.id=phone_numbers.idstudent;

Y AHORA SÍ que observamos que el estudiante Pedro aparece pero en donde va el número telefónico muestra NULL el cual es una palabra que encierra un concepto que en base de datos trae aún hoy en día candentes discusiones pero que en este caso práctico muestra su utilidad: «NO TIENE NÚMERO TELEFÓNICO REGISTRADO Y NO SABEMOS SI REALMENTE LO TIENE YA QUE SIMPLEMENTE O SE NEGÓ A SUMINISTRARLO O EL INSCRIPTOR OLVIDÓ REGISTRARLO». Todo eso encierra el concepto de NULL.


Actualizado el martes 12 de enero de 2016: me hacen la sugerencia que pudieramos colocar un campo lógico (verdadero o falso) para saber a ciencia cierta si la persona posee algún teléfono. No veo mala esa idea pero recomiendo que le coloquen NULL como valor predeterminado pero que sea obligatorio ese dato -y por ende no permitirá guardar con NULL-. A nivel de la interfaz del usuario, el formulario que introduce datos para agregar personas deberá utilizarse un RADIO BUTTON sin valor preseleccionado en ninguno de los dos. Ejemplo:

¿Posee teléfono?
Sí.
No.

LEFT JOIN
LEFT JOIN

Ya cerrando la entrada podemos  acotar la consulta JOIN con un simple WHERE tal como ejercitamos en otra entrada:

SELECT students.name, phone_numbers.number
FROM students
LEFT JOIN phone_numbers
ON students.id=phone_numbers.idstudent
WHERE LOWER(students.email) ~ ‘hotmail.com’;

sólo que esta vez veremos sólamente los estudiantes que posean correo electrónico en «hotmail.com» (hoy día «outlook.com») y que tengan al menos un número telefónico registrado.

En la próxima entrada veremos y estudiaremos cuáles otras opciones existen sobre JOIN, tan importante es que en Wikipedia en castellano tiene su propia entrada completa.

<Eso es todo, por ahora>.

Download PDF

PostgreSQL 9.1: consultas SQL sencillas con phpPgAdmin.

Download PDF

Aprovecho el breve receso de estas fechas carnestolendas de 2015 para continuar con esta miniserie de artículos sobre PostgreSQL 9.1. Para aquellos que quieran llevar la secuencia correcta del tema éste se inicia acá .

La fotografía que veís y que encabeza esta entrada es la del Doctor Donald Chamberlin, investigador de la IBM quien junto al Doctor Raymond Boyce (quien falleció en 1974 y muy poquísimas fotografías dejó) ambos idearon (y nos legaron) el «Structured Query Language» (SQL).

Lo que haremos hoy son unas consultas sencillas en SQL no sin antes haber agregado unos cuantos datos de prueba (cualquier semejanza con personas reales es pura y casual coincidencia).

Utilizando el navegador web predeterminado en Debian, el Iceweasel (que cada día aprecio más por su economía de recursos y por ende rapidez) nos vamos a la consabida dirección IP de nuestro servidor virtual:

Postgresql_2015-02-02 19:52:43

Introducimos el «login» y la contraseña (si no lo recuerdan ir a esta entrada ) y una vez hayamos logrado acceso hacemos click («o vamos») a la tabla students (aunque soy fanático del castellano, debo reconocer que el inglés es hoy en día lo que fue el latín en el mundo entero) y observamos su estructura de datos más sin embargo nos interesa, por ahora, el enlace «insert» para dar algunas altas en la tabla:

Postgresql_2015-02-02 19:53:20

Tras lo cual se nos abre el siguiente cuadro de diálogo el cual procedemos a llenar sin cortapisa:

Postgresql_2015-02-02 19:54:05Observen que dejé el campo «id» intencionalmente en blanco: nuestro primer valor será, naturalmente, el 1 pero en los siguientes registros que insertemos intenten guardar ese valor de nuevo y observarán una de las restricciones de la tabla: los valores no pueden repetirse para ese campo en particular. A la final verán algo parecido a esto, ya con los registros insertados:

Postgresql_2015-02-02 19:54:30 Postgresql_2015-02-02 19:58:16

Vuelvo a repetir: cualquier parecido con los datos personales en la realidad es simple y feliz coincidencia. Ahora que tenemos unos cuantos registros insertados podemos hacer unas consultas sencillas, para ello bastará con hacer click en el enlace «SQL» que está en el borde superior derecho de la web, cerquita de

«SQL | History |Find | Logout»

¿lo vieron? en el cuadro de diálogo que se abre escribimos la siguiente sentencia para visualizar los correos electrónicos de los estudiantes:

select email from students;

Antes que hagan click en «execute» («ejecutar -sentencia-«) observen atentamente que estamos trabajando con la base de datos «GNU_academy» y que nuestro vía de búsqueda de esquema está apuntada a «public» (ésto último permite que al ejecutar una sentencia SQL los nombres de tablas y campos sean buscados y verificados primero antes de comenzar a buscar datos, e incluso es útil para asuntos de seguridad y privilegios pero ese tema es más avanzado; si luego quieren aprender más sobre ello aquí el enlace introductorio al asunto ).

Así pues, sin más, ejecutamos la sentencia tras lo cual veremos algo parecido a esto:

Postgresql_2015-02-02 19:59:41

La explicación breve de la sentencia SQL es traducirla del inglés:

«select»->»selecciona»

«from»->»desde (la tabla)»

«;»-> indica fin de la sentencia, no es obligatorio pero es útil si vamos a introducir varias sentencias que deben ir en un orden específico (por ejemplo insertar más datos de estudiantes y luego mostrarlos en un listado para asistencia -ya le vamos dando utilidad en la vida real a esto de las bases de datos-).

Como hay comandos específicos del lenguaje SQL yo opto (y hay varias personas que lo hacen) por escribir dichos comandos en mayúsculas y los nombres de tablas (y/o variables y/o constantes) en minúsculas y como pueden ver se ejecutan sin ningún problema, el asunto es de legibilidad para nosotros los humanos:

SELECT email FROM students;

Importante: los nombres de campos y tablas han escribirse tal cual fueron creados en la base de datos correspondiente, de no ser así nos devuelve error; es por ello que desde un principio en estos tutoriales los creamos todos en minúsculas -y en inglés, de paso-.

Volviendo al tema de la realidad, supongamos que por cualquier razón necesitamos saber cúales (y cuántos) estudiantes utilizan correo hotmail pues simplemente introducimos la siguiente sentencia SQL

SELECT email FROM students WHERE email ~ ‘hotmail.com’;

Observen el nuevo comando

«WHERE»->»donde (satisfazga la condición)»

y el uso de la virgulilla como comparador lógico indicando que dicha condición tenga la cadena de texto ‘hotmail.com’. Otros detalles a considerar es el uso de las comillas simples y el uso de mayúsculas: si usamos comillas dobles se interpreta como nombre de columna y si usamos mayúsculas NO devuelve los correos electrónicos ya que «hoTMail.com» NO ES IGUAL A «hotmail.com»:

«hoTMail.com» <> «hotmail.com»

Sobre nomenclatura del correo electrónico:

Esto nos plantea desde ya nuevos retos: si vamos a desarrollar una aplicación seria es deber que los usuarios ingresen direcciones de correo válidos (sintaxis usuario@dominio ):

  • El nombre del usuario NO debe llevar espacios a menos que estén precedidos por una barra inversa y entrecomillado.
  • El dominio NUNCA debe llevar espacios (ni arrobas, claro está).
  • No pueden haber espacios antes o después de una dirección válida.
  • No pueden llevar dobles puntos «..», así estén entrecomillados.
  • El nombre del usuario no pueden contener dobles arrobas a menos que estén debidamente entrecomillados.

Y son sólo algunas de las reglas que aplican a la sintaxis de una dirección de correo electrónico, para mayor información (en inglés, ¡cuando no!) en RFC 822 y dirección de correo electrónico . La buena noticia es que PosgreSQL admite varios lenguajes de programación que junto con triggers o «disparadores» nos permitirán capturar y revisar los correos electrónicos antes de agregarlos a la base de datos (serán tratados a futuro en una entrada aparte). Y aunque nos hemos salido un poco de las consultas sencillas era necesario ir abonando el terreno hacia temas más avanzados (oh idioma castellano, qué poético eres, nunca cambies 😉 ).

Os ruego hagan la prueba escribiendo las sentencias en sus múltiples variantes, como ayuda os dejo el comando LIKE cuyo uso tiene una sintaxis más elaborada:

SELECT email FROM students WHERE email LIKE ‘%hotmail.com%’;

Produciendo el mismo resultado que con la virgulilla; vale destacar que al colocar el símbolo de porcentaje como comodín le estamos ordenando que nos busque cualquier dirección de correo electrónico registrado en nuestra tabla students que contenga la cadena de caracteres «hotmail.com» (obsérvese que si algún bromista registrara la dirección de correo electrónico «hotmail.com@gmail.com» sería devuelta también en la consulta, os animo a probarla -aunque dudo que alguien en verdad tenga ésa dirección-) pero eso aún no resuelve nuestro problema de mayúsculas y minúsculas.

Una solución sería utilizar una función integrada por defecto en nuestra base de datos, es decir, una serie de programas ya registrados y de propósito general; dicha función para este caso es LOWER() aplicado al campo email (ojo que si es así lo que entrecomillamos como condición debe ir todo en minúsculas):

SELECT email FROM students WHERE LOWER(email) LIKE ‘%hotmail.com%’;

o también podemos usar, como al principio, la virgulilla que nos ahorra el uso de comodines:

SELECT email FROM students WHERE LOWER(email) ~ ‘hotmail.com’;

Si quereís ver el resto de funciones de cadena, haced click aquí.

Por último, si quiséramos el caso contrario, listar los estudiantes que no tienen correo «hotmail» registrado:

SELECT email FROM students WHERE LOWER(email) !~ ‘hotmail.com’;

y lo único que hicimos fue agregarle el operador lógico «!» que indica negación «NOT», el cual si que lo podemos usar con LIKE:

SELECT email FROM students WHERE LOWER(email) NOT LIKE ‘%hotmail.com%’;

Y entonces nos desconectamos de la base de datos como es debido:

Postgresql_2015-02-02 20:01:21

<Eso es todo, por ahora>.

Download PDF

Gaceta Oficial N° 40.597: aumento 15% sueldo 1° febrero 2015.

Download PDF

Son 3 hojitas en formato pdf  (agradezco a «pdfsam» y lo recomiendo para dividir y combinar documentos en ese formato); con este aumento el sueldo mínimo en Venezuela se ubica en Bs. 5.622,48 (si tomamos como referencia el SICAD II serían aproximadamente US$ 114 mensuales).

Para descargar dicho ejemplar electrónico de la Gaceta Oficial desde nuestra página web haga click aquí.

Si desea descargarla desde el Tribunal Supremo de Justicia  deberá luego introducir el número «40597» en el cuadro de búsqueda rápida.

<Eso es todo, por ahora>.

Download PDF