Tutorial CGI I II III
Introducción a SQL
Tutorial VBScript

Fao.gif (4164 bytes)

Tutorial de CGI II

Que necesitamos para empezar

Para empezar necesitamos tener un poco de conocimiento en algún lenguaje de programación(el que sea).
La idea de esta guia es utilizar como base Perl, aunque seran dados ejemplos en C y tambien en Pascal (vamos Turbo todavia).
Creo que con eso basta para dar una idea general, (que por otra parte es lo que pretendo), y las adaptaciones necesarias para cualquier otro lenguaje con un poco de ingenio se podran hacer sin problemas.

Que son los scripts CGI?

Normalmente cuando un browser de Web llama a una URL en particular, sucede lo siguiente. Primero la computadora contacta el HTTP server con dicha URL. El server HTTP revisa si el archivo requerido por nuestra computadora se encuentra en su sistema, en caso afirmativo envia el archivo como respuesta. Nuestra computadora entonces, muestra el archivo en el formato apropiado.

Ademas de todo esto, los server de Web están configurados de tal manera que cada vez que se requiere un archivo de un directorio determinado (usualmente el cgi-bin), dicho archivo no es enviado; sino que es ejecutado como un programa y la salida de este programa es enviada a nuestra maquina para que esta la muestre. Esta funcion es conocida como "Common Gateway Interface" y los programas a los que nos referimos son los llamados scripts CGI.

En esta segunda parte veremos scripts que funcionan en base a los datos y variables que le son enviados a travez de un FORM en una pagina HTML, y dejaremos para la tercera de aquellos que no necesitan de esta input, por ejemplo los counters, las animaciones y otras cosas un poco mas complicadas.

Nuestro primer script.

Para empezar por lo mas simple y poder apreciar la funcionalidad de este sistema veremos un script muy facil de entender, el cual no necesita que le sean suministrados datos de ningun tipo para funcionar.
Pero sigamos con lo nuestro:

PERL
!#/usr/bin/perl                                                 <Esta linea llama al interprete de PERL

print "Content-type: text/html\n\n";
print"<HTML>\n";
print"<HEAD>\n";
print"<TITLE> Aprendiendo CGI</TITLE>\n";
print"</HEAD>\n";
print"<BODY>\n";
print"Hola intertips!";
print"</BODY></HTML>\n";

PASCAL
begin
  writeln "Content-type: text/html";
  writeln;
  writeln"<HTML>";
  writeln"<HEAD>";
  writeln"<TITLE>Aprendiendo CGI</TITLE>";
  writeln"</HEAD>";
  writeln"<BODY>";
  writeln"Hola intertips!";
  writeln"</BODY></HTML>";
end.
C
#include<stdio.h>

main()
{
printf("Content-type: text/html\n\n");
printf("<HTML>\n");
printf("<HEAD>\n");
printf("<TITLE>Aprendiendo CGI</TITLE>\n");
printf("</HEAD>\n");
printf("<BODY>\n");
printf("Hola intertips\n");
printf("</BODY></HTML>\n");
}

Es así de facil!! Y lo mejor de todo es que funciona!

Observen que l io primero que retornamos es un header indicando de que tipo es la información que enviamos, en este caso se trata de una pagina HTML, por lo tanto el header apropiado es :

Content-type: text/html

Tomemos en cuenta tambien que los primeros dos saltos de linea que introducimos son significattivos. Los códigos de retorno MIME, a los cuales pertenece "Content-type..", necesitan dos "newlines" siguiendolos para delimitar su fin. No enviar este segundo newline nos traera bastantes problemas. Los demas "newline" incluidos en la pagina que generamosno son realmente necesarios, pero facilitaran la lectura de alguien que haga un "View source".

Como vemos en los ejemplos tuvimos que generar todos los tags de la pagina, pero eso resulto muy simple, ¿No es asi?.
Ahora vamos a hacer algo un poco mas interesante, vamos a solicitar algunos datos con un form apropiado, y vamos a retornar una pagina que contenga los nombres de las variables utilizadas junto con el contenido de cada una ingresado por el usuario.

Un script que hace eco de un Form

En este punto comenzaremos a hacer uso de librerias especializadas (los sites donde conseguir cada una de las librerias figuran al final de este texto).
Quisiera recalcar que estas librerias no son únicas, existen muchas variaciones sobre el mismo tema, y cada una de ellas tiene su propia forma de manejarse, por lo tanto es conveniente revisar cuidadosamente la documentación que la acompaña en caso de que se utilize alguna otra que no figure aqui.

Estas librerias nos ahorraran el trabajo de separar los distintos componentes que son encapsulados en la variable de entorno QUERY_STRING (recuerdan lo que mencionamos en la primera parte?).
En el caso que estudiaremos, la llamada la hacemos al script en Perl, pero obviamente cambiando el nombre del ejecutable de acuerdo al lenguaje que estemos utilizando esto se soluciona.

Veamos el from que vamos a utilizar:

<html>
<head>
<title>prueba con un form</title>
</head>
<body>
<h1>Ingresa los datos que corresponda para hacer la prueba:</h1>
<br><hr>
<form method="post" action="http://mimaquina.midominio/cgi-bin/prueba.pl">
<ul>
<li>Nombre: <input type="text" name=nombre size=20>
<li>Edad: <input type="text" name=edad size=2>
<li>Hincha de:
<select name="equipo">
<option selected> Boca juniors
<option>River Plate
<option>San Lorenzo
<option>Independiente
<option>Racing Club
</select>
<li>Email: <input type="text" name=email size=20>
</ul>
<input type="submit" value="ok"><br>
<input type="reset" value="borrar"><br>
</form>
<hr>
</body>
</html>

Ingresa los datos que corresponda para hacer la prueba:

  • Nombre:
  • Edad:
  • Hincha de:
  • Email:



El script que utilizaremos sera muy simple y nos va a servir de base para futuros desarrollos. Veamos paso a paso su estructura:

  1. Primero llama al interprete en caso de ser necesario (Perl)

  2. Luego de incluir/carga la libreria, de alguna manera corre la funcion que separa  QUERY_STRING en sus componentes individuales.

  3. asignamos dichos componentes a las vasriables que vamos a utilizar.

  4. Imprimimos una salida como en cualquier programa y...

  5. Listo!

Aqui van los fuentes de cada uno de los lenguajes

PERL
!#/usr/bin/perl

push(@INC,"var/opt/ncsa/httpd/cgi-bin");
require("cgi-lib.pl");

&ReadParse;

$nombre=$in{´nombre´};
$edad=$in{'edad'};
$equipo=$in{'equipo'};
$email=$in{'email'};

print &PrinHeader;
print"<html>\n";
print"<head>\n";
print"<title>Aprendiendo CGI segundo ejercicio</title>\n";
print"</head>\n";
print"<body>\n";
print"Tu nombre es ",$nombre,"<br>\n";
print"Tienes",$edad," años y sos simpatizante de ",$equipo,"<br>\n";
print"Si alguien quisiera escribirte tu email es. ",$email,"<br>\n";
print"<hr>\n";
print"</body></html>\n";

PASCAL
Uses tpwcgi;

var nombre,edad,equipo,email:string;

Begin
Start CGI;
nombre:=Getvalue('nombre',1);
edad:= Getvalue('edad',1);
equipo:=Getvalue('equipo',1);
email:=Getvclue('email',1);

Makeheader;
Send ('<html>');
Send('<head>');
Send('<title>Aprendiendo cgi segundo ejercicio</title>');
Send('</head>');
Send('<body>');
Send('<hr>');
Send('tu nombre es'+nombre+'<br>');
Send('tienes'+edad+'años y sos simpatizante de'+equipo+'<br>');
Send('si alguien quisiera escribirte tu email es'+email+'<br>');
Send('<hr>');
Send('</body></html>');

endcgi;
end.

C
#include <stdio.h>
#include <errno.h>
#include <uncgi.h>
char *getenv();

main()
{
char *nombre;
char *edad;
char *equipo;
char *email;

uncgi();

nombre=getenv("WWW_nombre");
edad=getenv("WWW_edad");
equipo=getenv("WWW_equipo");
email=getenv("WWW_email");

printf ("Content-type:text/html\n\n");
printf("<html>\n");
printf("<head>\n");
printf("<title>Aprendiendo cgi segundo ejercicio</title>\n");
printf("</head>\n");
printf("<body>\n");
printf("<hr>\n");
printf("Tu nombre es %s <br>\n",nombre);
printf ("Teneis %s años y sos simpatizante de %S <br>\n",edad,equipo);
printf("Si alguien quisiera escribirte tu email es %s <br>\n",email);
printf("<hr>\n");
printf("</body></html>\n");
}

Es evidente que a partir de este punto podriamos abordar cosas mas complicadas si quisieramos, ya que es posible utilizar todos los recursos de cada lenguaje para efectuar las acciones y procesos que queramos.
Como sugerencia, la estructura que propongo para un script mas o menos decente es la siguiente ( de todas maneras igual que en matematicas de primer grado, el orden de los factores no altera el producto, aunque si lo hace mas dificil de mantener)

  • Asignación de variables

  • Proceso principal del script que genera la salida que queremos a partir de los datos de entrada

  • Envio de la pagina con los datos del proceso

Lo mejor es comenzar a practicar con las estructuras más comunes, decision (if) e iteración (for), haciendo pequeños programas y probando las salidas obtenidas.Por ejemplo, un script que dependiendo del contenido de la variable "nombre", retorne una pagina con distintos mensajes segun sea quien ha completado el form.
Los scripts pueden hacer cosas mas complicadas, como verificar que los campos sean llenados correctamente, modificar archivos y hasta mandar una pagina que no haya sido elaborada por ello. En el siguiente y ultimo punto veremos como implementar estos metodos en la forma de un "mini-guestbook".

Un Mini-Guestbook

Vamos a armar una especie de Mini.Libro de firmas, una aplicación bastante difundida, que nos servira de ejemplo para mostrar los puntos que mencionamos arriba.
Esto comienza con un form muy chiquito que solicita los siguientes datos:

  • Nombre

  • Email

  • Comentarios

A partir de ahi, lo que el usuario ingrese sera grabado en otra pagina, la pagina del guestbook mas precisamente, y luego finalmente se presentara una pantalla agradeciendo el comentario e invitando a mirar el libro.

Para poder conseguir lo que queremos, utilizaremos un metodo muy comun, estableceremos una marca invisible (un comentario) en la pagina en cuestion y tomaremos dicha marca como punto de partida para cada nuevo comentario. Los pasos a seguir en este caso son los siguientes:

  1. Verificar la entrada del usuario, para que no existan campos vacios, retornando un mensaje de error si existe algun problema.

  2. Abrir y leer la pagina del mini-guestbook linea por linea (grabando cada una de ellas en un archivo temporario) hasta encontrar la marca que indica el comienzo de los comentarios (o sea el ultimo ingresado), grabar despues de la misma el input del usuario y terminar de copiar el resto del archivo.

  3. Cerrar los archivos, borrar el original y renombrar el temporario.

  4. Devolver un codigo de retorno "Location.." que llevara al usuario a una pagina de agradecimiento que tendra un link al guestbook.

Muchos se preguntaran, y que pasa si dos usuarios acceden al mismo tiempo al archivo? Como hacen para leerlo/grabarlo? Quien tiene prioridad?.
Creo que seria intentar avanzar demasiado en este momento, a manera de comentario (de todas formas les contare como hacerlo en la tercera parte) lo que se necesita es una manera de trabar el acceso  al archivo mientras se esta trabajando con el.

Como siempre veremos el Form que permite al usuario agregar su nombre y su comentario en nuestro libro de firmas.

<html>
<head>
<title>Firme nuestro libro</title>
</head>
<body>
<h1>Ingrese sus datos y el comentario que desee hacernos</h1>
<br><hr>
<form method="post" action="http://mimaquina.midominio/cgi-bin/ingreso.pl">
Nombre:<br><input type="text" name=nombre size=20><br>
Email: <br><input type="text" name=email size=20><br>
Su comentario: <br><textarea name="comentario" rows=5 cols=40>Escriba aqui su comentario</TExtarea><br>
<input type="submit" value="Ok"><br>
<input type="reset" value="borrar"><br>
</form>
<hr>
</body>
</html>

PERL
!#/usr/bin/perl
push(@INC,"/var/opt/ncsa/httpd/cgi-bin");
require("cgi-lib.pl");

&ReadParse

$nombre=$in{'nombre'};
$email=$in{'email'};
$comentario=$in{'comentario'};

if (($nombre eq "2)||($emaileq"")||($comentarioeq""))
{
print&PrintHeader;
print"<html>\n";
print"<head>\n";
print"<title>error en el ingreso</title>\n";
print"</head>\n";
print"<body>\n";
print"<hr>\n";
print"<h1> Alguno de los campos que ingreso no contenia datos </h1>";
print" Por favor apriete este boton para ingresar sus datos nuevamente";
print"<a href="/imagenes/boton.gif">;
printf"<hr>\n";
print"</body></html>\n";
exit;
}

open (GB,"<htdocs/mini-gb.html");
@lineas=<GB>;
close GB;

$comentario =-s/\n/<br>\n/go;

 

open(GB,">/htdocs/mini-gb.htm");
foreach$linea(@lineas){
$linea=~s/<!--Ultimo comentario-->/<1--ultimo comentario-->\nNombre:
   $nombre<BR>\nEmail:<a href=\"mailto:$email\">$email<\a><br>\n
   comentarios:<br>\n$comentarios<hr>\n/o;

print GB $line;
}
closeGB;

print "location: http://mimaquina.midominio/httdocs/gracias.htm\n\n";

Pascal
Uses TPWCGI;

var nombre,edad,linea
      equipo,email: string:
      Arch-In, Arch-Out: text;

assign (Arch-In, 'D:\WEBSITE\HTDOCS\MINI-GB.HTM');
assign (Arch-Out,'D:\WEBSITE\HTDOCS\MINI-GB.TMP');

reset (Arch-In);
rewrite (Arch-Out);
linea:='';

Begin
StartCGI;

nombre:=Getrvalue('nombre',1);
email:=Getvalue('email,1);
comentario:=Getvalue('comentario',1);

if ((nombre = '')or (email='')or(comentario=''))
then begin
MakeHeader;
Send ('<html>');
Send('<head>');
Send('<title>Error en el ingreso</title>');
Send('</head>');
Send('<body>');
Send('<hr>');
Send('<h1> Alguno de los campos que ingreso no contenia datos</h1>');
Send('Por favor apriete este boton e ingrese sus datos nuevamente');
Send('<a href="/imagenes/boton.gif">');
Send ('<hr>\n');
Send('</body></html>');
EndCGI;
end;

else begin
Readln(Arch-In, linea);
while and NOT EOF (Arch.In) do
begin
writeln (Arch-Out, linea);
readln(Arch-In, linea);
if (linea = ' <!--ultimo comentario-->')
then begin
writeln (Arch-Out, linea);
linea:= 'Nombre:'+nombre+'<br>;
Writeln (Arch-Out, linea);
linea:=´'Email: <a href="mailto'+email+'">+email'</a><br>';
Writeln (Arch-Out, linea;linea);
linea:= 'Comentario:<br>';
writeln (Arch-Out,linea);
for i:=1 to GetLinNum('comentario') do
  begin
   linea:= GetValue ('comentario',1)+'<BR>';
   Writeln (Arch-Out, linea);
  end;
end;
end;

Close (FI);
Close(FO);

erase (FI);
rename(FO,'D:\WEBSITE\HTDOCS\DOCUMEN\MINI-GB.HTM');

Send ('Location: http://mimaquina.midominio/httdocs/gracias.htm');
Send ('');
EndCGI

end.

Me parecio redundante incluir la version en C ya que esta puede ser facilmente incluida a partir del fuente de Pascal.
Como el TEXTAREA que utilizamos para cargar el comentario entrega sus datos solo separados por newlines, tuvimos que hacer un pequeño proceso en cada uno de los programas para generar un <br< por cada uno de ellos en la pagina definitiva.
Notaran que existen diferencias en la forma de hacer el "update" del archivo en cada una de lasversiones. En el fuente Perl aproveche una función de sustitución   bastante potente que simplifica las cosas, en cambio en la version  en Pascal hubo que hacer dicha sustitucion "a mano".
Para finalizar esta segunda parte veremos una lista de cosas a tomar en cuenta la hora de programar scripts CGI.

Puntos importantes al programar scripts

Un script debe:

  • Ser ejecutable (o en el caso de Perl incluir la llamada al interprete)

  • Estar ubicado en el directorio cgi-bin. La ubicación de este server va a estar definida por el administrador del server.

  • Sea capaz de acceder a los archivos ue necesita. Como el script corre desde el directorio cgi-bin, todas las referenciasrelativas que hagamos van a estar referenciadas al mismo. Por las dudas cuando tengamos que retornar una pagina HTML completa, usemos su URL completa.

  • Teenr seteados los permisos correctamente. Perdonen que siga jodiendo con lo mismo, pero más de una vez las cossas no me anduvieros por esta sencilla razón. (Nadie podia ejecutar el programa excepto yo...)

Bueno, los dejo, espero no haberlos aburrido demasiado, que les sea de utilidad y encontrarlos leyendo la tercera y ultima parte (espero que en el tiempo que tarde en terminarla no surjan demasiadas cosas nuevas que me hagan empezar una cuarta ;-P!).

Bye Bye ;-)

   < Anterior | Siguiente >