Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad

Tutorial: Cómo procesar formularios CGI en Perl y crear scripts que envíen correo, Monografías, Ensayos de Tecnologías de Red y TCP / IP

En este documento se presenta un tutorial sobre cómo procesar formularios CGI en Perl y crear scripts que envíen correo. El tutorial explica cómo leer y procesar datos de formularios, crear archivos de bloqueo, manejar errores y enviar correos electrónicos. Se incluyen ejemplos prácticos de código Perl.

Tipo: Monografías, Ensayos

2019/2020

Subido el 16/07/2020

liliana-correa-2
liliana-correa-2 🇲🇽

1 documento

1 / 25

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
Javier E. Pérez Delgado
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19

Vista previa parcial del texto

¡Descarga Tutorial: Cómo procesar formularios CGI en Perl y crear scripts que envíen correo y más Monografías, Ensayos en PDF de Tecnologías de Red y TCP / IP solo en Docsity!

Javier E. Pérez Delgado

INTRODUCCIÓN

El CGI ( Common Gateway Interface ) es un estandar para comunicar aplicaciones externas con los servidores de información, tales como servidores HTTP o Web. Un documento en HTML que el daemon del Web se trae es estático, es decir, se mantiene constante: un fichero de texto que no cambia. Un programa CGI, por otro lado es ejecutado en tiempo real, así que puede generar información dinámica.

Por ejemplo, supongamos que quieres enganchar tu base de datos de Unix al WWW, para permitir a gente de todo el mundo consultarla. Básicamente se necesitará un programa CGI que el daemon del Web ejecutará para transmitir la información al gestor de base de datos, y recibir los resultados para presentarselos al cliente. Este es un ejemplo de pasarela ( gateway ), y es lo que CGI, actualmente en su versión 1.1, tiene en sus orígenes.

El ejemplo de la base de datos es una idea sencilla, pero la mayoría de las veces dificil de implementar. Realmente no hay límite con lo que tu quieras enganchar al Web. La íunica cosa que debes recordar es que haga lo que haga tu progrma CGI, no deberá tardar mucho tiempo en procesar. De otra manera, el usuario estaría esperando con su navegador a que algo pase.

Especificaciones

Como un programa CGI es un ejecutable, es equivalente a dejar a el mundo ejecutar un programa en tu sistema, que no es lo mas seguro a hacer. Por ello existen una serie de precauciones de seguridad que son necesarias de implementar cuando se usan programas CGI. Probablemente la que afectará al usuario típico del Web , es que hecho de que los programas CGI necesitan residir en un directorio especial, así el servidor sabe que tiene que ejecutarlo, en vez de simplemente mostrarlo por pantalla. Este directorio está generalmente bajo el control del webmaster , prohibiendo al usuario medio crear programas CGI. Hay otros métodos para permitir el accesos a scripts CGI, pero depende del webmaster que se te de esta posibilidad. Así que deberás contactar con tu webmaster para consultar la factibilidad de permitirte un acceso a los CGI.

Si dispones de una versión del servidor HTTPd NCSA , verás un directorio denominado /cgi-bin. Este es el directorio especial antes mencionado, donde todos los programas CGI residen. Un programa CGI se puede escribir en cualquier lenguaje que permita ser ejecutado en el sistema, como:

C/C++ Fortran PERL TCL Algún Shell de Unix Visual Basic AppleScript

Simplemente depende de lo que tengas en tu sistema. Si usas un lenguaje de programación como C o Fortran , como ya sabrás, debes compilar el programa antes de

El servidor usa tanto de líneas de comando, como variables de entorno para pasar los datos del servidor al script.

Estas variables de entorno se activan cuando el programa ejecuta el programa cgi.

Especificación

Las siguientes variables no dependen de la información enviada y son activadas en todos los casos:

SERVER_SOFTWARE

Devuelve el nombre y la versión del software del servidor de información que contesta la petición de usuario (y ejecuta el programa cgi). Formato: nombre/versión.

SERVER_NAME

Devuelve nombre de host del servidor, el alias DNS, o la dirección IP como aparecería en las URL autoreferenciadas.

GATEWAY_INTERFACE

Devuelve la revisión de la especificación CGI con que el servidor puede trabajar. Formato: CGI/revisión.

Las siguientes variables de entorno son específicas de la petición de usuario, y es el programa del gateway el que las da el valor:

SERVER_PROTOCOL

Da el nombre y revisión del protocolo de información con el que la peticion de usuario viene. Formato: protocolo/revisión. SERVER_PORT

Devuelve el número de puerto por el cual fue enviada la petición.

REQUEST_METHOD

Devuelve el método por el cual la petición fue enviada. Para HTTP serán "GET", "HEAD", "POST", etc.

PATH_INFO

La información extra sobre el path , tal como es dada por el cliente. En otras palabras, podemos acceder a los scripts por su pathname virtual, seguido de alguna

información extra. Esa información extra es enviada como PATH_INFO. La información será decodificada por el servidor si viene de una URL antes de pasarla al script CGI.

PATH_TRANSLATED

El servidor proporciona una versión traducida del PATH_INFO, que transforma el path virtual al físico.

SCRIPT_NAME

Path virtual al script que va a ejecutar, usado para autoreferenciar URL.

QUERY_STRING

La información que sigue al signo ‘?’ en la URL que referencia al script. Es la información de la pregunta. No deberá ser decodificada de ningún modo. Esta variable será activada cuando hay una petición de información, sin hacer caso de la decodificación de la línea de comandos.

REMOTE_HOST

El nombre de host que realiza la petición. Si el servidor no posee esta información activará REMOTE_ADDR y dejará esta desactivada.

REMOTE_ADDR

La dirección IP del host remoto que realiza la petición.

AUTH_TYPE

Si el servidor soporta autentificación de usuario , y el script está protegido, esta es el método de autentificación específico del protocolo para validar el usuario.

REMOTE_USER

Si el servidor soporta autentificación de usuario , y el script está protegido, este será el nombre de usuario con el que se ha autentificado.

REMOTE_IDENT

Si el servidor HTTP soporta autentificación RFC 931 , entonces está variable se activará con el nombre del usuario remoto obtenido por el servidor. Esta varible solo se utilizará durante el login.

CONTENT_TYPE

Para peticiones que tienen información añadida, como HTTP POST y PUT, este será el tipo de datos contenido.

seleccionado. (Los usuarios también pueden enviar ficheros con los formularios, pero no nos ocuparemos de ello.)

Estos pares nombre-valor llegan como una larga cadena que necesitamos formatear. No es muy complicado, hay una gran cantidad de rutinas que lo hacen por tí. En el directorio CGI de Yahoo encontrarás unas cuantas en varios lenguajes.

Si aun así prefiere hacerlo usted mismo, aquí esta el formato de la cadena:

“nombre1=valor1&nombre2=valor2&nombre3=valor3”

Así que sólo hay que dividir donde están los signos ‘&’ y ‘=’, y luego hacer dos cosas a cada nombre y valor:

1.Convertir todos los signos ‘+’ a espacios. 2.Convertir todas las secuencias ‘%xx’ al valor del carácter cuyo valor ASCII sea ‘xx’ en hexadecimal. Por ejemplo convertir ‘%3d’ a ‘=’.

Esto se hace necesario porque la larga cadena original esta codificada según el código URL, para permitir los signos ‘&’, ‘=’, y todo lo que el usuario introduzca.

Pero, ¿de donde se obtiene la cadena de entrada? Esto dependerá del método por el cual el formulario haya sido enviado:

Para los envíos con GET, será la variable de entorno QUERY_STRING. Para los envíos con POST, habrá que leer del STDIN. El número exacto de bytes a leer estará en la variable de entorno CONTENT_LENGTH.

DEVOLVIENDO LA RESPUESTA AL USUARIO

Primero, escribir la linea

Content-Type: text/html

más otra línea en blanco en el STDOUT. Después, escribiremos nuestra pagina de respuesta en HTML al STDOUT, y será enviada al usuario cuando el script esté ejecutado.

Sí, estamos generando código en HTML en tiempo real. No es difícil, si no más bien directo. El código HTML fue diseñado lo suficientemente simple para poder ser generado por este método.

GUARDANDO LA ENTRADA DEL USUARIO EN UN

ARCHIVO

En este apartado vamos a guardar los datos escritos por el usuario en un archivo para poder recuperarlos posteriormente. Como ejemplo utilizaremos un formulario para

/users/jperez/www/tutor/chiste.txt

Para abrir el fichero para añadir al final usaremos el comando de perl para abrir ficheros, que tiene la siguiente sintaxis:

open(FILEHANDLE,">>nombrearchivo");

FILEHANDLE es como llamaremos al archivo mientras esté abierto. Es similar a una variable. Nombrearchivo es el archivo a abrir. Los signos ‘mayor’ (>>) son importantes, y como en el shell indican ‘añadir a un fichero’.

Así la orden de apertura quedará así:

open(CHISTE,">>/users/jperez/www/tutor/chiste.txt");

Nota: Es aconsejable usar letras mayúsculas para FILEHANDLE para ayudar a distinguirlo de las variables.

Escribir a un fichero es idéntico a como hicimos previamente. La única diferencia es que el FILEHANDLE es el primer argumento de la sentencia print, y está separado de lo que será imprimido por un espacio. Por ejemplo para escribir la linea “Las rosas son rojas” al FILEHANDLE CHISTE, escribiremos:

print CHISTE "Las rosas son rojas\n";

Escribir variables se realiza de la misma manera:

print CHISTE "Las rosas son ",$in{'colorrosas'},"\n";

El código para nuestro ejemplo necesitará escribir al archivo:

  1. El nombre del usuario precedido con la cadena “Nombre:”
  2. Una línea en blanco.
  3. El chiste enviado.
  4. Una línea con 50 guiones.

El código es el siguiente:

print CHISTE "Nombre: ",$in{'nombre'},"\n"; print CHISTE "\n"; print CHISTE $in{'chiste'},"\n"; print CHISTE "--------------------------------------------------\n";

Ahora solo nos queda cerrar el fichero, y esto lo hacemos con el comando:

close FILEHANDLE;

DEVOLVIENDO UNA PÁGINA QUE NO HEMOS

GENERADO

En este apartado crearemos un libro de visitas sencillito. Durante el proceso de realización, haremos bastantes cosas de forma ordenada.


Última modificación 21/9/

Como se puede ver, los nombres serán añadidos al final del formulario.

Estos son los pasos para realizar nuestra tarea:

  1. Verificar la entrada, devolviendo un mensaje de error si hay un problema.
  2. Uraremos un bloqueo de archivo denominado ‘del pobre’. Creando un nuevo archivo denominado. Si este archivo existe el programa se detendrá durante un segundo y lo volverá a intentar.
  3. Abriremos y leeremos el archivo del libro de firmas actual: guestbook.html.
  4. Borraremos este archivo, y escribiremos un nuevo fichero que consistirá en la antigua información con toda la nueva en el sitio apropiado. Usaremos el comentario como marcador donde añadir entradas.

Nota: Puede ser deseable hacer una copia de seguridad del archivo, antes de borrarlo. No lo hacemos en este ejemplo, pero lo recomiendo en cualquier desarrollo. Se podrá hacer por cualquier método, incluido una llamada al sistema para copiar (cp).

  1. Retornar una directiva de lugar apuntando a una página de agradecimiento que ya hayamos preparado.
  2. Desbloquear borrando el archivo .guestlock.

Obviamente, este no es el mejor libro de visitas, pero servirá como un buen ejemplo, y es fácilmente ampliable.

Empecemos:

  1. Como es habitual nuestro script deberá empezar con una llamada al Perl, los comentarios apropiados, y una llamada a la rutina ReadParse. No lo detallaremos aquí, ya que se hizo anteriormente.
  2. Para empezar debemos verificar los datos de entrada. Nos queremos asegurar de que no hay campos en blanco, y de que la dirección e-Mail contiene una arroba (@). Para ventaja nuestra, las cadenas nos vienen dadas sin los espacios en blanco, justo igual que los navegadores cuando presentan páginas html. Esto significa que solo debemos comprobar que ninguna de las cadenas es igual a la cadena vacía, “”. En perl, como en muchos lenguajes, las cadenas se comparan de manera diferente a los números. Usaremos ‘ eq ’ para comprobar la igualdad de cadenas, y el signo ‘==’ para comprobar la igualdad de números. Usearemos ‘ ne ’ y ‘!=’ respectivamente para las comparaciones ‘no igual’.

Podemos hacerlo de la siguiente manera:

_if ($in{'nombre'} eq "") {

Hay una cadena vacía, devolver mensaje de error_

# salimos al final del script ahora, tenemos un error exit; }

Como podrás adivinar, Ahora no ponemos el código para devolver el mensaje de error, en el ejemplo de arriba. Aún así muestra lo facil que es comprobar que un campo está vacío. Nota: Los paréntesis () y las llaves ({}) son importantes. Los paréntesis contienen lo que se está comprobando como verdadero o falso, y las llaves contienen las sentencias a ejecutar si es verdadero. Como vamos a realizar varias comprobaciones de cadenas vacías, y vamos a devolver el mismo error para todas ellas, podemos incluirlas en la misma sentencia if- then uniéndolas por OR logicos ||, en perl. El OR significa que alguna de las comprobaciones tienen que ser verdad, para que toda la sentencia sea cierta.

Un ejemplo de comprobar si tres variables no están vacias podría ser este:

_if (($in{'nombre'} eq "") || ($in{'email'} eq "") || ($in{'comentarios'} eq "")) {

algun campo está en blanco, devolver mensaje de error_

# salimos al final del script ahora, tenemos un error exit; }

De nuevo he omitido, el codigo del mensaje de error, ya que es sencillo construir un pequeña tabla con los codigos para devolver un código de error útil para el usuario. El código que he elegido para hacerlo aparece más tarde en el código final de guestbook.pl.

La última verificación que necesitamos realizar es comprobar que la dirección eMail del usuario contiene un signo (@). Lo realizaremos fácilmente con las potentes expresiones regulares que el perl proporciona. Una expresion regular sencilla para chequear esto sería /\w@\w/. Simplemente describe una situación donde una palabra aparece delante y detras de un símbolo @. Las expresiones regulares son una herramienta extremadamente potente, pero no entran dentro del dominio de esta lección.

Para llevar a cabo la comprobación de que la expresión se cumple, simplemente comparamos. Funcionará como las comparaciones normales, pero usando el símbolo ‘ =~ ’ para igualdad y el símbolo ‘ !~ ’ para desigualdad. La expresión regular podría codificarse así:

_if ($in{'email'} !~ /\w@\w/) {

La expresión regular no es igual, devolver mensaje de error.

}_

De nuevo, he omitido el mensaje de error para este código.

Para crear el archivo de bloqueo, simplemente deberemos abrir y cerrar el archivo. Así crearemos un archivo de 0 bytes de longitud, que servirá en nuestro chequeo, y bloqueará otros procesos que la gente pueda realizar en ese momento, hasta que este haya acabado. Para ello esaremos un trozo de código que aquí se detalla:

open(LOCK,">/users/jperez/www/tutor//.guestlock"); close LOCK;

  1. Ahora tnemos un bloqueador del fichero. Ahora deberemos abrir y leer todos los contenisdos del guestbook.html. Esto se hace fácilmente abriendo el archivo para lectura. En el comando open antes empleado usaremos el símbolo (<) donde antes usamos (>>). El resultado será:

open(FILEHANDLE,"<nombrefichero");

El código será::

open(GB,"<users/jperez/www/tutor/guestbook.html");

Leer del fichero es igual de fácil. Perl perimite usar el FILEHANDLE entre los símbolos (<>) para sustituir a la próxima línea del fichero.

Así pues, podemos poner algo como esto:

$linea = ;

Así leeremos una línea del fichero apuntado por GB, y avanzará el puntero a la siguiente línea automáticamente. Esto significa que la siguiente sentencia como esta leerá la siguiente línea. Podremos leer el archivo entero en un bucle, saliendo solo cuando no quede nada más,. Pero hay un modo más fácil, podemos usar un vector. Un vector es una variable, con mucha información que puede ser accedida individualmente. Ya hemos usado arrays asociativos en la construcción $in{'variable'}. Recuerda que se tiene el elemento etiquetado como variable en el vector asociativo $in. Usaremos un vector ordenado numericamente. Esto significa que la información es almacenada en el vector en el orden en la que la ponemos, y podemos referenciar el elemento n-ésimo elemento añadido, donde n es un número cualquiera. Estos vectores son referenciados con el signo @, y se usan de manera similar a los vectores asociativos cuando queremos recuperar un solo elemento de él. El siguiente ejemplo lo explica:

_@pepe # Este es el vector pepe entero, con todos sus elementos $pepe[4] # El el quinto elemento del vector pepe. Notar que

se empieza a contar desde 0, y que por tanto:

$pepe[0] # es el primer elemento del vector. (Igual que en el lenguaje C)_

Perl proporciona un modo rápido para llenar un vector con el contenido de un archivo. Podemos usar la sentencia @vector = . Se leerá cada linea del fichero apuntado por FILEHANDLE, y seran colocados secuencialmente en el vector. Para leer el libro de visitas entero, deberemos usar:

@lineas = ;

No debemos olvidarnos de cerrar el fichero:

close GB;

  1. Vaciar el archivo es muy sencillo. Simplemente debemos reabrirlo para escritura sin añadir. Esto significa usar un ‘>’ en vez de dos. Una vez hecho esto debemos imprimir cada línea del fichero, sustituyendo lo que el usuario escribió justo delante del marcador.

Para llevar a cabo la sustitución usaremos la función s/oldpattern/newpattern/ , que reemplaza el patrón antiguo con el nuevo. La buena noticia es que modemos usar metacaracteres como \n para reemplazar varias líneas. Para que esto afecte a una variable que contiene una cadena usaremos un operador. La sentencia quedará así:

$linea =~ s/oldpattern/newpattern/

Realmente haremos una sustitución en los comentarios, para convertir las nuevas líneas en comandos
, de manera que las líneas queden tal y como el visitante las escribió. Para hacerlo pondremos:

$in{'comentarios'} =~ s/\n/
\n/go;

La g que va detrás del patrón significa que se hará esto para cada línea en la variable, la o significa compilar esta expresión regular de manea que concuerde más rápido. Es bueno hacerlo.

Para realizar la sustitución y añadir los comentarios del usuario para cada línea del vector, usaremos uin bucle foreach. Esto significa para cada elemento de la lista, coloca el elemento en la variable_de_bucle, y ejecuta las sentencias que están entre las llaves ({}). Esto sería:

foreach $variable_de_bucle (lista) { #cosas a hacer }

Queremos insertar el nombre de la persona con su dirección e-Mail entre paréntesis, seguido de sus comentarios. Esto lo incluiremos en un parrafo HTML, seguido de un comando


. No tenemos que olvidarnos de incluir un nuevo marcador <!--INSERTAR AQUÍ>. Lo pondremos primero así las nuevas entradas serán añadidas al principio de la página. Mi codigo será:

open(GB,">/users/jperez/www/tutor/guestbook.html"); foreach $linea (@lineas) { $linea=~ s//\n

Nombre: $in{'nombre'}($in{'email'})
\nComentarios:
\n$in{'comentarios'}</P>\n< HR>\n/o; print GB $linea; } close GB;

print "\n"; print "\n"; print "Mensaje de error\n"; print "\n"; print "\n"; print "\n"; print "

Ha ocurrido un error

\n"; print "\n"; print "

No has completado todos los campos Por favor vuelve a intentarlo.

\n"; print "\n"; print "\n";

# llamda para salir del script. Tenemos un error exit; }

_if ($in{'email'} !~ /\w@\w/) {

No es igual a la expresión regular. Enviar mensaje de error

print &PrintHeader; print "\n"; print "\n"; print "Mensaje de error\n"; print "\n"; print "\n"; print "\n"; print "

Ha ocurrido un error

\n"; print "\n"; print "

Tu dirección email no contiene una @.

\n"; print "\n"; print "\n";_

# llamada para salir ahora del script, tenemos un error exit; }

_$quitar = 0; while ($quitar != 1) { if (-e "/users/jperez/www/tutor/.guestlock") {

El fichero existe, esperamos un momento

sleep(1); } else {_

# Creamos el fichero de bloqueo, de manera que el libro de firmas queda bloqueado. open(LOCK,">/users/jperez/www/tutor/.guestlock"); close LOCK;

_# Abrimos y leemos el antiguo libo de firmas

Nota: Crear una copia de seguridad no sería una mala idea ...

open(GB,"</users/jperez/www/tutor/guestbook.html"); @lineas = ; close GB;_

# Preparamos los comentarios para html $in{'comentarios'} =~ s/\n/
\n/go;

# Vaciamos el libro de firmas antiguo, y lo volvemos a imprimir, añadiendo la nueva entrada open(GB,">/users/jperez/www/tutor/guestbook.html"); foreach $linea (@lineas) {

$linea =~ s//\n

Nombre: $in{'nombre'}($in{'email'})
\nComentarios:
\n$in{'comentarios'}</P>\n< HR>\n/o; print GB $linea; } close GB;

# desbloquear el archivo unlink("/users/jperez/www/tutor/.guestlock");

# Devolver el nuevo libro de firmas, y poner $quitar = 1 print "Location: http://www.ctv.es/users/jperez/www/tutor/thanks.html\n\n"; $quitar = 1; } }

Nota sobre el bloqueo de archivos:

El mecanismo de bloqueo de archivos usado arriba, no es perfecto ya que requiere varios pasos para bloquear un archivo. Por ello es posible obtener un bloqueo o desbloqueo falso, aunque es altamanete improbable. Una implementación mejot usara el sistema de ficheros nativo bloqueando, vinculando, o algún otro método atómico. Desconozco si perl simula el bloqueo en sistemas que no implementan el bloqueo de forma nativa. Un método usando vínculos sin comentar sería:

_$quit = 0; while ($quit != 1) { /users/jperez/www/tutor/guestbook.html if (link(/users/jperez/www/tutor/guestbook.html,/users/jperez/www/tutor/.guestlock)) {

Archivo bloqueado, nos detenemos un momento

sleep(1); } else {

Tenemos un bloqueo, hacemos lo que tengamos que hacer

unlink("/users/jperez/www/tutor/.guestlock"); } }_

SCRIPTS CGI QUE ENVÍAN CORREO

En este apartado crearemos un script CGI que envíe correo, y devolvera una página que indique que el correo ha sido enviado. Sin embargo, los conceptos serán bastante geneales para permitir que el script pueda ser adaptado a cualquier proyecto donde sea necesario enviár un correo desde un script. También veremos brevemente como examinar las areas de texto línea por línea.

Como siempre, cuando empezamos, necesitaremos un formulario.

_

_