CGI's con Shell Scripts

 

El nombre CGI proviene del inglés Common Gateway Interface, y vienen a ser programas escritos en cualquier lenguaje que añaden una mayor funcionalidad a las paginas Web. Son programas que se ejecutan en el servidor, no en la máquina cliente como sucede con los javascript.

Antes de continuar debo decir que para entender lo que voy a comentar es necesario tener algunas nociones, aunque sean mínimas de lenguaje HTML.

Un cgi permite construir por ejemplo una página web dinámicamente, tratar los datos de un formulario, o realizar determinadas tareas en la máquina servidor.

El motivo de hablar aquí de cgi's es debido a la posibilidad de construirlos en shell script. Hay lenguajes más potentes y flexibles como perl, python, C, VisualBasic, Java, etc. (que se salen del ámbito de este curso), pero el caso que nos incumbe es que se pueden construir en shell script. Tampoco voy a dar una clase magistral sobre el tema, pues no soy ni mucho menos un experto, pero si puedo dar unas pequeñas ideas a aquellos a los que les ha resultado útil el curso. Si tienes instalado Linux (no sé si trae servidor web con la instalación) y quieres montar un servidor web, puedes descargarte el Apache desde http://www.apache.org (venias con la intención de aprender un poco de UNIX y al final acabas montando un servidor web. Ya es un aliciente). Si tienes Windows, puedes encontrar también allí una versión especifica para Windows, pero evidentemente los cgi que vamos a desarrollar aquí no te funcionaran, pero tendrás un servidor web bajo Windows. No es complicado configurar el Apache para las tareas básicas, pero hay que leerse las instrucciones que por desgracia vienen en inglés.

Al construir un cgi con comandos UNIX tenemos toda la flexibilidad que dicho sistema operativo nos proporciona. Además podemos utilizar programas realizados en otros lenguajes dentro del propio shell script o cgi.

Lo mejor para entender un cgi creo que es mostrar un ejemplo como el siguiente, en el que construiremos una pagina web titulada prueba en la que aparezca un mensaje.

	#!/bin/ksh
	echo "Content-type: text/html"
	echo ""
	echo "<html><head><title>P&aacute;gina Web para probar el primer CGI</title></head>"
	echo "<body bgcolor=yellow>"
	echo "<H2>PRUEBA CGI</H2>"
	echo "<font face=\'Arial, Helvetica\' size=2>"
	echo "<p align=\'center\'>Esta p&aacute;gina se ha creado con mi primer CGI</p>"
	echo "</font></body>"
	echo "</html>"

Este ejemplo, salvo errores en las comillas deberia funcionar. Este mismo cgi en C seria:

	#include <stdio.h>
	main()
		{
		printf("Content-type: text/html\n\n");
		printf("<html><head><title>P&aacute;gina Web para probar el primer CGI</title></head>");
		printf"<body bgcolor=yellow>");
		printf("<H2>PRUEBA CGI</H2>");
		printf("<font face=\'Arial, Helvetica\' size=2>");
		printf("<p align=\'center\'>Esta p&aacute;gina se ha creado con mi primer CGI</p>");
		printf("</font></body>");
		printf("</html>");
		}

Como se puede ver un cgi se puede escribir en cualquier lenguaje. Antes de seguir adelante, he de avisar de que para que funcione el CGI debe tener permisos de ejecución, por lo que habrá que hacer un chmod:

chmod 755 <archivo>.cgi

Es conveniente ponerle la extensión cgi a los archivos de dicho tipo, para evitar por un lado confusiones a la hora de manipularlos y por otro para evitar errores de funcionamiento. Podemos observar que en todo cgi las dos primeras líneas de la página que se genere deben ser:


echo "Content-type: text/html"
echo ""

en donde la primera línea especifica el tipo de contenido de la página. Existen diferentes tipos, los cuales no vamos a comentar.

Un ejemplo tipico de CGI es un contador de visitas de una pagina web. Vamos a usar el mismo ejemplo anterior, y mostrar el valor del contador, que se supone que guardamos en un archivo llamado contador.txt (el nuevo código insertado va en cursiva), le incrementamos el valor en 1 (la visita que acabamos de realizar al visualizar la página) y guardamos el nuevo valor en el mismo archivo, sobreescribiendolo. Ojo, hay que crear el archivo contador.txt con un valor determinado. Si tras dos pruebas no se incrementa el contador, dale permiso de escritura al archivo (suele ser algo que se olvida fácilmente):

	#!/bin/ksh
	echo "Content-type: text/html"
	echo ""
	echo "<html><head><title>P&aacute;gina Web para probar el primer CGI</title></head>"
	echo "<body bgcolor=yellow>"
	echo "<H2>PRUEBA CGI</H2>"
	echo "<font face=\'Arial, Helvetica\' size=2>"
	echo "<p align=\'center\'>Esta p&aacute;gina se ha creado con mi primer CGI</p>"
	echo "<p>Eres el visitante n&uacute;mero: "
	CONTADOR="$( < contador.txt)"
	CONTADOR=(($CONTADOR + 1))
	echo $CONTADOR > contador.txt
	echo "$CONTADOR</p>"
	echo "</font></body>"
	echo "</html>"

Con lo visto hasta aquí podemos decir que un cgi es un shell script en el que la salida por pantalla se presenta en formato HTML. Las operaciones que se realizan dentro del cgi son idénticas a las realizadas con un shell script normal, pudiendo hacer llamadas a programas desarrollados en otros lenguajes, utilizando herramientas como awk, sed, etc. A modo de ejemplo, implementaremos el caso anterior con awk.

	#!/bin/ksh
	echo "Content-type: text/html"
	echo ""
	echo "<html><head><title>Pagina Web para probar el primer CGI</title></head>"
	echo "<body bgcolor=yellow>"
	echo "<H2>PRUEBA CGI</H2>"
	echo "<font face=\'Arial, Helvetica\' size=2>"
	echo "<p align=\'center\'>Esta p&aacute;gina se ha creado con mi primer CGI</p>"
	echo "<p>Eres el visitante n&uacute;mero: "
	CONTADOR="$( < contador.txt)"
	awk '{ contador+=1;}
	END { printf "%.5d", contador}' contador=$CONTADOR
	echo $CONTADOR > contador.txt
	echo "$CONTADOR</p>"
	echo "</font></body>"
	echo "</html>"

Si la página fuera estática,como sucede en la realidad, habría que llamar al cgi desde la propia pagina:


...
</p>Eres el visitante N&uacute;mero: <IMG SRC=\"archivo.cgi?parametro1=valor1&parametro2=valor2&...\" alt=\'Contador\'></p>
...

Y el cgi realizaria las operaciones antes vistas del contador.

Hasta el momento hemos visto cgi's a los que se llamaría sin pasarle parámetros. Pero normal es que cuando llamemos a un cgi sea para mostrar una página o realizar una tarea en función de unos datos suministrados a través de un formulario por ejemplo. Sin quererlo acabamos de ver como se realiza una llamada al cgi pasándole parámetros. Los parametros se pasan en una cadena, que habrá que tratar para separar los diferentes parámetros que le lleguen, lo cual podremos hacer con programas construidos especificamente para ello (en C por ejemplo) o utilizando algo que hemos aprendido en este curso, el editor sed. Los parametros dentro del cgi estarán dentro de unas variables de entorno, llamadas QUERY_STRING y CONTENT_LENGTH. El uso de QUERY_STRING o CONTENT_LENGTH dependerá del modo en que se envía la información. Existen dos formas de enviar la información: GET y POST. Si se utiliza el método GET habrá que emplear QUERY_STRING, y si se emplea el método POST habrá que emplear CONTENT_LENGTH. Si se emplea el método GET la información no puede superar un cierto tamaño (1 kb), mientras que si se emplea el método POST no existe dicha limitación, pues se toma la información de la entrada estándar (stdin). El usar uno u otro método se especificará a la hora de definir la acción a ejecutar con la información del formulario.


<FORM ACTION="direccion_cgi" METHOD="metodo" NAME="nombre">
....
</FORM>

Para más información sobre el tema, es conveniente consultar cualquier manual o tutorial sobre HTML.

En el siguiente ejemplo, que evidentemente admimte mejoras y optimizaciones pero que muestro así para mayor claridad, vemos como se pueden obtener los parametros que se pasan al cgi, para poder trabajar con ellos.

	#!/bin/ksh

	if [ $1 ]
		then
			cadena=$1
	else
			cadena=`head -c -n$CONTENT_LENGTH`
	fi
	variable1=`echo $cadena | awk -F "&" '{ print $1 }' | awk -F "=" '{ print $2 }'`
	variable2=`echo $cadena | awk -F "&" '{ print $2 }' | awk -F "=" '{ print $2 }'`
	variable3=`echo $cadena | awk -F "&" '{ print $3 }' | awk -F "=" '{ print $2 }'`

	echo Content-type: text/html
	echo ""
	echo "<html><head>"
	...

Otro ejemplo:

	#!/bin/ksh

	if [ $1 ]
		then
			cadena=$1
		else
			cadena=`head -c -n$CONTENT_LENGTH | sed 's/%2B/+/g
				s/%2F/\//g
				s/%3A/:/g'`
	fi
				# Tratamiento de los argumentos recibidos para utilizarlos en el cgi
	Variable1=`echo $cadena | awk '{
		if (index($0,cadena1) > 0)
			print valor1}'`
	Variable2=`echo $cadena | awk '{
		if (index($0,cadena2) > 0)
			print valor2}'`
	Variable3=`echo $cadena | awk '{
		if (index($0,cadena3) > 0)
			print valor3}'`
	...

Ejemplo en el que se formatea QUERY_STRING para posterior utilización:

	#!/bin/ksh
	cadena=`echo $QUERY_STRING | cut -c7-200 | sed '1,$ s/+/|/g'`
	echo Content-type: text/html
	echo ""
	...

Una vez que hemos recibido los parámetros necesarios, tan solo hay que procesarlos, y en función de los mismos construir la página adecuada.

Creo que con lo visto hasta aquí nos podemos hacer una idea de como construir un cgi, para profundizar más es conveniente acudir a documentación de lenguaje HTML y cgi´s. Una dirección que puede resultar útil es http://www.w3.org/. El lenguaje a emplear dependerá por un lado de los lenguajes que soporte el servidor, de la facilidad para implementar lo que deseamos construir, y como no, de nuestras preferencias.