Luis Colorado Acerca del Author: Luis Colorado trabaja como administrador de sistemas UNIX y de acceso a Internet para la empresa Telef�nica Sistemas, S.A. en Espa�a. Es Licenciado en CC. F�sicas por la Universidad Complutense de Madrid y ha preparado varias utilidades de libre distribuci�n para entornos UNIX. Contenidos:Introducci�n Motivaci�n M4 �C�mo funciona? �C�mo pasa la informaci�n del usuario al CGI? Descarga (Download) |
Resumen:
En este art�culo se describe un programa para permitir el
acceso a bases de datos desde consultas HTML. El programa tiene
como requisitos el control de accesos, la flexibilidad en la
configuraci�n y la independencia del formato de presentaci�n. El
programa es el resultado de una serie de ideas surgidas de la
lectura de una serie de art�culos sobre M4, aparecidos en las
revistas Linux Journal y LinuxFocus (www.linuxfocus.org), en
los 12 �ltimos meses.
Este art�culo pretende ser una descripci�n de los trabajos ---como dicen los ingleses, `a rationale'--- o de las ideas que me llevaron a realizar este programa.
No pretende ser un manual de usuario (un manual de referencia acompa�a al software, cuya URL de obtenci�n se presenta a lo largo del art�culo) sino mas bien una presentaci�n del mismo y una invitaci�n a los usuarios a que lo empleen y comuniquen al autor cualquier problema que puedan encontrar con �l.
El programa surgi� como respuesta a una serie de art�culos aparecidos en las revistas Linux Journal (*) y LinuxFocus (*) sobre el empleo de M4 en entornos de gesti�n de documentaci�n HTML, ya que dichos art�culos mostraban el potencial de M4, por s� solo, para el mantenimiento de documentos HTML y control de informaci�n insertable en el momento de generaci�n de las p�ginas.
Por otro lado, la disponibilidad de numerosos programas servidores web y numerosas aplicaciones de base de datos, hac�a chocante la ausencia de aplicaciones de interfaz entre los dos entornos (la mayor�a de aplicaciones de este tipo son comerciales, o tienen grandes defectos respecto a la dependencia de los formatos de presentaci�n).
Este programa trata de unificar los dos mundos con una aplicaci�n que reuna los siguientes requisitos:
La mayor parte de aplicaciones que conozco que se emplean como pasarela entre HTML y bases de datos, componen la informaci�n extendiendo el conjunto de tags de HTML para que se puedan identificar las `macros'. Pero esto tiene un grave problema: La mayor�a de las sustituciones que hay que hacer en un documento para conseguir el efecto deseado ocurren dentro de los propios tags HTML. Lo que hace a estos programas muy limitados (muchos de ellos `reinventan' tags solo con el fin de obtener un determinado efecto sobre un tag existente). Mi programa pretende emplear M4 a fondo con el fin de conseguir sustituciones de macro all� donde se necesiten. La independencia del formato de salida la impone el hecho de que el programa por s� no genera ning�n texto formateable, sino solo una colecci�n de macros con los resultados de la consulta, que luego una plantilla y M4 integran en un documento HTML.
La aplicaci�n propuesta consigue de forma aceptable estos requisitos, a costa de un peque�o coste de eficiencia (la aplicaci�n ha de llamar varias veces a M4 en el curso de una ejecuci�n) pero los resultados son satisfactorios en la mayor�a de los casos (normalmente, los accesos a bases de datos suelen provocar retardos superiores en las propias consultas).
M4 se cre� hace ya mucho tiempo con la idea de tener un procesador de macros potente y totalmente general. La utilizaci�n de M4 por la aplicaci�n es muy fuerte:
La aplicaci�n fu� creada inicialmente para enlazar el interface CGI (Common Gateway Interface, interface com�n de pasarela entre el servidor Web y los programas de aplicacion) con la base de datos PostgreSQL. Pronto se vi� que el programa era lo suficientemente general como para poder incluir otras pasarelas (por ejemplo pasarela con un servidor LDAP, o con otras bases de datos como Informix u Oracle). Se estandariz� el interface recogiendo la funcionalidad necesaria y se reescribi� el modulo PostgreSQL de acuerdo con este interface. Ahora es posible escribir nuevos drivers que permitan al programa enlazar con otros gestores de base de datos. |
Esto puede provocar perdidas de eficiencia, aunque las pruebas realizadas con la utilidad M4 de GNU, han sido bastante satisfactorias.
La aplicaci�n hace uso de expresiones regulares a la hora de verificar la regla de configuraci�n a emplear. El uso de comparaciones sencillas tiene como resultado una p�rdida notable de funcionalidad y posibilidades. El empleo de expresiones regulares para comparar permite, entre otras:
|
Debido a este �ltimo punto se consigue una gran funcionalidad: El agrupamiento de sub-expresiones regulares permite la exigencia de que los datos pasados por el cliente respondan a un formato espec�fico, y obtener la informaci�n que nos interesa para pasarla al driver que se encargar� de realizar la consulta.
Pongamos un ejemplo: Supongamos que nos interesa que el cliente nos pase una informaci�n en la query_string, y esta informaci�n debe ajustarse al formato:
CAMPO=valor
Adem�s nos interesa forzar que la query_string se ajuste a este formato y no haya informaci�n extra.
Nosotros podremos conseguir este prop�sito poniendo el siguiente t�rmino en la regla de selecci�n:
QUERY_STRING: "^CAMPO=[^&]*$";
Con la l�nea anterior conseguiremos que la regla s�lo se seleccione si la QUERY_STRING es de esta forma. Pero a�n m�s, si en vez de poner la l�nea anterior, rodeamos la parte correspondiente al valor de unos par�ntesis, el programa nos permitir� obtener, ya separada, la parte correspondiente al valor (adem�s, en este proceso, el programa transforma las secuencias de escape de la forma %xx, introducidas por el navegador) con el siguiente t�rmino:
QUERY_STRING: "^CAMPO=([^&]*)$";
Ha llegado el momento de describir c�mo funciona el programa. El programa, al arrancar, recibe del servidor web un conjunto de variables de entorno que transmiten informaci�n al mismo. Este conjunto de variables de entorno es todo lo que tiene el programa a su disposici�n para obtener datos de: �Qui�n es el cliente? �Desde donde hace la petici�n? �Qu� consulta est� haciendo? �Qu� tipo de informaci�n (MIME type) puede soportar el cliente? etc. El programa permite seleccionar la regla que emplear� bas�ndose en los t�rminos que aparecen en la parte izquierda de la regla. Estos son de tres tipos (actualmente):
QUERY_STRING: "^CAMPO=([^&]*)$";
! HTTP_ADDRESS: "^194\.142\.12\.";(Este ejemplo invalidar�a la regla si la petici�n llegara de la red 194.142.12.xxx)
[ QUERY_STRING: "USUARIO=([^&]*)" ];Este t�rmino permitir� pasar el nombre del usuario, caso de pasarlo el cliente, pero no invalida la selecci�n de la regla en caso de no aparecer.
Con toda esta artiller�a, ya tenemos las bases para empezar a construir reglas. A continuaci�n agruparemos todos los t�rminos que nos permitan construir una regla v�lida y los encerraremos entre llaves, para formar lo que llamaremos el lado izquierdo de una regla.
El lado izquierdo de una regla y el lado derecho se delimitan de igual modo (entre llaves) y se separan entre s� por el s�mbolo `->'.
El lado derecho contiene t�rminos con la misma estructura: un nombre de variable, el car�cter `:', una cadena de caracteres y el car�cter `;'. Los t�rminos del lado derecho son asignaciones de valores a variables, que se realizan, empleando los servicios de M4:
El resto de variables, pueden emplearse en el fichero plantilla, o ser�n empleadas por los drivers correspondientes.
Muy f�cil. Los grupos creados con las expresiones regulares de los t�rminos del lado izquierdo de la regla son definidos en variables con nombres espec�ficos (los nombres de las variables son `term_<i>_match_<j>', donde <i> hace referencia al n�mero de t�rmino en la regla y <j> hace referencia al n�mero del grupo (contando por la izquierda) en la expresi�n regular). As�, suponiendo que la query_string pasada por el cliente es:
y que tenemos los siguientes t�rminos en la regla:
QUERY_STRING: "NOMBRE=([^&]*)"; QUERY_STRING: "APELL1=([^&]*)"; QUERY_STRING: "APELL2=([^&]*)";Esto dar� como resultado:
term_0_match_0 <- "NOMBRE=JOSE"; term_0_match_1 <- "JOSE"; term_1_match_0 <- "APELL1=DE LA FUENTE"; (obs�rvese la transformaci�n de caracteres + por ` ') term_1_match_1 <- "DE LA FUENTE"; term_2_match_0 <- "APELL2=LOPEZ"; term_2_match_1 <- "LOPEZ";Drivers:
No haremos una descripci�n de c�mo se emplean los drivers en este art�culo, dejando al lector interesado la posibilidad de leer la documentaci�n del manual de referencia que acompa�a la distribuci�n.
S�lo diremos que en estos momentos tan s�lo hay un driver, para conexi�n a bases de datos tipo POSTGRESQL (el nombre del driver es este, precisamente) aunque el autor planea realizar uno para acceso a bases de datos LDAP.
Ejemplo:
Veamos un ejemplo completo para ilustrar el uso del programa:
Valga la informaci�n de la Tabla de consultas a la base de datos de `AVISOS A LOS NAVEGANTES' de slug.ctv.es. Es un ejemplo muy sencillo, que permite ver como emplear dos plantillas para ver registros individuales de una tabla, o un listado completo.
/etc/html2sql.cfg
{ PATH_INFO: "^/avisos/?$"; # Selecciona por PATH_INFO [SERVER_ADMIN: ".*"]; # Obtiene la info de SERVER_ADMIN. Opcional } -> { DRIVER: "POSTGRESQL"; PGTTY: "/dev/console"; # Env�a trazas a consola. PGDATABASE: "postgres"; # Hacemos una consulta (siempre ponemos el oid, que lo # emplear� internamente el fichero con la plantilla para # enlazar con los registros individuales). PGQUERY: "select oid,ct,titulo,texto,mt" " from avisos" " where (dt is NULL or dt > 'now')" " order by mt desc"; # Fichero que contiene la plantilla. M4FILE: "/usr/local/etc/httpd/plantillas_m4/avisos.m4"; WEBMASTER: "term_1_match_0"; #TESTMODE: "TRUE"; } # Esta regla de selecci�n permite seleccionar un aviso en el que se ha # elegido un OID (clave primaria) La informaci�n va incluida en la # variable PATH_INFO del CGI. { PATH_INFO: "^/avisos/([0-9]+)/?$"; SERVER_ADMIN: ".*"; } -> { DRIVER: "POSTGRESQL"; PGTTY: "/dev/console"; # igual que antes, trazas por consola. PGDATABASE: "postgres"; OID: "term_0_match_1"; # damos un nombre al OID. # Nuevamente, la selecci�n es importante. Incluimos el OID al # comienzo de los campos, por si quisieramos poner un hiperenlace para # borrar este registro. PGQUERY: "select oid,ct,titulo,texto,mt,dt,autor" " from avisos" " where (dt is NULL or dt > 'now') and oid=OID"; # La plantilla es diferente. M4FILE: "/usr/local/etc/httpd/plantillas_m4/avisos_oid.m4"; WEBMASTER: "term_1_match_0"; #TESTMODE: "TRUE"; } |
define(<<<for>>>, <<<dnl
ifelse(eval((<<<$2>>>) <= (<<<$3>>>)), 1, <<<define(<<<$1>>>,<<<$2>>>)$4<<<>>>dnl for(<<<$1>>>,eval(<<<$2>>>+1),<<<$3>>>, <<<$4>>>)dnl >>>)dnl >>>)dnl divert(0)dnl Mime-Version: 1.0 Content-type: text/html <HTML>
<!-- la tabla est\xe1 vac\xeda -->
>>>,<<<dnl /* PGRES_NTUPLES != 0 )( */
for(<<<i>>>,0,eval(PGRES_NTUPLES-1),<<<dnl
</table>
>>>)dnl /* PGRES_NTUPLES */ >>>,<<<dnl /* ifelse PGRES_RESULTSTATUS )(*/ Error en el resultado: <B>PGRES_RESULTSTATUS</b><BR>
>>>)dnl <CENTER><HR WIDTH=100></center>
|
divert(-1)
$Id: generic_list.m4,v 1.1 1998/07/06 17:13:33 luis Exp $ define(<<<cell>>>, <<<PGRES_CELL_$1_$2>>>) define(<<<field>>>, <<<PGRES_FNAME_$1>>>) define(<<<for>>>, <<<dnl ifelse(eval((<<<$2>>>) <= (<<<$3>>>)), 1, <<<define(<<<$1>>>,<<<$2>>>)$4<<<>>>dnl for(<<<$1>>>,eval(<<<$2>>>+1),<<<$3>>>, <<<$4>>>)dnl >>>)dnl >>>)dnl divert(0)dnl Mime-Version: 1.0 Content-type: text/html <HTML>
ifelse(PGRES_RESULTSTATUS, <<<PGRES_TUPLES_OK>>>,<<<dnl
<!-- la tabla est\xe1 vac\xeda -->
>>>,<<<dnl /* PGRES_NTUPLES != 0 )( */
>>>)dnl /* PGRES_NTUPLES */ >>>,<<<dnl /* ifelse PGRES_RESULTSTATUS )(*/ Error en el resultado: <B>PGRES_RESULTSTATUS</b><BR>
>>>)dnl <CENTER><HR WIDTH=100></center>
|
Los resultados se pueden ver, consultando, por ejemplo:
http://slug.ctv.es/cgi-bin/pg2cgi/avisos/
�
http://slug.ctv.es/cgi-bin/pg2cgi/avisos/20384
Descarga (Download)
El programa puede hallarse en la siguiente direcci�n del web:
http://slug.ctv.es/~luis/utils/pg2cgi-0.1.tar.gzTexto original en Castellano
P�ginas web mantenidas por Miguel �ngel Sep�lveda © Luis Colorado 1998 LinuxFocus 1998 |