Documente Academic
Documente Profesional
Documente Cultură
Curso 2012/2013
Fco. Javier Muoz Calle Francisco Jos Fernndez Jimnez Jos ngel Gmez Argudo Ignacio Campos Rivera
-I-
NDICE
Objetivos y alcance (5 minutos) ...................................................................................................... 3 1.1 1.2 1.3 1.4 1.5 Introduccin............................................................................................................................. 3 Objetivo de la prctica ............................................................................................................. 4 Planificacin de la prctica...................................................................................................... 4 Documentacin de apoyo ........................................................................................................ 4 Preparacin del entorno de trabajo .......................................................................................... 4
CGI (50 minutos)............................................................................................................................. 6 2.1 2.2 Introduccin (2 minutos) ......................................................................................................... 6 Programando en CGI (8 minutos) ........................................................................................... 8 Variables de entorno ........................................................................................................ 8 Formularios ................................................................................................................... 11 Ejercicios propuestos (40 minutos) ....................................................................................... 12 Ejercicio1: CGI y Shell Script ....................................................................................... 12 Ejercicio2: CGI y Lenguaje C ....................................................................................... 13 Ejercicio3: CGI y Lenguaje Java ................................................................................... 15
PHP (190 minutos) ........................................................................................................................ 17 3.1 3.2 3.3 Introduccin........................................................................................................................... 17 Preparacin del entorno ......................................................................................................... 18 PHP Bsico (110 minutos) .................................................................................................... 18 Introduccin................................................................................................................... 18 Ejemplos (60 minutos) .................................................................................................. 18 Ejercicios propuestos (50 minutos) ............................................................................... 34
Usos prcticos de PHP (80 minutos) ..................................................................................... 36 Introduccin................................................................................................................... 36 Ejercicios propuestos ..................................................................................................... 36
3.4.1 3.4.2 4
-1-
Introduccin (5 minutos) ....................................................................................................... 56 Preparacin del entorno (5 minutos) ..................................................................................... 57 Tomcat (5 minutos) ............................................................................................................... 58 Programando en JSP (40 minutos) ........................................................................................ 59 Insercin de cdigo Java (5 minutos) ............................................................................ 59 Directivas (5 minutos) ................................................................................................... 61 Invocacin de clases Java desde JSP: Javabeans (10 minutos) ..................................... 62 Objetos implcitos (10 minutos) .................................................................................... 67 Formularios HTML y pginas JSP (5 minutos)............................................................. 71 Sesiones (5 minutos) ..................................................................................................... 72
6 7
Ejemplo de Test (5 minutos) ......................................................................................................... 81 Anexo I .......................................................................................................................................... 84 7.1 7.2 Instalacin de Tomcat ........................................................................................................... 84 Instalacin de Apache ........................................................................................................... 85
-2-
-3-
-4-
Para acceder a las URLs comentadas, es necesario arrancar los servicios correspondientes para servir las webs de forma adecuada. En este caso, solamente es necesario arrancar el servidor Web Apache. Para la interpretacin de pginas JSP, tambin es necesario arrancar el servidor contenedor de servlets Tomcat. El anexo I describe el proceso de instalacin, configuracin e integracin de los servidores Apache y Tomcat. Realice las siguientes acciones para arrancar el servidor Apache y descomprimir los ficheros necesarios para realizacin de esta prctica. Hasta la seccin dedicada a JSP, no es necesario arrancar el servidor Tomcat. IMPORTANTE: Para la realizacin de la prctica, utilice el usuario afast.
NOTA: durante el desarrollo de la prctica puede emplear el editor o IDE (entorno de desarrollo integrado: Eclipse, etc.) que estime oportuno para abrir/editar los ficheros correspondientes.
-5-
La mayora de los servidores esperan que los programas y scripts CGI residan en un directorio especial, normalmente llamado cgi-bin, y/o que tengan una cierta extensin de fichero. En el caso de Apache, hemos de configurarlo para que permita la ejecucin de scripts CGI. Hay varios mtodos para hacer esto, y puede consultar el Anexo I para examinar cmo se ha hecho para esta prctica. En la configuracin de Apache, se han habilitado los directorios /home/afast/web/ y /home/afast/web/cgi-bin/ al efecto. Para la fase de despliegue de ficheros CGI en el servidor, puede ubicar en estos directorios los scripts correspondientes, y acceder a las URLs siguientes: http://localhost/afast/, y http://localhost/afast/cgi-bin/, respectivamente.
-6-
a) La primera, que toda la salida de un programa CGI debe ser precedida de una cabecera de tipo MIME. Esta es una cabecera que le dice al navegador Web qu tipo de contenido est recibiendo, y suele tener una forma como esta:
Content-type: text/html
b) La segunda, que la salida ha de ser cdigo HTML, o algn tipo de formato que el navegador sea capaz de mostrar: una imagen, etc. A parte de estas dos cosas, escribir un programa CGI es similar a la sintaxis de cualquier otro lenguaje conocido, empleado en el propio CGI. Veamos un ejemplo de un programa CGI que imprime una lnea en el navegador:
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "Hello, World.";
Lo anterior es un ejemplo de script escrito en Perl, un lenguaje interpretado. La primera lnea (shebang) le dice a Apache que este script ha de ser ejecutado enviando el fichero al intrprete que se encuentra en /usr/bin/perl. La segunda lnea imprime la declaracin content-type, seguido por dos pares de retornos de carro y nueva lnea. Esto imprime una lnea en blanco despus de la cabecera, para indicar el fin de las cabeceras HTTP, y el comienzo del cuerpo de la pgina Web. La tercera lnea del script imprime Hello, World.
Por otro lado, hay que destacar que los programas CGI han de tener permiso de ejecucin para un usuario distinto a afast (afast es el propietario del fichero, pero quien lo ejecuta puede ser el usuario de Apache o un usuario distinto). Por tanto, hay que ejecutar una orden como la siguiente para dar permisos de ejecucin a los scripts CGI:
chmod a+x script.cgi
As mismo, si el programa lee o escribe a otros ficheros, estos ficheros necesitan tener los permisos adecuados para permitir esto. La mayor parte de la peticin de un programa CGI es la misma que la peticin de cualquier otra pgina web. La diferencia es que cuando el servidor reconoce que la direccin pedida es un programa CGI, el servidor no devuelve los contenidos del fichero, sino que intenta ejecutar el programa. La peticin del cliente tambin pasa los formatos de datos que puede aceptar (www/source, text/html, and image/gif, etc.), se identifica con el User_Agent y enva la informacin de usuario
-7-
correspondiente. Toda esta informacin est disponible desde el programa CGI, junto con informacin adicional del servidor. La forma en que los programas CGI consiguen la informacin de entrada depende del servidor y el sistema operativo del mismo. En un sistema UNIX, como es el caso de las prcticas, los programas CGI consiguen su entrada desde la entrada estndar (STDIN) y desde las variables de entorno UNIX. Estas variables almacenan esta informacin: la cadena de bsqueda de entrada (en el caso de un formulario), el formato de la entrada, la longitud de la entrada (en bytes), el host remoto y el usuario que enva la entrada, y otra informacin del cliente. Tambin almacenan el nombre del servidor, el protocolo de comunicacin y el software que se ejecuta en el servidor. Una vez que el programa CGI comienza a ejecutarse, puede crear y enviar su salida a una nueva pgina web, o proporcionar la URL a una existente. En UNIX, los programas envan su salida a la salida estndar (STDOUT) como un flujo de datos. Este flujo de datos est formado por dos partes: la primera parte es una cabecera HTTP completa o parcial que, como mnimo, describe el formato de los datos devueltos (HTML, texto plano, imagen gif, etc.). Posteriormente, una lnea en blanco que significa el fin de la cabecera. La segunda parte es el cuerpo, que contiene los datos que conforman el tipo de datos reflejado en la cabecera. Veamos ahora algunos ejemplos y ejercicios propuestos.
-8-
echo echo echo echo echo echo echo echo echo echo echo exit
"<hr/><pre>" "Nombre Servidor: "Puerto: "Software: "Software: "Protocolo: "Revision CGI: "Directorio raiz: "Info.pasada a GET: "<hr/></pre>" "</body></html>" 0
Observe el contenido del programa CGI escrito en shell script, en especial en la sentencia que imprime el tipo de contenido que dar lugar a la salida del CGI (doble retorno de carro y nueva lnea). En este momento no se pide ninguna modificacin ni creacin de ficheros con cdigo, lo que correspondera a la fase de desarrollo (y pruebas) de la aplicacin web, pues estamos mostrando un ejemplo ya creado y probado. Ahora vendra la fase de despliegue en el servidor Web, la cual s vamos a realizar. Para ello, siga los pasos que se detallan a continuacin:
-9-
a) Ya hemos dicho que hemos habilitado Apache para poder llamar a programas CGI desde los directorios /home/afast/web/ y /home/afast/web/cgi-bin/, aunque el directorio cgi-bin no est creado; ejecute los siguientes comandos en una ventana de terminal para crearlo y conceder los permisos adecuados (recuerde: permisos de ejecucin para directorios, de lectura para ficheros contenidos en esos directorios y de lectura y ejecucin para ficheros que necesiten permisos de ejecucin, como los programas CGI): cd $WEB/ mkdir cgi-bin chmod 711 cgi-bin TAREAS b) Copie el fichero ejemplo1.sh en el directorio anterior (opcin -p copia preservando permisos y propietario): cp -p /home/afast/p07/cgi/ejemplo1.sh $WEB/cgi-bin/ c) Vaya ahora a la ventana de terminal, acceda al directorio /home/afast/web/cgibin y conceda permisos de ejecucin al programa CGI a ejecutar: cd $WEB/cgi-bin/ chmod 755 ejemplo1.sh
Puede examinar las transparencias de teora para encontrar informacin sobre el resto de variables de entorno no expuestas aqu. Tambin puede probar con algunas de estas variables para ver el valor que toman en tiempo de ejecucin: REQUEST_METHOD, PATH_INFO, PATH_TRANSLATED, SCRIPT_NAME, REMOTE_HOST, REMOTE_ADDR, AUTH_TYPE, REMOTE_USER, REMOTE_IDENT, CONTENT_TYPE, CONTENT_LENGTH, HTTP_ACCEPT, HTTP_USER_AGENT, HTTP_REFERER.
-10-
2.2.2 Formularios
Ahora vamos a ver algunos ejemplos relacionados con formularios HTML, y su interaccin con programas CGI. Ya hemos visto en el apartado anterior el paso de parmetros mediante el mtodo GET (recuerde que GET y POST son los mtodos disponibles para el paso de informacin en un formulario HTML desde el lado cliente al servidor). Abra ejemplo2.html y observe su contenido: /home/afast/p07/cgi/ejemplo2.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head><title>Formulario HTML y CGI</title></head> <body> <form action="http://localhost/afast/cgi-bin/ejemplo2.out" method="GET"> <div><label>Multiplicando 1: <input name="m" size="5"></label></div> <div><label>Multiplicando 2: <input name="n" size="5"></label></div> <div><input type="submit" value="Multiplica"></div> </form> </body> </html>
Tambin sera posible emplear el mtodo POST, pero habra que realizar un mayor procesamiento del cuerpo de la respuesta. Abra ahora ejemplo2.c (con el editor de C/C++) y analice su contenido: /home/afast/p07/cgi/ejemplo2.c
#include <stdio.h> #include <stdlib.h> int main(void) { char *datos; long m,n; printf("Content-Type:text/html\n\n"); printf("<html>\n<head>\n"); printf("<title>Resultado de la multiplicacion</title>\n"); printf("</head>\n<h1>Resultado de la multiplicacion:</h1>\n"); printf("<body>\n"); datos = getenv("QUERY_STRING"); if(datos == NULL) printf("<p>Error pasando datos desde el formulario al prog. CGI</p>"); else if(sscanf(datos, "m=%ld&n=%ld", &m, &n)!=2) printf("<p>Error: los datos deben ser numericos.</p>"); else printf("<h3>El producto de %ld y %ld es %ld.</h3>", m, n, m*n); printf("</body>\n"); printf("</html>\n"); return 0; }
-11-
Para probar el ejemplo, realice las siguientes acciones: a) Copie el fichero ejemplo2.html a /home/afast/web/. b) Cree ahora el siguiente directorio para los ficheros de cdigo fuente: mkdir /home/afast/web/cgi-bin/sources chmod 700 /home/afast/web/cgi-bin/sources c) Copie el fichero ejemplo2.c al directorio destino /home/afast/web/cgibin/sources. TAREAS d) Ahora, abra una ventana de terminal y ejecute lo siguiente para compilar el programa CGI escrito en C y dar permisos adecuados: cd $WEB/cgi-bin/sources/ gcc -g -o ../ejemplo2.out ejemplo2.c cd .. chmod 755 ejemplo2.out
e) Abra un navegador y acceda a la direccin http://localhost/afast/ejemplo2.html. f) Rellene el formulario y compruebe los resultados.
/home/afast/p07/cgi/ejercicio1.sh
#!/bin/bash echo -e "Content-type: text/html\n\n" echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" echo "<html>" # ...
-12-
a) Complete el cdigo de ejercicio1.sh. TAREAS b) Ubique el script en el directorio correspondiente para su ejecucin mediante CGI. c) Abra un navegador y acceda a la direccin propuesta: http://localhost/afast/cgi-bin/ejercicio1.sh?IPcompaero
/home/afast/p07/cgi/ejercicio2.c
#include <stdio.h> #include <stdlib.h> #define MAXLEN 80 #define DATAFILE "/home/afast/web/datos_alumno.txt" int main(void) { char *lenstr; char input[MAXLEN]; long len; FILE *fout; int error; printf("Content-Type:text/html\n\n"); printf("<html>\n<head>\n"); printf("<title>Ejercicio 2: Formulario CGI y Leng. C</title>\n"); printf("</head>\n<body>\n"); lenstr = getenv("CONTENT_LENGTH");
-13-
if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len >= MAXLEN) { // ... } else { if ((fout = fopen(DATAFILE, "w")) == NULL) { // ... error=1; } else { fgets(input, len+1, stdin); //... error=0; } } printf("</body>\n"); printf("</html>\n"); return error; }
a) Complete el cdigo de los ficheros ejercicio2.html y ejercicio2.c. b) Copie los ficheros a los directorios correspondientes: ejercicio2.html al directorio $WEB/ ejercicio2.c al directorio $WEB/cgi-bin/sources/
TAREAS
c) Compile el fichero fuente y proporcione los permisos adecuados desde una ventana de terminal: cd $WEB/cgi-bin/sources/ gcc -g -o ../ejercicio2.out ejercicio2.c cd .. chmod 755 ejercicio2.out touch /home/afast/web/datos_alumno.txt chmod a+w /home/afast/web/datos_alumno.txt
-14-
/home/afast/p07/cgi/ejercicio3.java
public class ejercicio3 { public static void main(String[] args) { // ... Codigo Java System.out.println ("Content-Type: text/html\n" + "\n" + "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" + "<html>\n" + "<head><title>CGI y Java</title></head>\n" + "<body>\n" + // ... Codigo Java "</body>\n</html>\n"); // ... Codigo Java } }
/home/afast/p07/cgi/ejercicio3.sh
#!/bin/sh java ejercicio3 exit 0
-15-
a) Complete el cdigo de ejercicio3.html y ejercicio3.java (puede reutilizar ejercicio2.html cambiando la URL de la accin del formulario). b) Copie los ficheros a los directorios correspondientes: TAREAS ejercicio3.html al directorio $WEB/ ejercicio3.java al directorio $WEB/cgi-bin/sources/ ejercicio3.sh al directorio $WEB/cgi-bin/
c) En una ventana de terminal ejecute lo siguiente para compilar el fichero java y proporcionar los permisos adecuados: cd $WEB/cgi-bin/sources/ javac ejercicio3.java -d ../ cd .. chmod 755 ejercicio3.sh touch /home/afast/web/datos_alumno.txt
-16-
Requisitos para esta seccin: haber estudiado las transparencias de teora (seccin de PHP).
-17-
-18-
<html lang="es"> <head> <title>Tabla de multiplicar</title> <link rel="stylesheet" type="text/css" href="estilo.css"/> </head> <body> <h1>Tabla de multiplicar</h1> <?php $n = 7; print ("<p>La tabla de multiplicar del $n es:</p>\n"); for ($i=1; $i<=10; $i++) print ("$n x $i = " . $n*$i . "<br/>\n"); ?> </body> </html>
TAREAS
a) Abra el fichero ejemplo1.php, que se encuentra dentro del directorio basico, y analice su contenido. Tambin puede inspeccionar el contenido del fichero estilo.css, que se emplear en los siguientes ejercicios. b) A continuacin, abra un navegador y acceda a la siguiente direccin:
http://localhost/afast/PHP/basico/ejemplo1.php.
-19-
while ($i<12 and !$enc) { if ($i == $mes-1) $enc = true; else $i++; } return ($meses[$i]); } ?> </head> <body> <h1>Tablas y funciones</h1> <?php $dia $mes $anyo print "<BR>\n"); ?> </body> </html> = date ("j"); = date ("n"); = date ("Y"); ("Hoy es " . $dia . " de " . nombreMes($mes) . " de " . $anyo .
TAREAS
a) Abra el fichero ejemplo2.php y analice su contenido. b) A continuacin, abra un navegador y acceda a la siguiente direccin:
http://localhost/afast/PHP/basico/ejemplo2.php.
Observe los siguientes fragmentos de cdigo, que muestran cmo utilizar tablas multidmensionales:
<?php $coches = array ( array("Volvo",100,96), array("BMW",60,59), array("Toyota",110,100) ); echo $coches[0][2]; ?>
Resultado: 96
<?php $coches[0][0] = "Volvo"; $coches[0][1] = 100;
-20-
Resultado: 96
<?php $familias = array ( "Lopez"=>array("Pedro","Luis","Maria"), "Martinez"=>array("Pablo"), "Ruiz"=>array("Susana","Lucia","Juan"), array("Javier","Manolo","Cesar"), //indice 0(automtico) array("Fran","Pepe","Julio"), //indice 1(automtico) ); echo "Es " . $familias['Lopez'][2] . " parte de la familia Lopez? Y " . $familias[1][2] . "?"; ?>
-21-
// si no // mostrar formulario // fsi ////////////////////////////////////////////////////////////// // Obtener valores introducidos en el formulario $texto = $_REQUEST['texto']; $donde = $_REQUEST['donde']; $genero = $_REQUEST['genero']; $buscar = $_REQUEST['buscar']; // Comprobar errores $error = false; if (isset($buscar)) { // Texto de bsqueda if (trim($texto) == "") { $errores["texto"] = "Debe introducir el texto de bsqueda!"; $error = true; } else $errores["texto"] = ""; } // Si los datos son correctos, procesar formulario if (isset($buscar) && $error==false) { print ("<H1>Validacin de formularios. Resultados del formulario</H1>\n"); print ("<p>Estos son los datos introducidos:</p>\n"); print ("<ul>\n"); print (" <li>Texto de bsqueda: $texto</li>\n"); print (" <li>Buscar en: $donde</li>\n"); print (" <li>Gnero: $genero</li>\n"); print ("</ul>\n"); print ("<p>[ <a href='ejemplo3.php'>Nueva bsqueda</a> ]</p>\n"); } else { ?> <h1>Validacin de formularios</h1> <h2>Bsqueda de canciones</h2> <form class="borde" action="ejemplo3.php" method="post"> <p> <label for="busqueda">Texto a buscar:</label> <?php print ("<input type='text' id='busqueda' size='40' name='texto'"); if (isset($buscar)) print ("value='$texto'>\n"); else print (">\n"); if ($errores["texto"] != "")
-22-
print ("<br><span class='error'>" . $errores["texto"] . "</span>"); ?> </p> <p> <label for="search">Buscar en:</label> <input type="radio" name="donde" value="titulo" id="search">Ttulos de cancin</input> <input type="radio" name="donde" value="album" id="search">Nombres de lbum</input> <input type="radio" name="donde" value="ambos" checked id="search">Ambos campos</input> </p> <p> <label for="gen">Gnero musical:</label> <select name="genero" id="gen"> <option selected>Todos</option> <option>Acstica</option> <option>Banda Sonora</option> <option>Blues</option> <option>Electrnica</option> <option>Folk</option> <option>Jazz</option> <option>New Age</option> <option>Pop</option> <option>Rock</option> </select> </p> <p> <input type="submit" name="buscar" value="Buscar" /> </p> </form> <?php } ?> </body> </html>
-23-
a) Abra el fichero ejemplo3.php y analice su contenido. Observe el uso de la etiqueta HTML "label". b) Pruebe a abrir un navegador y acceda a la direccin: TAREAS http://localhost/afast/PHP/basico/ejemplo3.php. c) Realice la siguiente modificacin: elimine la clave checked de la seccin Buscar en del formulario. Ha de validar que el radio-button es seleccionado por el usuario. Si estuviese vaco, se debe mostrar el formulario con el error, de forma similar a como se hace en el caso del Texto a buscar.
En el momento de subir el fichero se crean las siguientes variables: $_FILES["file"]["name"]: nombre del fichero subido. $_FILES["file"]["type"]: tipo del fichero. $_FILES["file"]["size"]: tamao en Kbytes. $_FILES["file"]["tmp_name"]: nombre de la copia temporal del fichero almacenado en el servidor. $_FILES["file"]["error"]: error en la subida (0 si no error).
-24-
El fichero temporal se elimina cuando finaliza el script de PHP: si queremos mantenerlo, es necesario guardar una copia en una ubicacin concreta. El script que procesa el formulario podra tener el siguiente aspecto: upload_file.php
$allowedExts = array("gif", "jpeg", "jpg", "png"); $extension = end(explode(".", $_FILES["file"]["name"])); if ((($_FILES["file"]["type"] == "image/gif") || ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/jpg") || ($_FILES["file"]["type"] == "image/png")) && ($_FILES["file"]["size"] < 20000) && in_array($extension, $allowedExts)) { if ($_FILES["file"]["error"] > 0) { echo "Cdigo de error: " . $_FILES["file"]["error"] . "<br>"; } else { if (file_exists("upload/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " ya existe. "; } else { move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" . $_FILES["file"]["name"]); echo "Almacenado en: " . "upload/" . $_FILES["file"]["name"]; } } } else { echo "Fichero invlido."; }
A continuacin vamos a analizar un ejemplo que muestra cmo subir ficheros a un servidor, cmo controlar su tamao, cmo crear un nombre nico para el fichero y cmo almacenarlo en el lugar deseado. Los ficheros que se suban al servidor (imgenes) se almacenarn en una carpeta llamada img, que ha de crear previamente, antes de acceder a la pgina web. Puede encontrar el cdigo del ejemplo en: /home/afast/web/PHP/basico/ejemplo4.php. No se ha incluido aqu por su extensin.
-25-
a) Cree la carpeta img en el directorio de la pgina web, y conceda permisos de escritura para poder subir los ficheros: cd $WEB/PHP/basico/ mkdir img chmod a+w img b) Abra el fichero ejemplo4.php y analice su contenido. Fjese en las funciones de biblioteca como: trim, is_file o time. Puede acceder a http://www.php.net/manual/es/funcref.php para obtener una descripcin de las mismas (trim en la seccin cadenas, is_file en la seccin sistema de archivos). c) Pruebe a abrir un navegador y acceda a la direccin: http://localhost/afast/PHP/basico/ejemplo4.php. d) Pruebe a no introducir ciertos campos y compruebe las condiciones de error. e) Realice la siguiente modificacin: aada un nuevo campo al formulario, donde el usuario ha de introducir el nombre que quiere que tenga el fichero subido al servidor. Utilizar este nombre para almacenar el fichero en el directorio img.
El parser Expat es un analizador basado en eventos: se centra en el contenido de los documentos XML, no en la estructura. Por esta razn, los parsers basados en eventos pueden acceder a los datos ms rpidamente que los parsers basados en rbol. Mire la siguiente fraccin de cdigo XML: <from>Pepe</from> Un parser basado en eventos reporta este XML como una serie de tres eventos: Elemento de inicio: from Seccin CDATA de comienzo, valor: Pepe Elemento de cierre: from
TAREAS
-26-
Este ejemplo est bien formado, pero no es vlido porque no hay un DTD (Document Type Definition) asociado con l. Sin embargo, Expat ignora cualquier DTD, pero los documentos XML han de estar bien formados. Analice los siguientes ficheros: /home/afast/web/PHP/basico/ejemplo5.xml <?xml version="1.0" encoding="UTF-8"?> <note> <to>Juan</to> <from>Pepe</from> <heading>Recordatorio</heading> <body>Devolver los libros.</body> </note> /home/afast/web/PHP/basico/ejemplo5.php <?php //Inicializamos el parser XML $parser=xml_parser_create(); //Funcin para emplear al inicio de un elemento function start($parser,$element_name,$element_attrs) { switch($element_name) { case "NOTE": echo "-- Nota --<br />"; break; case "TO": echo "Para: "; break; case "FROM": echo "De: "; break; case "HEADING": echo "Cabecera: "; break; case "BODY": echo "Mensaje: "; } } //Funcin para el final de un elemento function stop($parser,$element_name) { echo "<br />"; } //Funcin para cuando se encuentra un dato function char($parser,$data) { echo $data; } //Especificamos un manejador de elementos
-27-
xml_set_element_handler($parser,"start","stop"); //Especificamos el manejador de datos xml_set_character_data_handler($parser,"char"); //Abrimos el fichero XML $fp=fopen("ejemplo5.xml","r"); //Leemos los datos while ($data=fread($fp,4096)) { xml_parse($parser,$data,feof($fp)) or die (sprintf("XML Error: %s en la linea %d", xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser))); } //Liberamos el parser XML xml_parser_free($parser); ?> a) Abra el fichero ejemplo5.php y analice su contenido. b) Pruebe a abrir un navegador y acceda a la direccin: http://localhost/afast/PHP/basico/ejemplo5.php.
/home/afast/web/PHP/basico/ejemplo6.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang="es"> <head>
TAREAS
-28-
<title>Ejemplo de cookies</title> </head> <body> <h1>Ejemplo de uso de cookie</h1> Introduzca su nombre: <form action="ejemplo6a.php" method="get"> <input type="text" name="nombre"> <input type="submit" value="Enviar"> </form> </body> </html> /home/afast/web/PHP/basico/ejemplo6a.php <?php setcookie("user", $_GET['nombre'], time()+3600,"/",""); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang="es"> <head> <title>Ejemplo de cookies</title> </head> <body> <h1>Ejemplo de uso de cookie</h1> Se ha establecido una cookie de nombre <b>user</b> con el valor: <b><?php print $_GET['nombre']; ?></b> que ser vlida durante 1 hora.<br/> <a href="ejemplo6b.php">Eliminar cookie</a> </body> </html> /home/afast/web/PHP/basico/ejemplo6b.php <?php setcookie("user", "", time()-3600); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang="es"> <head> <title>Ejemplo de cookies</title> </head> <body> <h1>Ejemplo de uso de cookie</h1> Valor de la cookie de nombre <b>user</b>: <b><?php print $_COOKIE['user']; ?></b><br/> </body> </html>
-29-
a) Abra los 3 ficheros anteriores y analice su contenido. TAREAS b) Pruebe a abrir un navegador, acceda a la siguiente direccin, y siga los enlaces: http://localhost/afast/PHP/basico/ejemplo6.html.
c) Por ltimo recargue la ltima pgina (F5), y compruebe que se ha eliminado la cookie.
-30-
<title>Ejemplo de cookies</title> </head> <body> <h1>Ejemplo de uso de sesiones</h1> <?php if(isset($_SESSION['visitas'])) unset($_SESSION['visitas']); echo "visitas = ". $_SESSION['visitas']; session_destroy(); ?> </body> </html>
a) Abra los 2 ficheros anteriores y analice su contenido. TAREAS b) Pruebe a abrir un navegador, acceda a la siguiente direccin y recarge la pgina (F5) varias veces: http://localhost/afast/PHP/basico/ejemplo7a.php.
Las cookies y las sesiones se utilizan para almacenar datos persistentes, pero existen diferencias bsicas: Las sesiones se almacenan en el servidor, mientras que las cookies se almacenan en el cliente. En condiciones normale, las sesiones se cierran cuando el usuario cierra su navegador (almacenar un valor en Base de Datos ayuda a resolver esto). Para las cookies es posible ajustar el tiempo de expiracin. Las sesiones son ms seguras que las cookies, puesto que al estar estas ltimas almacenadas en el equipo del cliente, son susceptibles de ser modificadas.
-31-
<? class Operaciones { var $inicializada=1; var $num1; var $num2; var $suma; var $diferencia; var $producto; var $cociente; var $contador=0; //Constructor function Operaciones ($val1=55,$val2=45){ $this->contador +=1; $c=$this->contador; $this->num1[$this->contador]=$val1; $this->num2[$c]=$val2; $this->suma[$c]=$val1+$val2; $this->diferencia[$c]=$val1-$val2; $this->producto[$c]=$val1*$val2; $this->cociente[$c]=$val1/$val2; } function imprime(){ echo "<table align=center border=1>"; echo "<td>Num1</td><td>Num2</td><td>Suma</td>"; echo "<td>Diferencia</td><td>Producto</td><td>Cociente</td><tr>"; foreach($this->num1 as $clave=>$valor){ $n2=$this->num2[$clave]; $s=$this->suma[$clave]; $d=$this->diferencia[$clave]; $p=$this->producto[$clave]; $c=$this->cociente[$clave]; echo "<td align=center>$valor</td>"; echo "<td align=center>$n2</td>"; echo "<td align=center>$s</td>"; echo "<td align=center>$d</td>"; echo "<td align=center>$p</td>"; echo "<td align=center>$c</td><tr>"; } echo "</table>"; } } //Creamos el objeto $objeto = new Operaciones; for ($i=10;$i>0;$i--){ for ($j=1;$j<11;$j++){ $objeto -> Operaciones($i,$j); } } //Imprimimos los valores $objeto-> imprime(); ?>
-32-
</body> </html>
TAREAS
a) Abra el fichero anterior y analice su contenido. b) Pruebe a abrir un navegador, acceda a la siguiente direccin: http://localhost/afast/PHP/basico/ejemplo8.php.
comando: el comando que ser ejecutado. output: si se especifica este array, ser llenado con cada lnea de la salida del comando. return_var: si se especifica junto con el array, almacena el valor de retorno del comando.
-33-
a) Abra el fichero anterior y analice su contenido. b) A continuacin, ejecute los siguientes comandos desde una ventana de terminal (analice qu se est haciendo): TAREAS echo "prueba" > $WEB/PHP/basico/prueba.txt sudo chown www-data:www-data $WEB/PHP/basico/prueba.txt c) Abra el ejemplo desde el navegador Web para comprobar su funcionamiento.
d) Modifique su contenido para hacer ping al PC de su compaero y mostrar el resultado en
sobre
esta
funcin
desde:
Tambin puede emplear el esqueleto de cdigo contenido en el fichero ejercicio1.php. El resultado debe ser el siguiente:
-34-
NOTA: el contenido de cada celda deber ser la posicin de dicha celda en el tablero (compuesta por el nmero de la fila y la letra de la columna). Para ello puede utilizarse el operador de concatenacin .. Puede emplear como punto de partida el fichero ejercicio2.php.
-35-
El ejercicio deber resolverse implementando 2 ficheros: uno el que contenga el formulario de subida junto con las miniaturas de las imgenes ya subidos (photos.php). Y otro fichero que realice la lgica de la aplicacin, en este caso, la validacin y subida de ficheros (upload.php). A continuacin, se detallan los pasos a seguir.
-36-
se
encuentran
los
ficheros
b) Realice los siguientes pasos para crear el directorio de nombre " upload", que contendr las imgenes subidas al servidor: cd /home/afast/web/PHP/avanzado/ejercicio1/ mkdir upload TAREAS chmod a+w upload
photos.php, el cual se muestra a continuacin. Debe enviar la informacin mediante el mtodo POST a la pgina upload.php (tenga en cuenta el uso de enctype para la subida de ficheros al servidor). A continuacin, analice el cdigo incluido despus del formulario, que recorre el directorio de imgenes y las muestra en el navegador.
/home/afast/web/PHP/avanzado/ejercicio1/photos.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="style.css" /> <title>Subida de fotos</title> </head> <body> <div id="wrapper"> <!--Cabecera header, similar a div, utilizado en HTML5 para que la etiqueta tenga un significado semntico.--> <header> <!-- Tenga en cuenta el uso de enctype para la subida de ficheros al servidor --> <form > ... </form> </header> <section> <h1>Imgenes subidas</h1>
-37-
<?php $directorio=opendir("./upload"); while ($archivo = readdir($directorio)) { if(!is_dir($archivo)) {?> <div class="photo"> <img src="./upload/<?php echo $archivo; ?>" width="200px" /> </div> <?php } closedir($directorio); ?> </section> </div> </body> </html> }
TAREAS
/home/afast/web/PHP/avanzado/ejercicio1/upload.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="style.css" /> <title>Subida de fotos</title> </head> <body> <?php /* cod cod cod cod cod */ $codigos = array( 1 => "el tipo de fichero no es vlido", 2 => "el tamao del fichero es superior a 500 KB", 3 => "existe algn error al transmitir el fichero", = = = = = 1: 2: 3: 4: 5: el tipo de fichero no es vlido el tamao del fichero es superior a 500 KB existe algn error al transmitir el fichero ya existe otro fichero con ese nombre en el servidor EL FICHERO SE HA SUBIDO CON XITO
-38-
4 => "ya existe otro fichero con ese nombre en el servidor", 5 => "el fichero se ha subido con xito" ); $cod = 5; //Comprobar que los tipos de ficheros son los //admitidos (image/gif, image/jpeg, image/png): if ( ... ) {
//Comprobar que el tamao de la imagen es, a lo sumo, //500KB = 51200Bytes if( ... ) { //Comprobar si ha existido algn error con el fichero if ( ... ) { $cod = 3; } else { //Comprobar si existe un fichero con el //mismo nombre. //Ayuda: utilizar la funcion "file_exists", //mas informacin en: //http://www.php.net/manual/es/book.filesystem.php if ( ... ) { $cod = 4; } else { //Mover el fichero al directorio //"upload" con el mismo nombre //del fichero original. ... $cod = 5; } } } else { $cod = 1; //El tamao del fichero excede los 500KB"; } } else { $cod = 2; //El tipo de fichero no es ni GIF ni JPEG ni PNG"; } //Imprimimos en el navegador el resultado de la subida del //fichero, en funcin del cdigo correspondiente del 1 al 5. //El cdigo CSS para el elemento que muestra la informacin de //la subida de fichero correcta ha de ser: //<div class="msg info> // //Y en el caso de subida errnea: <div class="msg error> ...
-39-
TAREAS
Paso 3: aadir un campo de texto en el formulario de subida de fotos. Este campo contendr el nombre que se le ha de dar al fichero al subirlo al servidor. Al enviar el formulario, se ha de validar que se han definido tanto el nombre como el fichero a subir.
Por todos es conocida la aplicacin para mailing online mailChimp. Pues bien, en los siguientes ejercicios vamos a programar nuestra versin lite con funcionalidad reducida, que hemos llamado miniMailChimp. La primera funcionalidad ser la posibilidad de iniciar sesin en la aplicacin, pudiendo as acceder a las pginas de la aplicacin, de acceso permitido slo a usuarios registrados. Para desarrollar esta parte deber tenerse en cuenta lo siguiente:
Los usuarios registrados se encuentran en el fichero passwd.txt, en el que se almacena un usuario en cada lnea. El formato del archivo es el siguiente: username|password|block. Puede analizar el contenido de ejemplo de este fichero: el primer dato hace referencia al nombre, el segundo a la contrasea y el tercer puede tomar el valor 0 (usuario activo) o 1 (usuario bloqueado). Ejemplo:
-40-
El formulario de login se encuentra en la pgina login.php que se facilita en el material del ejercicio. Dicho formulario deber enviar la informacin a la pgina check_login.php. Ambos ficheros se presentan a continuacin. /home/afast/web/PHP/avanzado/ejercicio2/login.php
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>miniMailChimp - Login</title> <link <link <link <link <link rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" media="screen" media="screen" media="screen" media="screen" media="screen" href="css/reset.css" /> href="css/grid.css" /> href="css/style.css" /> href="css/messages.css" /> href="css/forms.css" />
</head> <body class="login"> <div class="login-box main-content"> <header> <h2>miniMailChimp: Identificacin</h2> </header> <section> <div class="message info">Completa el nombre de usuario y contraseña y pulsa Entrar</div> <!-- Tenga en cuenta que el formulario debe enviar los datos al fichero check_login.php --> <form id="form" ... class="clearfix"> <p> <input type="text" id="username" class="full" value="" name="username" placeholder="Nombre de usuario" /> </p> <p> <input type="password" id="password" class="full" value="" name="password" placeholder="Contraseña" /> </p> <p class="clearfix"> <button class="button button-gray fr" type="submit">Entrar</button> </p> </form> <ul> <li>Comuncate con tus clientes</li> </ul> </section> </div> </body> </html>
-41-
/home/afast/web/PHP/avanzado/ejercicio2/check_login.php
<?php $codigos = array( 1 => "El usuario ha sido baneado. No puede acceder", 2 => "Los datos de acceso no son correctos", 3 => "No ha indicado alguno de los datos de acceso" ); $cod; //Comprobar que existen contienen algn valor if( ... ) { las variables 'username' y 'password' y que
//Rescatar el valor de las variables 'username' y 'password' ... //Abrimos el fichero contraseas, en modo lectura ... $enc = false; $usuario = array(); //Mientras que no encontremos al usuario y no lleguemos al final del fichero while(...){ //Rescatamos el contenido de la lnea actual del fichero ... //Almacenamos en el array '$usuario' que declaramos //anteriormente, los valores de cada lnea $usuario = explode("|",$linea_fichero); if($user==$usuario[0] && $pwd==$usuario[1]) { $enc = true; //Comprobamos si el usuario ha sido bloqueado if($usuario[2]==1) { //El usuario ha sido baneado. No puede acceder $cod=1; } else { //Si todo ha ido bien, iniciamos sesin session_start(); $_SESSION['username']=$user; //y redirigimos al usuario a la pgina de inicio: header("Location: ./home.php"); } } } if(!$enc) { //Los datos de acceso no son correctos. $cod=2; } passwd que contiene a los usuarios y
-42-
} else { $cod=3; } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>miniMailChimp - Login</title> <link <link <link <link <link rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" media="screen" media="screen" media="screen" media="screen" media="screen" href="css/reset.css" /> href="css/grid.css" /> href="css/style.css" /> href="css/messages.css" /> href="css/forms.css" />
</head> <body class="login"> <div class="login-box main-content"> <header> <h2>miniMailChimp: Identificacin</h2> </header> <section> <div class="message error"> <?php echo $codigos[$cod]; ?> </div> <br /> <a class="button button-red" href="login.php">Volver a inciar sesin</a> </section> </div> </body> </html>
-43-
se
encuentran
los
ficheros
NOTA: Comprobar que se han introducido comentarios en todos los ficheros, que le ayudarn a completar las tareas que se le solicitan. Paso 2: complete el esqueleto de la pgina check_login.php. Deber comprobarse que los datos enviados por el usuario se corresponden con el usuario y contrasea de algn usuario registrado. Para que un acceso se d por vlido, deber comprobarse adems que el usuario no se encuentre bloqueado (valor del tercer dato igual a 1). TAREAS Se pueden producir los siguientes errores, que debern ser mostrados en la pgina login.php, en el caso en que proceda: Cdigo de error 1: El usuario ha sido bloqueado. No puede acceder. Cdigo de error 2: Los datos de acceso no son correctos". Cdigo de error 3: No se ha indicado alguno de los datos de acceso. En caso de que el login sea correcto, se deber redireccionar al usuario a la pgina home.php. Puede comprobar el funcionamiento de la funcin header, empleada para enviar encabezados HTTP sin formato, y visitar el siguiente enlace para una explicacin ms detallada: http://www.php.net/manual/es/function.header.php. Paso 3: Acceda desde un navegador a: http://localhost/afast/PHP/avanzado/ejercicio2/login.php y compruebe los resultados.
Una vez que el usuario se ha logado correctamente, se le presenta la pgina de inicio: home.php, la cual presenta el siguiente aspecto:
-44-
En esta pgina, se presenta un formulario, donde el usuario puede rellenar los campos de remitente, destinatario y asunto, y enviar un email con el mensaje introducido. El enlace a Inicio permite acceder de nuevo a esta pgina. An no acceda al enlace Usuarios, se realizar un apartado posterior. A continuacin se presenta el contenido de los ficheros home.php, send_mail.php, y las tareas correspondientes a realizar. logout.php y
/home/afast/web/PHP/avanzado/ejercicio2/home.php
<?php <?php session_start(); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>miniMailChimp - Home</title> <link rel="stylesheet" media="screen" href="css/reset.css" />
-45-
<link rel="stylesheet" media="screen" href="css/grid.css" /> <link rel="stylesheet" media="screen" href="css/style.css" /> <link rel="stylesheet" media="screen" href="css/messages.css" /> <link rel="stylesheet" media="screen" href="css/forms.css" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <div id="wrapper"> <section> <div class="container_8 clearfix"> <!-- Sidebar --> <aside class="grid_1"> <nav class="global"> <ul class="clearfix"> <li class="active"><a class="nav-icon icon-house" href="#">Inicio</a> </li> <li class="active"><a class="nav-icon icon-book" href="users.php">Usuarios</a> </li> </ul> </nav> </aside> <!-- Sidebar End --> <!-- Main Section --> <section class="main-section grid_7"> <div class="main-content"> <header> <h2> <!-- Mostrar el nombre del usuario que ha iniciado Sesin y un enlace "Salir" que permita cerrar la sesin (enlace a la pgina logout.php) --> ... </h2> </header> <section class="container_6 clearfix"> <div class="other-options grid_6"> <h3 class="other">Formulario de envío</h3> <!-- Remitir la informacin al fichero send_mail.php mediante POST --> <form ... > <ul> <li> <h4>De:</h4> <input name="from" type="text" value="" /> </li> <li> <h4>Para:</h4> <input name="to" type="text" /> </li>
-46-
<li> <h4>Asunto:</h4> <input name="subject" type="text" /> </li> </ul> <h4>Mensaje:</h4> <textarea name="message"></textarea> <h4> <input type="submit" value="Enviar email" /> </h4> </form> </div> </section> </div> </section> <!-- Main Section End --> </div> <div id="push"></div> </section> </div> <footer> <div id="footer-inner" class="container_8 clearfix"> <div class="grid_8"> <span class="fr">© 2012. ICR </span> </div> </div> </footer> </body> </html>
/home/afast/web/PHP/avanzado/ejercicio2/logout.php
<?php //Destruir la sesin actual ... ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>miniMailChimp - Login</title> <link <link <link <link <link rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" media="screen" media="screen" media="screen" media="screen" media="screen" href="css/reset.css" /> href="css/grid.css" /> href="css/style.css" /> href="css/messages.css" /> href="css/forms.css" />
-47-
</head> <body class="login"> <div class="login-box main-content"> <header> <h2>miniMailChimp</h2> </header> <section> <div class="message success ac"> <h3>La sesin se ha cerrado correctamente</h3> </div> <br /> <a class="button button-blue" href="login_solucion.php">Volver a iniciar sesin</a> </section> </div> </body> </html>
/home/afast/web/PHP/avanzado/ejercicio2/send_mail.php
<?php $codigos = array( 1 => "Email enviado correctamente", 2 => "El email no ha podido ser enviado" ); //Obtener los datos del formulario de envo // de correo electrnico: // - Remitente // - Destinatario // - Asunto // - Mensaje ... //Definir la cabecera necesaria para que en //el email aparezca el remitente indicado //en el formulario ... $cod; //Realizar el envo de email y definir si //se ha realizado correctamente o no if ( ... ){ $cod=1; } else { $cod=2; } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head>
-48-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>miniMailChimp - Login</title> <link <link <link <link <link rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" media="screen" media="screen" media="screen" media="screen" media="screen" href="css/reset.css" /> href="css/grid.css" /> href="css/style.css" /> href="css/messages.css" /> href="css/forms.css" />
</head> <body class="login"> <div class="login-box main-content"> <header> <h2>miniMailChimp</h2> </header> <section> <!-- Comprobar que la variable '$cod' contenga algn valor --> <?php if( ... ) { ?> <!-- imprimir el mensaje almacenado en el array '$codigos', en funcin del cdigo de error que haya resultado. Tambin se debe utilizar la clase CSS 'success' si el envo se ha realizado correctamente ($cod=1) o la clase CSS 'error' si el mail no ha sido enviado ($cod=2)--> <div class="message success ac"> <h3>...</h3> </div> <?php } ?> <br /> <a class="button button-blue" href="users.php">Volver al listado de usuarios</a> </section> </div> </body> </html>
-49-
Paso 4: complete el cdigo del fichero home.php para que muestre el nombre del usuario y un enlace para el cierre de sesin (puede tomar como referencia la imagen siguiente). Complete tambin el formulario. Cuando finalice, acceda desde un navegador a: http://localhost/afast/PHP/avanzado/ejercicio2/login.php y lguese correctamente, para acceder a home.php y comprobar los resultados. TAREAS Paso 5: complete el esqueleto de la pgina logout.php, que realiza el cierre de la sesin. Cuando termine, pruebe a cerrar la sesin pulsando Salir desde la pgina de home.php. Paso 6: complete el cdigo de send_mail.php. Para realizar una prueba de envo de correo, ha de inicializar el agente de transferencia de correo local, encargado de enviar el correo lanzado desde PHP a los servidores de correo destino. Para ello, realice la siguiente accin desde una ventana de terminal: sudo /etc/init.d/exim4 start Ahora ya puede probar a enviar un correo, siempre y cuando haya completado el cdigo de send_mail.php.
En este momento es cuando haremos uso del enlace Usuarios de la pgina principal (home.php). Al hacer click en este enlace, se accede a la pgina users.php, la cual muestra los usuarios y sus contraseas contenidos en el fichero passwd.txt, as como una imagen circular, roja o verde, que indica si el usuario ha sido bloqueado o no. Adems, esta pgina permite aadir nuevos usuarios, lo cual hace uso del fichero add_user.php. Fjese en la siguiente figura, que es el aspecto que ha de presentar la pgina users.php.
-50-
A continuacin, se presenta el contenido de los ficheros users.php y add_user.php, y las tareas correspondientes a este apartado. /home/afast/web/PHP/avanzado/ejercicio2/users.php
<?php session_start(); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>miniMailChimp - Home</title> <link rel="stylesheet" media="screen" href="css/reset.css" /> <link rel="stylesheet" media="screen" href="css/grid.css" /> <link rel="stylesheet" media="screen" href="css/style.css" /> <link rel="stylesheet" media="screen" href="css/messages.css" /> <link rel="stylesheet" media="screen" href="css/forms.css" /> <link rel="stylesheet" media="screen" href="css/tables.css" /> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <div id="wrapper"> <section> <div class="container_8 clearfix"> <!-- Sidebar -->
-51-
<aside class="grid_1"> <nav class="global"> <ul class="clearfix"> <li class="active"><a class="nav-icon icon-house" href="home.php">Inicio</a> </li> <li class="active"><a class="nav-icon icon-book" href="#">Usuarios</a> </li> </ul> </nav> </aside> <!-- Sidebar End --> <!-- Main Section --> <section class="main-section grid_7"> <div class="main-content"> <header> <h2> <!-- Mostrar el nombre del usuario que ha iniciado sesin y un enlace "Salir" que permita cerrar la sesin--> ... </h2> </header> <section class="container_6 clearfix"> <div class="other-options grid_6"> <h3 class="other">Usuarios</h3> <table class="datatable full"> <thead> <tr> <th>Nombre usuario</th> <th>Contrasea</th> <th>Bloqueado</th> </tr> </thead> <?php //Abrir el fichero 'passwd.txt' que //contiene a los usuarios y //contraseas, en modo lectura ... //Mientras nos lleguemos al final //del fichero while( ... ){ //leer la lnea actual del //fichero ... //almacenar en cada posicin de //un array los 3 datos //del usuario actual: nombre,
-52-
//password y bloqueado. ?> <tr class="ac"> <!-- Imprimimos en las 3 celdas siguientes los 3 datos que hemos rescatado del usuario actual. El dato de bloqueado deber pintarse en forma de imagen haciendo uso de las imgenes 1.png y 0.png que se encuentra en el directorio '/images' --> <td>...</td> <td>...</td> <td>...</td> </tr> <?php } ?> <!-- Incluir una ltima fila en la tabla que incluya un formulario para la creacin de un nuevo usuario en el fichero 'passwd.txt'. Para ello deber solicitarse un nombre de usuario y una contrasea y enviarse al fichero 'add_user.php'--> <form...> <tr class="ac"> <td><input type="text" name="user" /> </td> <td><input type="text" name="pass" /> </td> <td><input type="submit" value="Aadir usuario" /> </td> </tr> </form> </table> </div> </section> </div> </section> <!-- Main Section End --> </div> <div id="push"></div> </section> </div> <footer> <div id="footer-inner" class="container_8 clearfix"> <div class="grid_8"> <span class="fr">© 2012. ICR </span> </div> </div> </footer>
-53-
</body> </html>
/home/afast/web/PHP/avanzado/ejercicio2/add_user.php
<?php $res; $cod; $codigos = array( 1 => "El usuario se ha creado correctamente", 2 => "El usuario no ha podido crearse", ); //Comprobar que existan las variables 'user' y 'pass' y que contengan algn valor if( ... ) { //Concatenar la informacin del usuario que ser introducida en la ltima lnea del fichero ... //Escribir la informacin del usuario en la ltima lnea del fichero 'passwd.txt' ... } if($res==false) { $cod=2; } else { $cod=1; } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>miniMailChimp - Login</title> <link <link <link <link <link rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" rel="stylesheet" media="screen" media="screen" media="screen" media="screen" media="screen" href="css/reset.css" /> href="css/grid.css" /> href="css/style.css" /> href="css/messages.css" /> href="css/forms.css" />
</head> <body class="login"> <div class="login-box main-content"> <header> <h2>miniMailChimp</h2> </header> <section> <!-- Imprimir el mensaje de error en funcin del valor de $cod -->
-54-
<div class="message ac"> <h3>...</h3> </div> <br /> <a class="button listado de usuarios</a> </section> </div> </body> </html>
button-blue"
href="users.php">Volver
al
TAREAS
Paso 7: complete el cdigo de los ficheros users.php y add_users.php siguiendo los comentarios. Por ltimo, realice las pruebas pertinentes para probar el cdigo completado.
-55-
El proceso de compilacin de las pginas consiste en analizar su contenido buscando etiquetas JSP y traduciendo stas a cdigo Java equivalente. El contenido esttico de las pginas (cdigo HTML) es traducido a cadenas de caracteres en lenguaje Java. Las etiquetas de componentes JSP son traducidas a su correspondiente objeto Java. Todo este cdigo fuente es usado para formar los mtodos de servicio del servlet. Al igual que sucede con los servlets, para hacer uso de pginas JSP se necesita un componente adicional instalado en el propio servidor web que sea capaz de manipular toda la lgica que dichas pginas implementan, esto es, se require un motor (engine) que se integre de algn modo con el servidor web a fin de que las peticiones hechas al servidor puedan ser recogidas por el cdigo Java para generar la respuesta adecuada. Uno de estos motores es el servidor web Tomcat. El cdigo de una pgina JSP puede contener: Elementos de script: comentarios, expresiones, declaraciones, scriptlets.
-56-
Directivas: proporcionan al motor JSP informacin sobre lo que ste debe hacer a la hora de procesar la pgina. Estas acciones pueden ser estndar (ya definidas por la especificacin JSP) o etiquetas personalizadas. Las directivas son instrucciones procesadas por el compilador JSP cuando la pgina se compila a un Servlet. En JSP se definen tres tipos diferentes de directivas: include, page y taglib. Acciones JSP: proporcionan informacin global de la pgina e indican lo que el motor JSP debe hacer con la pgina JSP a la hora de la traduccin de la pgina a servlet. Las acciones son el elemento que se encarga de controlar el funcionamiento del motor JSP y siguen el formato clave/valor: <accion parametro=valor ... />. Aqu se incluyen los JavaBeans.
En adicin a lo anterior, el motor JSP dispone de una serie de objetos implcitamente creados, los cuales no necesitan ser declarados para ser usados, sino que pueden usarse directamente. Estos objetos resultan muy tiles para acceder a determinadas propiedades que no se conseguiran de otra manera. Los principales objetos implcitos son: request: es el objeto HttpServletRequest asociado con la solicitud del cliente. Con esta variable se puede acceder a los parmetros recibidos del formulario del cliente, as como a las cabeceras HTTP. response: es el objeto HttpServletResponse asociado con la respuesta al cliente. session: es el objeto HttpSession (sesin) asociado con la solicitud del cliente. out: corresponde al objeto de la clase Java PrintWriter que posee todo objeto de tipo response, usndose para enviar la salida al cliente o a otra pgina. page: sinnimo de this en lenguaje Java.
JSP tiene bastantes ventajas frente a otros lenguajes como ASP o PHP. La ventaja fundamental es que tenemos toda la potencia del lenguaje Java a nuestro alcance, con sus ventajas: reusabilidad, robustez, multiplataforma, etc.
-57-
a) Abra una ventana de terminal y arranque los servidores Tomcat y Apache (en este orden): sudo service tomcat6 start sudo service apache2 start b) Si acaba de abrir la mquina virtual porque, por ejemplo, ha comenzado esta seccin en un da distinto al de los apartados anteriores, realice los pasos indicados en el apartado 1.5, para arrancar el servidor web Apache y copiar los ficheros necesarios para la realizacin de la prctica.
c) Cree el directorio siguiente: TAREAS mkdir /home/afast/web/JSP d) Copie los ficheros correspondientes a la parte de JSP en el directorio anterior y liste el contenido del mismo: cp r /home/afast/p07/jsp/* /home/afast/web/JSP cp r /home/afast/p07/WEB-INF /home/afast/web/ ls laR /home/afast/web/JSP e) Cree un fichero de nombre test.jsp. dentro de /home/afast/web/JSP/ y aada el siguiente cdigo: <html><body><% out.println("<h1>Mi primera pgina JSP</h1>"); %></body></html> f) Abra en un navegador la URL correspondiente: http://localhost/afast/JSP/test.jsp.
-58-
<%= "Tamao de cadena: "+cadena.length() %> <%= new java.util.Date() %> <%= Math.PI*2 %>
b) Declaraciones: contienen declaraciones de variables o mtodos, mediante <%! declaracin %>. Estas variables o mtodos sern accesibles desde cualquier lugar de la pgina JSP. Hay que tener en cuenta que el servidor transforma la pgina JSP en un servlet, y ste es usado por mltiples peticiones, lo que provoca que las variables conserven su valor entre sucesivas ejecuciones. Ejemplos:
<%! int numeroAccesos=0; %> <html> <body> <%= "La pgina ha sido accedida "+(++numeroAccesos)+ " veces desde el arranque del servidor" %>
-59-
</body> </html>
c) Scriptlets: Son fragmentos de cdigo Java con la forma <% cdigo %>, en general, podemos insertar cualquier cdigo que pudiramos usar dentro de una funcin Java. Para acceder a la salida del navegador, usamos el objeto implcito out. Ejemplos:
<table> <% for (int i=0;i<10;i++) { %> <tr><td> <%=i%> </td></tr> <% } %> </table>
Si observamos los dos ejemplos anteriores (que hacen lo mismo), podra parecer que la segunda opcin es ms deseable, pero en general hay que evitar el uso de out.println() para elementos HTML. En un proyecto en el que trabajen programadores y diseadores conjuntamente, hay que separar presentacin y cdigo, tanto como sea posible. Dentro de un scriptlet podemos usar cualquier librera de Java, incluyendo las propias, lo cual hace que resulte muy sencillo construir interfaces web de entrada y salida para nuestras clases. Ejemplo:
<% String parametro1=request.getParameter("parametro1"); String parametro2=request.getParameter("parametro2"); MiClase miClase=new MiClase(); String salida=miClase.procesa(parametro1, parametro2); %> <%= salida %>
Para introducir comentarios en JSP, usaremos las marcas <%-- comentario --%>. Dentro de un scriptlet o declaracin podemos usar comentarios siguiendo la sintaxis de Java.
<%-- Comentario JSP --%> <!-- Comentario HTML --> <%
-60-
a) Abra el fichero /home/afast/web/JSP/accesos.jsp y observe su contenido. b) Abra en un navegador la URL correspondiente: http://localhost/afast/JSP/accesos.jsp. c) Pruebe a recargar la pgina (pulsando F5) para ver cmo aumenta el nmero de accesos (la variable conserva su valor entre sucesivas ejecuciones). d) Abra la web de gestin de Tomcat (ver apartado 4.3) y recarge la aplicacin referente a /afast. e) Pruebe a recargar de nuevo la pgina, comprobando que el servlet que se haba generado en la primera ejecucin de la pgina JSP se ha vuelto a crear. f) Puede probar tambin los siguientes fragmentos de cdigo. /home/afast/web/JSP/accesos2.jsp
<%! java.util.Date primerAcceso=new java.util.Date(); %> <html> <body> El primer acceso a la pgina se realiz en: <%= primerAcceso %> </body> </html>
TAREAS
/home/afast/web/JSP/hora.jsp
<%! private String ahora() { return ""+new java.util.Date(); } %> <html> <body> <%= ahora() %> </body> </html>
-61-
errorPage: pgina a la que dirigirse cuando ocurre una excepcin al procesar esta pgina. Ver isErrorPage. <%@ include file='footer.html' %>
La directiva anterior aade el contenido del archivo especificado antes de comenzar la fase de traduccin a Servlet. <%@ page import='java.util.*' %> Con esta directiva se puede importar clases que se utilizan en scriptlets dentro de la pgina. Ejemplo: /home/afast/web/JSP/fecha.jsp <%@ page language='java' contentType='text/html;charset=iso-88591'%> <%@ page import='java.util.Date' %> <html> <head><title>Hola Mundo</title></head> <body> Hola, esto es una pagina JSP. <p>La hora del servidor es <%= new Date() %></p> </body> </html>
-62-
Para cada variable (o propiedad) deben crearse dos mtodos cuyo nombre sea el nombre de la propiedad comenzando por letra mayscula y precedido por get (para mtodo de lectura) o set (para mtodo de escrituta).
As, un ejemplo de clase que sigue la convencin Javabean podra ser la siguiente: clase_javabean.java
public class clase_javabean { public clase_javabean() { } private String propiedad = "valor"; public String getPropiedad() { return propiedad; } public void setPropiedad(String prop) { propiedad = prop; } }
De esta forma, las propiedades del Javabean se exponen pblicamente mediante esos mtodos, cuyo nombre es conocido de antemano al seguir la regla de nombrado Javabean. Esto confiere la caracterstica de instrospeccin que no es ms que la capacidad que tienen los motores JSP como Tomcat de acceder directamente a las variables de la clase, al conocerse los mtodos necesarios para ello. Adicionalmente a lo anterior, las clases Javabean tienen la caracterstica de que pueden implementar la interfaz java.io.Serializable. Se denomina serializacin al proceso de escribir el estado de un objeto en un flujo de octetos, permitiendo con ello almacenar objetos en archivos, transmitirlos por una red de comunicaciones y utilizarlos en aplicaciones distribuidas. Por otro lado, se conoce como persistencia a la capacidad que tiene un objeto para existir ms all de la ejecucin de un programa (en un archivo, por ejemplo). De acuerdo con ello, puede observarse como la seriacin es la clave para la implementacin de la persistencia, ya que permite escribir un objeto en un flujo y volver a leerlo posteriormente. En un flujo de bytes solamente se puede guardar y restablecer un objeto que implemente la interfaz Serializable. Esta interfaz no dispone de mtodos, slo sirve para indicar que una clase se puede serilizar, para lo cual ser necesario que todas las instancias de clases usadas sean de tipo primario o clases que tambin se puedan serializar (por ejemplo, esto no ocurre con la clase Object, pero s con String). Consecuentemente con lo anterior, una definicin de clase Javabean que presente la capacidad de persistencia podra ser la siguiente: clase_javabean_persistente.java
package paquete; import java.io.Serializable; public class clase_javabean_persistente implements Serializable { public clase_javabean_persistente() { }
-63-
private String propiedad = "valor"; public String getPropiedad() { return propiedad; } public void setPropiedad(String propiedad) { } }
Los Javabean, conforme a lo anteriormente indicado, no son ms que una clase Java que sigue unos criterios estndar para el nombrado de los mtodos que permiten acceder pblicamente a variables de dicha clase. Conforme con esto, el uso de Javabeans podra seguir hacindose mediante la inclusin de cdigo Java dentro del fichero JSP, creando por ejemplo una instancia del Javabean del siguiente modo:
<% paquete.clase_javabean instancia = new paquete.clase_javabean (); %>
No obstante, esto no implicara ventaja substancial respecto al uso de los scriptlets. La principal ventaja de los Javabean es que tanto la creacin de la instancia de la clase Javabean como el acceso a sus variables puede realizarse mediante etiquetas JSP, eliminando as el cdigo Java de la pgina JSP. Las etiquetas JSP que permiten esto son: a) jsp:useBean: crea una instacia nombre de la clase Javabean clase:
<jsp:useBean id="nombre" class="clase" type="tipo" scope="mbito" />
donde se distinguen los siguientes parmetros: id: especifica el nombre de la instancia del JavaBean con el que ser conocido dentro del mbito en el que se define. class: indica la clase JavaBean que se va a instanciar. type: indica otra clase o interfaz de la que deriva el bean, haciendo que ste deba usarse como tipo de datos de esa clase o interfaz. Su valor puede ser el mismo que el del parmetro class, una superclase de class o una interfaz implementada por class. As, por ejemplo, si el JavaBean va a implementar la interfaz Runnable para ejecucin en segundo plano, se indicara como tipo type="Runnable". scope: determina el mbito en el que puede usarse el JavaBean, pudiendo ser: = page: es accesible nicamente dentro de la pgina en la que se define. = session: es accesible desde todas las pginas que procesen peticiones dentro de la misma sesin (objeto session, asociado a un cliente, que ayuda a administrar datos especficos del mismo en la aplicacin Web). = application: es accesible desde todas las pginas de la misma aplicacin Web.
b) jsp:getProperty: obtiene el valor de la propiedad (variable) propiedad de la instancia de clase Javabean nombre:
-64-
<jsp:getProperty name="nombre" property="propiedad" /> c) jsp:setProperty: establece a valor el valor de la propiedad (variable) propiedad de la instancia de clase Javabean nombre: <jsp:setProperty name="nombreInstancia" property="propiedad" value="valor" />
Para que las etiquetas anteriores funcionen, el cdigo Java del JavaBean requerira: Variable miembro propiedad. Funciones miembro pblicas getPropiedad() y setPropiedad().
Como ejemplo de uso de estas etiquetas, se crea una instancia fuente de la clase FuenteBean, se modifica el valor de la propiedad codigo de esa instancia fuente y se recupera a continuacin dicho valor: <jsp:useBeanid="fuente" class="FuenteBean" /> <jsp:setProperty name="fuente" property="codigo" value="YO"/> <jsp:getProperty name="fuente" property="codigo"/>
Resumiendo, el uso de JavaBeans permite eliminar gran parte del cdigo Java de las pginas JSP, de forma que casi toda la lgica de programacin de la pgina se encapsule en JavaBeans (reduciendo la pgina a cdigo HTML o XML) que, adems, podrn ser reutilizados. Esas clases o cdigo Java podrn ser compilados y depurados utilizando las herramientas habituales de programacin, ventaja importante frente a la insercin de cdigo Java dentro de la pgina (que tiene que ser depurado en la propia carga de la pgina). Ejemplo: Para mostrar el funcionamiento se presenta un ejemplo sencillo que se limita a llamar a la clase que implementa el JavaBean, recuperando en primer lugar el valor inicial del parmetro saludo del mismo (inicialmente saludo = Hola y, posteriormente, cambiando dicho valor a uno distinto (al finalizar, saludo = Adios), recogiendo esos valores en el cdigo HTML resultante. Se usan as dos ficheros: jbean.jsp: pgina JSP que realiza las llamadas al cdigo JavaBeans a travs de directivas JSP. /home/afast/web/JSP/jbean.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <%-- jbean.jsp
-65-
Ejemplo para mostrar el uso de un JavaBean siguiendo la convencin de la especificacin JavaBean --%> <html> <head> <title>Titulo del Ejemplo: Pagina JSP basada en JavaBeans</title> </head> <body> <%-- Indicamos que se desea crear una instancia del objeto jspJB --%> <jsp:useBean id="miBean" scope="page" class="paquete.jspJB" /> <h2>Ejemplo: Pagina JSP basada en JavaBeans</i></h2> <p>Saludo inicial:<br> <%-- Se imprime el valor inicial de la propiedad Saludo --%> <jsp:getProperty name="miBean" property="saludo" /> <p>Saludo final:<br> <%-- Se fija e imprime un nuevo valor para la propiedad Saludo --%> <jsp:setProperty name="miBean" property="saludo" value="Adios" /> <jsp:getProperty name="miBean" property="saludo" /> </body> </html>
/home/afast/web/WEB-INF/classes/paquete/jspJB.java
// jspJB.java /* Clase Java que sigue la convencion JavaBean * Bean que describe la propiedad saludo. Constructor por defecto, sin * argumentos, necesario para que esta clase sea un JavaBean. */ package paquete; public class jspJB { private String saludo = "Hola"; // Mtodos set/get para asignar/recuperar el valor de la propiedad public void setSaludo( String _saludo ) { saludo = _saludo; } public String getSaludo() { return( saludo ); } public String saludoCompleto() { return( saludo+", afast" ); } }
En este caso, al no necesitar pasar informacin inicial a ninguna clase Java, no resulta necesario el descriptor de la aplicacin web.xml, por lo que en este caso se prescindir de l con la intencin de mostrar su no obligatoriedad en aplicaciones simples. Puede observarse como el uso de JavaBeans reduce considerablemente la cantidad de cdigo JSP insertado dentro de la pgina HTML, al tiempo que permite la reutilizacin de cdigo Java. El uso de la directiva include tambin permite reducir parte del cdigo Java insertado en la pgina, pero no
-66-
ofrece las posibilidades de los JavaBeans, presentando un funcionamiento a nivel de programacin Java totalmente diferente. No obstante, a pesar de las mejoras que introducen los JavaBeans, el desarrollo de pginas mediante su uso an sigue requiriendo ciertos conocimientos en programacin Java (debido a que se estn usando directivas JSP, no etiquetas HTML). Para probar la aplicacin realice las siguientes tareas. a) Compile el fichero jspJB.java: TAREAS javac verbose /home/afast/web/WEBINF/classes/paquete/jspJB.java b) Accediendo al gestor de Tomcat va web, recargue el contexto del usuario afast. c) Acceda a la pgina http://localhost/afast/JSP/jbean.jsp
a) request Es un objeto de la clase HttpServletRequest, su uso principal es el acceso a los parmetros de la peticin. Destacaremos las siguientes funciones: String getParameter(String name): devuelve el valor de un parmetro. Enumeration getParameterNames(): devuelve una enumeracin con los nombres de todos los parmetros de la peticin. String[] getParameterValues(String name): los parmetros pueden tener valor mltiple, con esta funcin recuperamos un array con todos los valores para un nombre dado. String getRemoteAddr(): devuelve la IP del host desde el que se realiza la peticin. String getRemoteHost(): devuelve el nombre del host desde el que se realiza la peticin.
Ejemplo: /home/afast/web/JSP/request.jsp
<html> <body> <form> <input type="text" name="parametro"/> <input type="submit"/>
-67-
</form> <br><br> Su IP: <%=request.getRemoteAddr()%> <br> Su nombre de host: <%= request.getRemoteHost() %> <br> Valor del parmetro: <%= request.getParameter("parametro") %> </body> </html>
TAREAS
a) Abra en un navegador la URL correspondiente: http://localhost/afast/JSP/request.jsp. b) Introduzca un valor en el campo del formulario y compruebe el funcionamiento.
b) response Es un objeto de la clase HttpServletResponse, que asiste al servlet en su generacin de la respuesta para el cliente, contiene funciones para manejo de cabeceras, cdigos de estado, cookies y transferencia de control. c) out Es un objeto de la clase JspWriter, es el que nos permite acceder a la salida del navegador desde los scriplet. Ejemplo: <% out.print("cadena"); out.println("cadena"); %> d) session Es un objeto de la clase HttpSession. Nos permite acceder a la sesin asociada a la peticin. A travs de este objeto podemos, entre otras cosas, guardar objetos que sern accesibles desde cualquier JSP de la sesin o invalidarla. Para guardar y recuperar informacin usaremos: Object session.getAttribute("clave"); void session.setAttribute("clave", Object objeto); Y para invalidar la sesin: void session.invalidate(); Ejemplo: /home/afast/web/JSP/session.jsp
<%@ page session="true" %>
-68-
<% java.util.ArrayList accesos=(java.util.ArrayList)session.getAttribute("accesos"); if (accesos==null) accesos=new java.util.ArrayList(); accesos.add(new java.util.Date().toString()); session.setAttribute("accesos", accesos); if (request.getParameter("invalidaSesion")!=null) session.invalidate(); %> <html> <body> <form> <input type="submit" name="invalidaSesion" value="Invalidar sesin"/> <input type="submit" value="Recargar pgina"/> </form> <br/> Usted accedi a esta pgina en los siguientes momentos: <br> <% for (int i=0;i<accesos.size();i++) { %> <%= accesos.get(i) %> <br> <% } %> </body> </html>
TAREAS
e) application Es un objeto de la clase ServletContext. Este objeto es comn para toda la aplicacin web y, entre otras cosas, nos permite almacenar informacin que ser accesible desde todas las pginas de la aplicacin web, independientemente de la sesin. Para guardar y recuperar valores: Object application.getAttribute("clave"); void application.setAttribute("clave", Object objeto); Ejemplo: /home/afast/web/JSP/application.jsp
<%@ page session="true" %> <%
-69-
java.util.Hashtable getAttribute("direcciones");
direcciones=(java.util.Hashtable)application.
if (direcciones==null) direcciones=new java.util.Hashtable(); direcciones.put(request.getRemoteAddr(),""); application.setAttribute("direcciones", direcciones); %> <html> <body> El servidor fue accedido desde las siguientes direcciones IP: <br> <% java.util.Enumeration e=direcciones.keys(); while (e.hasMoreElements()) { %> <%= e.nextElement() %> <br> <% } %> </body> </html>
TAREAS
f) config Es un objeto de la clase ServletConfig. Permite acceder a parmetros de inicializacin del servlet y a su contexto. g) pageContext Es un objeto de la clase PageContext. Entre otras cosas, nos permite almacenar informacin localmente a la pgina. Para guardar y recuperar valores: Object pageContext.getAttribute("clave"); void pageContext.setAttribute("clave", Object objeto); Tambin podemos usar PageContext para almacenar y recuperar informacin en sesin y en aplicacin: Almacenar en contexto de pgina: PageContext.setAttribute("clave", obj, PageContext.PAGE_SCOPE); PageContext.setAttribute("clave", obj);
-70-
Almacenar en contexto de sesin: PageContext.setAttribute("clave",obj, PageContext.SESSION_SCOPE); session.setAttribute("clave", objeto); Almacenar en contexto de aplicacin: PageContext.setAttribute("clave",obj,PageContext.APPLICATION_SCOPE); application.setAttribute("clave",objeto); h) page Es un sinnimo de this, no tiene utilidad en el estado actual de la especificacin.
/home/afast/web/JSP/pagina.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Formulario JSP</title> </head> <body> Valor de parametro1: <%= request.getParameter("parametro1") %>
-71-
<br/> Valor de parametro2: <%= request.getParameter("parametro2") %> <br/> Valor de parametro clave: <%= request.getParameter("clave") %> <br/> <% String[] seleccion= request.getParameterValues("selectMultiple"); for (int i=0;i<seleccion.length;i++) { %> <%= seleccion[i] %> <br/> <% } %> </body> </html>
TAREAS
-72-
TAREAS
-73-
Observe las siguientes capturas, que son el resultado de la ejecucin de la aplicacin web finalizada:
-74-
Antes de nada, descargue de WebCT el fichero formquiz.tar.gz y descomprmalo en /home/afast/web/PHP/. NOTA: si est realizando la aplicacin prctica en un da distinto al apartado referente a PHP, puede seguir los pasos de la seccin 3.2 para preparar el entorno. Para desarrollar la aplicacin debern seguirse las indicaciones hechas en el cdigo fuente de los ficheros que se proporcionan para completar los ficheros PHP (indicaciones mediante comentarios en el cdigo), en el orden que se indica a continuacin: 1) generador_html.php: este fichero se encarga de generar el cdigo fuente en funcin del tipo de elemento que el usuario ha seleccionado en el fichero index.php. Una vez genera el cdigo fuente, se encarga de incluirlo en una variable de sesin cuyo tipo es la clase Form. /home/afast/web/PHP/formquiz/generador_html.php <?php include("form.php"); session_start(); if(!isset($_SESSION['form'])) { $_SESSION['form'] = new Form; } $form = $_SESSION['form']; $tipo_elemento = $_REQUEST['tipo-elemento']; $nombre_elemento = $_REQUEST['nombre-elemento']; $codigo_fuente = ""; $id = $form->get_num_elementos(); /* A continuacin deben tratarse los tipos de campos que pueden haber generado el usuario: 1 2 3 4 5 6 7 => => => => => => => campo de texto Grupo de botones de opcin Checkbox Lista desplegable Nmero (HTML5) Email (HTML5) Submit
-75-
8 => Botn */ switch($tipo_elemento) { case 1: $codigo_fuente = '<label for="'.$id.'">'.$nombre_elemento.': </label>'; $codigo_fuente .= '<input type="text" id="'.$id.'" />'; $codigo_fuente .="\n"; break; //Completar el resto de casos ... } $form->add_item($codigo_fuente); header("Location: index.php"); ?>
2) form.php: completar las funciones de esta clase PHP que se encarga de almacenar en la variable tems los elementos HTML de formulario que el usuario ha ido generando. /home/afast/web/PHP/formquiz/form.php <?php class Form { var $items = array(); // La siguiente funcione aade el cdigo fuente // del elemento que ha generado el usuario // al array 'items' de esta clase function add_item($codigo) { // Primero debemos calcular cul es la ltima // posicin del array, es decir, la longitud // del array 'items' para almacenar el elemento // en la ltima posicin $posicion = ... // Una vez sepamos la ltima posicin del array // almacenamos en dicha posicin items[$posicion] // el cdigo fuente del elemento ... } // Esta funcin devuelve el nmero de elementos que // el usuario ha generado. function get_num_elementos() { // Para devolver el nmero de elementos del array
-76-
// puede utilizarse la funcin count() // http://php.net/manual/es/function.count.php ... } // Muestra los elementos del array 'items' como una lista // ordenada en HTML. function show_items() { echo "<ul>"; // Recorrer los elementos del array 'items' imprimiendo // el valor de cada elemento dentro de un elemento de lista: // <li> valor del elemento</li>. ... echo "</ul>"; } } ?>
3) index.php: en este fichero, adems de permitirse la generacin de nuevos elementos de formulario, se muestra el cdigo fuente y la visualizacin de los elementos que el usuario ha ido generando. /home/afast/web/PHP/formquiz/index.php <?php include("form.php"); session_start(); ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>formQuiz</title> <link rel="stylesheet" href="style.css" media="screen" /> <script type="text/javascript" language="javascript" src="jquery.min.js"></script> <script type="text/javascript" language="javascript"> $(document).ready(function() { $("#tipo-elemento").change(function() { var tipoSeleccionado = $(this).val(); if(tipoSeleccionado=="2" || tipoSeleccionado=="4") { $("#numero-elementos").css("display","inline"); } else { $("#numero-elementos").css("display","none"); } }); $("#generar").click(function() {
-77-
var tipoSeleccionado = $("#tipo-elemento").val(); var nombreElemento = $("#nombre-elemento").val(); //Compruebo si han seleccionado un tipo de elemento if(tipoSeleccionado==0) { alert('Debes seleccionar un tipo de elemento'); $("#tipo-elemento").focus(); return false; } //Compruebo si han seleccionado un tipo de elemento if(nombreElemento=="") { alert('Debes introducir un nombre de elemento'); $("#nombre-elemento").focus(); return false; } $("#form").submit(); }); }); </script> </head> <body> <header id="main"> <div id="logo"></div> <nav id="top-menu"> <form action="generador_html.php" method="post" id="form"> <ul> <li> <select id="tipo-elemento" name="tipo-elemento"> <option value="0">-Selecciona un elemento</option> <option value="1">Campo de texto</option> <option value="2">Grupo de botones de opcin</option> <option value="3">Checkbox</option> <option value="4">Lista desplegable</option> <option value="5">Nmero (HTML5)</option> <option value="6">Email (HTML5)</option> <option value="7">Submit</option> <option value="8">Botn</option> </select> </li> <li> <input type="text" id="nombre-elemento" name="nombre-elemento" placeholder="Etiqueta del campo" size="30" /> </li> <!-- El siguiente elemento de lista slo aparecer cuando haya seleccionemos un grupo de botones de opcin o una lista desplegable --> <li id="numero-elementos" style="display:none">
-78-
<label for="num-elementos">N de elementos</label> <input type="number" id="num-elementos" name="numelementos" value="1" min="1" max="5" /> </li> <li> <input type="button" id="generar" value="Generar elemento" /> </li> <li> <a href="reset.php">Resetear formulario</a> </li> </form> </ul> </nav> </header> <section id="content"> <section id="code"> <h1>Formulario generado</h1> <div id="source-code"> <textarea style="width:100%"> <?php // Invocar al mtodo de la clase Form que muestre los // elementos que el usuario haya generado ... ?> </textarea> <?php // Repetir el cdigo escrito arriba para que se muestren // los elementos tal y como se veran en el navegador ... ?> </div> </section> </section> </body> </html>
4) reset.php: se destruye la sesin, de manera que se vaca el bloque de formulario generado, perdindose los elementos generados que haban sido almacenados en la variable de sesin de tipo Form. /home/afast/web/PHP/formquiz/reset.php <?php session_start();
-79-
// Destruir la sesin actual ... // Redireccionar al usuario a la pgina // index.php header("Location: index.php"); ?>
-80-
-81-
El Test consta de 5 cuestiones, todas igualmente ponderadas ("2 puntos", sobre 10, por cuestin). Cada cuestin presenta 3 opciones, de las cuales slo 1 de ellas es correcta. La cuestin mal contestada descuenta 1/3 de una cuestin bien contestada, sobre el total del Test (una cuestin no contestada no puntuar, ni positiva ni negativamente). Si obtuviese en el Test una calificacin negativa, se le computara como "0" puntos al sumarla con las dems pruebas de la asignatura (dems Tests de Prcticas y Examen). Si alguna pregunta del Test tuviese que ser anulada, su puntuacin sera distribuida entre las dems cuestiones del Test. La adecuada interpretacin de las cuestiones planteadas en el examen forma parte del mismo (el profesor no responder a ninguna pregunta relativa a la interpretacin de las cuestiones del Test). III) PROCEDIMIENTO DE ENTREGA DEL TEST Cuando termine el Test, asegrese de que ha pulsado el botn "Terminar". Tras ello, levante la mano para que el profesor acuda a su puesto de trabajo y compruebe que todo est correcto. Cuando el profesor se lo indique, salga de la sala en silencio. NOTA: Estas Instrucciones sern referenciadas cuando comience el Test. Se le presentan aqu para que no necesite invertir tiempo del examen en su lectura.
1) La forma correcta en que un programa CGI ha de enviar al navegador la cabecera MIME es: (a) print "Content-type: text/html\n"; (b) print "Content-type: text/html\n\n"; (c) print "Content: text/html\n";
2) La variable "$_FILES" de PHP contiene: (a) Toda la informacin del fichero subido. (b) Slo el nombre original del fichero en la mquina cliente. (c) Slo el nombre del fichero temporal en el que se almacena el fichero subido en el servidor.
3) Qu variable de entorno CGI contiene los datos de la lnea de peticin al emplear el mtodo GET?
-82-
4) Dispone del siguiente cdigo PHP en su pgina: $precio_mueble = array ('mesa'=>100, 'silla'=>50, 'sofa'=>350); Indique la forma correcta de acceder al primer valor: (a) $precio_mueble[1]; (b) $precio_mueble[mesa]; (c) precio_mueble[0];
5) Una de las ventajas de emplear JSP frente a PHP es: (a) PHP no tiene soporte de orientacin a objetos. (b) JSP ofrece soporte para sesiones. (c) Ninguna de las anteriores.
Cuestin Solucin
1 (b)
2 (a)
3 (a)
4 (b)
5 (c)
APAGUE EL EQUIPO Cuando finalice la prctica no olvide apagar el equipo. Para ello: 1 Apague el "equipo" de la mquina Linux Debian, bien desde la opcin "Apagar" del escritorio KDE o Gnome, o bien mediante el comando "poweroff". Una vez en el sistema real desde el que entr en la mquina virtual, apague finalmente el ordenador usando la opcin "Apagar".
-83-
7 Anexo I
7.1 Instalacin de Tomcat
a) Instalacin de paquetes necesarios, desde una ventana de terminal:
apt-get install sun-java6-jdk tomcat6 tomcat6-user tomcat6-common tomcat-docs tomcat-examples libtomcat6-java libservlet2.5-java libservlet2.5-java-doc libmysql-java
b) Libreras de Tomcat (.jar en "/usr/share/tomcat6/lib", que son enlaces simblicos a ficheros en "/usr/share/java/"): "jsp-api.jar", API de JSP (apunta a "/usr/share/tomcat6/lib/jsp-api.jar" y ste a "jsp-api2.1.jar"): ".jar" y enlace simblico creados por el paquete "libservlet2.5-java" "servlet-api.jar", API de Servlets (apunta a "/usr/share/tomcat6/lib/servlet-api.jar" y ste a "servlet-api-2.5.jar"): ".jar" y enlace simblico creados por el paquete "libservlet2.5-java" Configuracin de Tomcat: En "/etc/tomcat6/server.xml": Comentar conector "Connect 8080" Descomentar conector "Connect 8009", quitarle el "redirect" y aadir uriencoding="UTF8" para no tener problemas con las tildes: <connector protocol="AJP/1.3" uriencoding="UTF-8" port="8009" /> En "/etc/tomcat6/tomcat-users.xml": Definir los roles "tomcat", "manager-gui", "manager-script", "manager-jmx", "managerstatus", "admin-gui", "admin-script" Definir el usuario "manager" con la clave "tomcat" y asignarle los roles anteriores En "/etc/tomcat6/Catalina/localhost/", aadir el fichero "afast.xml" con el contexto: docBase="/home/afast/web/"
c)
-84-
d) Web de gestin (necesaria para recargar los contextos de las aplicaciones): instalada con el paquete "tomcat6-admin" Acceso: http://IP/manager/html/ (usuario "manager", clave "tomcat")
Acceso: http://IP/host-manager/html/ (Gestor de mquinas virtuales de Tomcat) NOTA: Se encuentra fsicamente en: /usr/share/tomcat6-admin/manager/ /usr/share/tomcat6-admin/host-manager/ NOTA2: Tomcat slo escucha en el puerto: 8009 (AJP 1.3, comunicacin con Apache), y permite conexiones desde un Apache local o remoto.
b) Configuracin: Al final de "/etc/apache2/apache2.conf" aadir: ServerName FAST (para que no de warning al arrancar el servidor) Editar el fichero "/etc/apache2/conf.d/charset" y descomentar: AddDefaultCharset UTF-8 (para evitar problemas con las tildes)
Crear los enlaces simbolicos (activar acceso HTTPS): cd /etc/apache2/mods-enabled/ ln -s ../mods-available/ssl.conf ln -s ../mods-available/ssl.load cd /etc/apache2/sites-enabled/ ln -s ../sites-available/default-ssl 000-default-ssl ssl.conf ssl.load
-85-
NOTA: la primera vez que accedamos al navegador pedir que aceptemos el Certificado digital del cliente.
c) Conexin con Tomcat para JSP: mdulo mod_jk Instalacin: apt-get install libapache2-mod-jk (crea los enlaces simblicos necesarios en la carpeta de apache) Configuracin: Crear el fichero "/etc/apache2/mod_jk_worker_property" con el contenido: worker.list=wlajp worker.wlajp.port=8009 worker.wlajp.host=localhost worker.wlajp.type=ajp13
JkWorkersFile
"mod_jk_workers_property"
Editar los ficheros "/etc/apache2/sites-available/default" y "/etc/apache2/sitesavailable/default-ssl", y aadirles al final del VirtualHost (dentro):
JkMount /manager/* JkMount /host-manager/* JkMount /*.jsp JkMount /*.jspx JkMount /*/servlets/*
-86-
d) Mdulo "mod_php": Motor PHP: Instalacin. Paquetes: apt-get install php5-common php5-cli php5xmlrpc php5-xsl" php-auth-http php-html-common php-xajax Configuracin en "/etc/php5/apache2/php.ini": default_charset = "UTF-8" (para evitar problemas con las tildes)
Instalacin modulo PHP de Apache "mod_php": Paquete: libapache2-mod-php5 (crea los enlaces simblicos necesarios en la carpeta de apache)
e) Mdulo "mod_cgi" (CGI con C/C++, Java, shell-scripts, Perl): Instalacin (http://httpd.apache.org/docs/2.2/howto/cgi.html): Paquete: "apache2.2-common" (antes instalado, aporta el CGI normal)
Configuracin en Apache: En el fichero "/etc/apache2/mods-enabled/mime.conf", debe estar descomentada la linea: AddHandler cgi-script .cgi .sh
Editar "/etc/apache2/conf.d/afast.conf" para que su contenido sea (el orden de las directivas es fundamental): ScriptAlias /afast/cgi-bin/ /home/afast/web/cgi-bin/ <Directory "/home/afast/web/cgi-bin/"> AllowOverride None
-87-
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> Alias /afast "/home/afast/web/"
<Directory "/home/afast/web/"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch +Includes Order allow,deny Allow from all </Directory>
NOTA: con esta configuracin, los CGIs pueden ser ubicados en: "/home/afast/web/cgi-bin" (por la directiva "ScriptAlias"): con cualquier extensin Accedidos con la URL http://IP/afast/cgi-bin/fichero_ejecutable "/home/afast/web/" (por la directiva "AddHandler"): con la extension ".cgi" Accedidos con la URL http://IP/afast/cgi-bin/fichero.cgi
-88-