Neotienda.com

Home

Foros

Favoritos

Sube tu Artículo

Webmaster

 

Buscar  Artículos

laVariable.com

Trucos

 Visual Basic

(72)

 JavaScript (8)
 Visual C++

(6)


Tutoriales

 CSS  nuevo!
 DHTML  nuevo!
 Java  intermedio
 SQL  básico 
 JavaScript básico 
 JavaScript interm.
 DirectX introducción
 C básico
 Visual C++ básico

Artículos

  ActiveX (2)
  ADO

(10)

  ASP

(27) 

  CGI

(4)

  Tecnologías

(5)

  Java

(6)

  Java Script

(12)

  Visual Basic

(8)

  VBScript

(3)

  Visual C++

(2)

  SQL

(2)

  XML

(8)


RECIBE LAS NOVEDADES



laVariable.com

 


GLOSARIO

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z



   
Viernes 22 de Junio de 2001  04:29:44 PM

23 Usuarios Activos


Tutorial de CGI Cedido por Gabriel Natale

CGI es una norma para establecer comunicación entre un servidor web y un programa, de tal modo que este último pueda interactuar con internet. También se usa la palabra CGI para referirse al programa mismo, aunque lo correcto debería ser script. De todos modos en este tutorial nos interesa aprender a escribir estos programas por lo cúal usaremos la palabra indistintamente, como es costumbre en castellano.

Un CGI (Common Gateway Interface) es un programa que se ejecuta en tiempo real en un Web Server en respuesta a una solicitud de un Browser. Cuando esto sucede el Web Server ejecuta un proceso hijo queo recibirá los datos que envía el usuario (en caso de que los haya), pone a diposición del mismo algunos datos en forma de variables de ambiente y captura la salida del programa para enviarlo como respuesta al Browser.

El propósito de los CGI´s es proveer "inteligencia" e interactividad a un sitio web, por ejemplo encontrar un sitio en Yahoo utilizando solo los links que se proveen puede ser una labor frustrante, sin embargo usar el formulario y solicitar una busqueda personalizada suele frustrarnos (un poco) menos, ya que un CGI nos provee de una respuesta hecha a la medida (eso dice la teoría) de nuestra consulta.
Existen otras herramientas para lograr esto en cierta medida, tales como Server Side Includes o JavaScript, no es el proposito de este tutorial tocar en profundidad estos temas.

Lenguajes

Aunque un CGI se puede programar en cualquier lenguaje soportado por el sistema operativo del servidor, usaremos el lenguaje C para nuestros ejemplos (excepcionalmente se tocarán algunos otros lenguajes).
Esto es porque un ejemplo en C podrá ser fácilmente portado a casi cualquier sistema operativo.

Nota:
Si escribes CGIs para IIS (Windows NT), debes asegurarte de compilarlos en modo 32 bits, de otro modo no funcionarán.
Además no es una buena idea usar programas .exe sino más bien usar DLLs Dynamic Link Libraries que corren mucho más rápido.

Otro lenguaje popular para escribir CGI´s es el Perl, el cúal es interpretado y al igual que el C es altamente portable entre sistemas operativos.

Los ejemplos de código los haré lo mas claros posibles, por ejemplo en vez de usar un código como:

int main(){
FILE *fp;
if ( (fp = fopen("algo.dat","rb"))==NULL ) exit(1) else algo();
return(0);
}

preferiré uno algo más largo pero también más claro como:.

int main(){
FILE *fp;
fp = fopen("algo.dat","rb");
if( fp == NULL )
{
exit(1);
}else{
algo();
}
return ( 0 );
}

Servidor

Este sitio se encuentra funcionando sobre un servidor Apache cuya configuración particular obliga a que la extensión de los cgis sea .cgi, esto puede variar en el caso de tu webserver. Te sugiero que contactes a tu webmaster para que te indique que extensiones, lenguajes y directorios están a tu disposicion para ejecutar CGI´s.

HolaMundo

Cómo tienes algunos conocimientos de programación, haremos juntos el ejemplo básico de todo curso, el programa "Hola Mundo".

Como resultado obtendremos una página html que dirá solamente eso, "Hola Mundo".
Al igual que en casi todo lenguaje de programación este programita es muy sencillo.

El código básico en lenguaje C es:

  /* Programa Hola Mundo */
  /* Autor: Juan Manuel Doren */
  /* Compilar en unix con: gcc -i hola.c -o hola.cgi */

  int main(){
      
    printf("Content-Type: text/html\n\n");
    printf("<html>Hola Mundo</html>\n");

    return( 0 );

  }
  
Ejecutando este programa desde un browser se obtendrá una página conteniendo.
<html>Hola Mundo</html>
Sin embargo como puedes notar en el código hay una primera línea que debería imprimir:
Content-Type: text/html

La salida de esta primera línea de código es efectivamente recibida por el browser y le indica que tipo de información viene enseguida. Un CGI puede enviar código html, imágenes, sonido y en general cualquier tipo de archivo que se usa en Internet y es esta línea la que indica al browser como debe interpretar los datos que recibirá.

Adicionalmente el browser recibe otra información como largo de los datos o cookies que se desean grabar, todo esto en forma de un encabezado que no será visible. El final de este encabezado está marcado por dos retornos de carro ("\n\n") siguiendole inmediatamente los datos.

Un documento html típico recibido por un browser puede verse así:

HTTP/1.0 200 OK
Date: Fri, 08 May 1998 19:18:41 GMT
Server: Apache/1.2.5 mod_perl/1.07
Last-Modified: Tue, 07 Apr 1998 19:22:57 GMT
ETag: "7807b84a-1d52-352a7d11"
Content-Length: 7506
Accept-Ranges: bytes
Content-Type: text/html
X-Pad: avoid browser bug

<HTML>
  [ ... etc. ]

Por el momento, al construir un cgi solo será necesario preocuparse de la línea destacada en rojo ya que las demás son colocadas por el browser indicando entre otras cosas que protocolo usa, la fecha del documento (así sabe el browser si bajarlo o usar alguna versión guardada en el caché), el largo de los datos (así el browser puede indicarnos el porcentaje que ya ha bajado) y otra información que no nos interesa de momento.

Algunos de los encabezados mas frecuentes son:

Encabezado Significado
text/html Documento html
Location: url Desvia al visitante a otra dirección
image/gif Imágen del tipo: .gif
text/plain Documento de Texto
image/jpeg Imágen del tipo: .jpeg .jpg .jpe
audio/x-wav Sonido .wav
audio/midi Sonido .mid
video/mpeg Video .mpeg .mpg .mpe
video/quicktime Video Quicktime .qt .mov
video/x-msvideo Video .avi
video/x-sgi-movie Video .movie
audio/basic Sonido .au .snd
application/zip Archivo .zip
application/msword Archivo Word .doc
application/msexcel Planilla Excel .xls
audio/x-pn-realaudio (Real)Audio .ram .ra
"Espiando" al visitante

En este capítulo analizaremos como puede un CGI recibir información desde el mundo externo.

Aparte de lo que tradicionalmente puede obtener un programa desde el sistema operativo un CGI recibe información en dos formas diferentes.

  • i) Datos que el Browser envía al Servidor Web y que a su vez tienen dos componentes
    • Datos de sí mismo y de la conexión (son enviados siempre).
    • Datos ingresados en un form o pasados como parametros (Solo si existen).
  • ii) Datos que el Servidor Web pone por defecto a disposición del CGI con información sobre sí mismo.

En este capítulo nos concentraremos en los datos que siempre son pasados al CGI y la manera de recogerlos.

Algunos de estos datos son:

HTTP_REFERER Documento que está solicitando el CGI.
HTTP_USER_AGENT Browser que está usando el visitante.
HTTP_USER_OS Sistema operativo está usando el visitante.
REMOTE_HOST Nombre del equipo que esta pidiendo el cgi (habitualmente el Módem del ISP que está usando el visitante).
REMOTE_ADDR Dirección IP del visitante.

Cuando un Servidor Web ejecuta un CGI, levanta un proceso hijo con un juego independiente de variables de entorno conteniendo estos datos.

La manera de leer estos datos en C es usando la función getenv( char *nombre), en Perl la función $ENV{"NOMBRE"}, y con Server Sides Includes nombre de la variable. Un ejemplo en C se implementa en el programa espia cuyo código (Resumido) es el siguiente:

/* ****************************
   Programa Espia
   Autor: Juan Manuel Doren
   Compilar en unix con: gcc -i espia.c -o espia.cgi
   **************************** */

#include <stdlib.h>

void imprimeVariable( char *Nombre );

int main(){     
/* *********************************** */

   printf("Content-Type: text/html\n\n");

   printf("<html><body bgcolor=#ffffff text=#ffffff>\n");

   printf("<p align=center><table cellpadding=4 bgcolor=000000>\n");
   printf("<tr><td color=000080 align=center>");
   printf("<b>Variables del Sistema</b></td></tr>\n");

   imprimeVariable("REMOTE_ADDR");
   imprimeVariable("REMOTE_HOST");

   printf("</table>\n");
   printf("</body></html>");

   return( 0 );
}


void imprimeVariable( char *Nombre ){
/* *********************************** */

printf("<tr>\n");
printf("<td bgcolor=\"#9999FF\" valign=top>%s</td>\n",Nombre);
printf("<td bgcolor=\"#DDDDFF\" valign=top><font color=#000000>");

printf("%s",getenv(Nombre));

printf("</td>\n");
printf("</tr>\n");
}

El programa utiliza el mismo metodo visto en el Capítulo 1 para generar una página HTML. La función imprimeVariable() recibe como parámetro el nombre de la variable que se desea mostrar, imprime el código HTML necesario para formatear la salida y mediante una invocación a getenv(Nombre) recupera el valor que se solicita.
En algunos casos las variables no devuelven nada.

Procesamiento de Formularios

Una de las funciones más importantes de los cgis es el proceso datos ingresados por el visitante mediante rellenar un formulario. Es el propósito de este capítulo entregar las herramientas necesarias para poder recibir estos datos.

El CGI puede recibir el contenido de un formulario de dos maneras básicas:

  • Mediante la variable de ambiente QUERY_STRING
  • Mediante la entrada éstandar en cuyo caso la variable de ambiente CONTENT_LENGTH nos indicará el largo del string que deberemos leer.

Cúal de las dos formas se usa dependerá del método que se haya seleccionado en el parametro method del tag form del documento HTML.

Para enterarnos de cúal de método fúe usado se deberá consultar la variable de ambiente REQUEST_METHOD que contendrá GET o PUT según sea el caso.

Nota:

Las principales diferencias entre ambos metodos se ve en esta tabla:

GET POST
El CGI lo recibe por medio de una variable de entorno lo que significa una restriccion en el tamaño de los datos. El CGI lo recibe por medio de la entrada estandard (como si fuera teclado) lo que significa virtualmente recibir cualquier tamaño de datos.
El Browser envía los datos visiblemente haciendo una llamada de la forma: .../cgi-bin/cgi.pl?campo=algo
Es la forma como se llaman cgis desde fuera de un formulario, por ejemplo los contadores de visitas son habitualmente llamados de la forma:
<img
src="Count.cgi?df=cgimaster2">
siendo el resultado:
El Browser envia los datos directamente al CGI por lo cual no se ven en el browser (ideal para campos ocultos)

En ambos casos se recibe un string con pares ordenados en la forma:
nombre=valor separados por un signo &
los espacios serán pasados como un signo más (+) y los caráctes especiales (incluyendo el espacio) en la forma:
%valor hexadecimal

Por ejemplo el string: mañana comeré será recibido como: ma%F1ana+comer%E9

Para ilustrar como procesar estos datos usaremos el programa  que muestra el contenido de los datos pasados desde el browser.

#include <stdio.h>
#include "cgiforms.h"
#define LARGO_MAXIMO 1024

void imprimeVariable( char *lpzNombre );


main(){
/* **** */
   printf("Content-Type: text/html\n\n");

   printf("<html><body bgcolor=#ffffff text=#ffffff>\n");

   printf("<p align=center><table cellpadding=4 bgcolor=000000>\n");
   printf("<tr><td color=000080 align=center>");
   printf("<b>Campos recibidos desde el Form</b></td></tr>\n");

   imprimeVariable( "nombre" );
   imprimeVariable( "color" );
   imprimeVariable( "pais" );
   imprimeVariable( "preferencia" );
   imprimeVariable( "marca" );

   printf("</table>\n");
   printf("</body></html>");

   return( 0 );
}



void imprimeVariable( char *lpzNombre ){
/* *************************************
recibe el nombre de la variable y
la imprime formateada como celdas de
una tabla
************************************* */
   char lpzResultado[LARGO_MAXIMO];

   printf("<tr>\n");
   printf("<td bgcolor=\"#9999FF\" valign=top>%s</td>\n",Nombre);
   printf("<td bgcolor=\"#DDDDFF\" valign=top><font color=#000000>");


/*
   *********************
   aqui pide la variable
   y luego la imprime
   *********************
*/

   formPideVariable( lpzNombre,lpzResultado,LARGO_MAXIMO);
   printf(¨[%s]",lpzResultado);

   printf("</td>\n");
   printf("</tr>\n");

}

Generación de imágenes

En este capítulo se analizará como enviar una imagen desde un cgi y posteriormente, como generarlas a voluntad.
El protocolo para el envío de imágenes no varía notablemente en relación al envío de otro tipo de documentos al browser. Primero ha de enviarse un header indicando el tipo de documento que enviaremos y luego byte a byte, el documento (imagen) en cuestión.

A continuación se muestra el código del programa lanzagif.c el cual ilustra el uso de la función lanzaGif que nuestra un gif almacenado en el disco, la función no modifica para nada la imagen y puede ser usado para mostrar alguna imagen aleatoriamente (yo lo uso en Minibanner).

 #include <stdio.h>

void lanzaGif( char *NombreGif );
main(){
    lanzaGif("ejemplo.gif");
}


void lanzaGif( char *NombreGif ){
/* *************************************************************
   envia una imagen leyendola del archivo NombreGif

**************************************************************** */

#define GIF_BUFF_SIZE 2048

FILE         *fp;
int          buff[GIF_BUFF_SIZE];
int          leido = GIF_BUFF_SIZE;

fp = fopen(NombreGif,"rb");   
if ( fp != NULL )
{
    printf( "Content-type: image/gif\n\n");   /* Este es el header de un gif */ 

    while ( leido == GIF_BUFF_SIZE ){
       leido = fread(&buff,1,GIF_BUFF_SIZE,fp);
       if (leido)
       {
          fwrite(&buff,1,leido,stdout);   /* lanza lo leido por
                                                        la salida standard */
       }
    }
     fclose(fp);
}
}

El resultado del programa lo ves en la imagen a continuación. (El código html para la inclusión del cgi es:
<img src=lanzagif.cgi>

 

Ahora tenemos dos formas de generar un gif, una es estudiando la estructura interna de un gif y lanzando 1 a 1 los bytes que lo compondrían o utilizar alguna librería para lograr lo mismo. Como el propósito de este tutorial no es profundizar el formato de archivos gifs nos remitiremos a usar GD una popular libreria disponible gratuitamente en internet.
Para eso desarrollaremos un pequeño ejemplo que no pretende ahondar en el uso de la mencionada librería sino mostrar la base de la generación de imágenes.

Generación de imágenes usando GD

Para ilustrar el uso de la libreria GD construiremos un peque&ntildeo "juego", llamado Kill Nikita y que trata de disparar con el Mouse a la Femme Nikita.
El juego se basa en un CGI que recibe como parametros las coordenadas del click y dibuja un círculo rojo en aquellas coordenadas.
El código del programa se lista a continuación

 

#include
#include "gd.h"
#include "gdok.c"
#include "cgiforms.h"

int main(void)
{

        int  i;   
FILE *in;           /* Archivo Gif de Entrada  */
gdImagePtr im_out;  /* Imagenes de entrada y salida */

        char lpzX[5];        /* coordenadas del disparo */
        char lpzY[5];
        int  X = 0;   int  Y = 0;


gdImagePtr brush;   /* pincel y colores */
int rojo;  int blanco;



        formPideVariable( "x",lpzX,4);    /* lee las coordenadas */
        formPideVariable( "y",lpzY,4);

        if (lpzX[0])
        {
           X = atoi(lpzX);
        }

        if (lpzY[0])
        {
           Y = atoi(lpzY);
        }

in = fopen("nikita.gif", "rb");   /* crea el gif a partir de uno existente */
im_out = gdImageCreateFromGif(in);

rojo   = gdImageColorAllocate(im_out, 255, 0, 0);  /* crea los colores */
blanco = gdImageColorAllocate(im_out, 255, 255, 255);        


        if ( (X > 0) && (Y > 0) )                          /* Si hay disparo */
        {
           gdImageArc(im_out, X, Y, 15, 15, 0, 360, rojo);  /* Dibuja el disparo */
           gdImageArc(im_out, X, Y, 14, 14, 0, 360, rojo);   /* Lo pinta */
           gdImageArc(im_out, X, Y, 13, 13, 0, 360, rojo);  
           for ( i=12;i>10;i--)
           {
              gdImageArc(im_out, X, Y, i, i, 0, 360, blanco);
           }
           for ( i=10;i>0;i--)
           {
              gdImageArc(im_out, X, Y, i, i, 0, 360, rojo);
           }

        }


        printf("Content-type: image/gif\n\n");   /* Headers */
gdImageGif(im_out, stdout);               /* Salida Estandard */

fclose(in);                      /* cierra archivos */
gdImageDestroy(im_out);         /* libera memoria */


return 0;
}

Como se observa se han usado las rutinas de la librería GD para dibujar el disparo. Hemos usado además otro cgi que lanza el có:digo HTML y usa un form para poder pasar las coordenadas a una segunda llamda a sí mismo.
La forma de usar el form es
<form method=get action=nikita.cgi><input type=image src="shownikita.cgi?x=&y="width=181 height=310 border=0>

No nos detendremos a analizar las rutinas GD ya que estas vienen bastante bien documentadas con la librería

 
 

Neotienda.com

Copyright © 2000 laVariable.com - Todos los derechos reservados.