Desarrollo de aplicaciones web con PHP y MySQL
Interactuando con el servidor
Sergio Sáez y José Luis Poza
E.T.S. de Ingeniería Informática
- Subiendo ficheros con PHP
- Accediendo al sistema de ficheros
- Control de acceso con Apache
Introducción
En las aplicaciones en las que se quiere que el usuario sea capaz de actualizar los contenidos del servidor se requiere:
- Permitir al usuario poner información en el servidor.
- Información en los formularios.
- Subir ficheros con información al servidor.
- El servidor debe adaptar sus contenidos de acuerdo con la información actualizada.
- Acceso al sistema de ficheros.
- No se debe permitir a cualquiera interactuar con el contenido del servidor.
Subiendo ficheros al servidor en PHP
- PHP soporta los uploads del protocolo HTTP.
- En este caso, la información fluye desde el navegador hacia el servidor web mediante un formulario.
- Permite enviar un fichero desde el sistema de ficheros del usuario hasta el sistema de ficheros del servidor.
<form enctype="multipart/form-data" action="upload.php" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="1024">
Subir el fichero: <input type="file" name="fichero"><br>
<input type="submit" value="Enviar fichero">
</form>
- Se debe utilizar el método POST. GET no funciona.
- La codificación debe ser multipart/form-data para indicarle al servidor que, además de los datos normales del formulario, también se está enviando un fichero.
Subiendo ficheros al servidor en PHP (cont.)
- Existe un campo oculto que permite informar al navegador del tamaño máximo del fichero que se puede enviar.
- El nombre de la variable debe ser MAX_FILE_SIZE.
- El valor indica el máximo tamaño del fichero en bytes.
- Este campo debe ir antes que el campo de tipo file.
- Un campo de entrada de tipo file, con un nombre que permita identificar el fichero posteriormente (v.g. fichero).
Acceso al fichero desde PHP
- Cuando el fichero se envía al servidor, se deja en un fichero temporal.
- Información disponible (nombre fichero)
- $_FILES['fichero']['name']
- Nombre original del fichero en la máquina del cliente.
- $_FILES['fichero']['tmp_name']
- Nombre del fichero temporal con el que se ha almacenado el fichero en el servidor.
- $_FILES['fichero']['type']
- Tipo MIME suministrado por el navegador. v.g. image/gif.
- $_FILES['fichero']['size']
- El tamaño del fichero recibido en bytes.
- $_FILES['fichero']['error']
- Código de error indicando los posibles problemas que hayan podido suceder. 0 indica que todo ha ido correctamente.
- Si el fichero no se renombra o mueve antes de terminar el script, el servidor lo borrará.
Acceso al fichero desde PHP (cont.)
<?php
$uploaddir = '/var/www/uploads/';
if (!is_uploaded_file($_FILES['fichero']['tmp_name'])) {
echo "El fichero no se ha enviado correctamente. <br>\n";
} elseif ($_FILES['fichero']['size'] <= 0 ||
$_FILES['fichero']['size'] > MAX_SIZE) {
echo "El fichero es demasido grande o está vacio. <br>\n";
} elseif ($_FILES['fichero']['type'] != "text/plain") {
echo "El fichero no es del tipo solicitado. <br>\n";
} elseif (move_uploaded_file($_FILES['fichero']['tmp_name'],
$uploaddir . $_FILES['fichero']['name'])) {
echo "El fichero se ha recibido correctamente. <br>\n";
} else {
echo "Error al mover el fichero. Error: " .
$_FILES['fichero']['error']. ". <br>\n";
}
?>
- Si no queremos comprobar el tipo del fichero, move_uploaded_file hace casi todo el trabajo.
Ficheros de configuración asociados
- /etc/mime.types
- Contiene la descripción de los tipos de archivo MIME y las posibles extensiones. Se puede encontrar en http://www.iana.org/assignments/media-types/. Ejemplos:
application/pdf pdf
application/postscript ps ai eps
image/png png
image/jpeg jpeg jpg jpe
- /etc/php5/apache2/php.ini
- Contiene información sobre las caracteríticas del proceso de subida de ficheros en PHP.
;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;
; Whether to allow HTTP file uploads.
file_uploads = On
; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
;upload_tmp_dir =
; Maximum allowed size for uploaded files.
upload_max_filesize = 2M
Accediento al sistema de ficheros
Una vez se ha recibido el fichero desde el usuario y se ha almacenado en un directorio quizás se necesite:
- Examinar o manipular el contenido del fichero que acabamos de recibir.
- Examinar/modificar el directorio dónde se ha almacenado el fichero.
- Ejecutar algún programa externo para manipular los ficheros existentes.
Vamos a ver un conjunto de funciones que nos van a permitir llevar a cabo estas acciones.
Examinando directorios
<?php resource opendir (string path); ?>
- Abre un directorio para su lectura, similar a fopen. Si no se puede abrir el directorio (ruta, permisos) devuelve false y genera un warning.
<?php string readdir (resource dir_handle); ?>
- Devuelve el siguiente fichero del directorio, en el orden en el que está almacenado en el sistema de ficheros.
- Devuelve false cuando no quedan más ficheros en el directorio. Debe comprobarse con la identidad, porque el fichero "0" tambien se evalua a false.
<?php void closedir (resource dir_handle); ?>
- Cierra el directorio abierto con opendir().
<?php void rewinddir (resource dir_handle); ?>
- Rebobina el directorio hasta el primer fichero.
Examinando directorios (cont.)
$ ls -la
total 24
drwxr-xr-x 2 ssaez ssaez 4096 mar 4 18:39 .
drwxr-xr-x 14 ssaez ssaez 4096 mar 4 17:35 ..
-rw-r--r-- 1 ssaez ssaez 0 feb 19 10:26 0
-rw-r--r-- 1 ssaez ssaez 10995 feb 19 10:26 10-accediendo-al-servidor.fmt
-rw-r--r-- 1 ssaez ssaez 0 feb 19 10:26 index.html
-rw-r--r-- 1 ssaez ssaez 116 feb 19 10:26 Makefile
|
<?php if ($handle = opendir('.')) { echo "\n **** Primera pasada ****\n"; /* De esta forma no habrá problemas con los nombres de los ficheros (v.g. 0). */ while (false !== ($file = readdir($handle))) { echo "$file\n"; } // endwhile echo "\n **** Segunda pasada ****\n"; /* Éste podría terminar antes del final. */ rewind($handle); while ($file = readdir($handle)) { echo "$file\n"; } closedir($handle); } ?>
|
**** Primera pasada ****
index.html
0
Makefile
.
10-accediendo-al-servidor.fmt
..
**** Segunda pasada ****
index.html
|
Información sobre el directorio
<?php string dirname (string path); ?>
- Recibe una ruta y devuelve el nombre del directorio.
<?php string basename (string path [, string suffix]); ?>
- Recibe una ruta a un fichero y devuelve el nombre del fichero propiamente dicho.
<?php string realpath (string path); ?>
- Recibe una ruta con enlaces simbólicos, y elementos del tipo "/./" o "/../" y devuelve la ruta canónica (absoluta) equivalente.
<?php float disk_free_space (string directory); ?>
- Devuelve el espacio libre en bytes del sistema de ficheros o partición de disco en que se encuentra el directorio.
<?php float disk_total_space (string directory); ?>
- Devuelve el espacio ocupado en bytes por el sistema de ficheros o partición de disco en que se encuentra el directorio.
Creando y borrando directorios
<?php bool rmdir (string dirname); ?>
- Intenta borrar el directorio dirname. Éste debe estar vacio y debemos tener los permisos adecuados.
<?php bool mkdir (string pathname [, int mode]); ?>
- Intenta crear el directorio pathname con el modo mode. El mode se verá afectado por umask.
<?php int umask ([int mask]); ?>
- Cambia la mascara a mask & 0777, y devuelve la mascara anterior.
Existen multitud de funciones que permiten obtener información sobre un fichero: si es un fichero, un directorio, un enlace, si es ejecutable, si se puede mofificar, etc.
Ejecución de programas
<?php string exec (string command [, array output
[, int return_var]]); ?>
- Ejecuta command pero no muestra ninguna salida.
- Si output está presente almacenará todas las líneas de la salida.
- En return_var almacenaría el código de error del programa.
<?php string system (string command [, int return_var]); ?>
- Ejecuta command y le envia el resultado al navegador.
- Intenta enviar la salida al navegador línea por línea.
- Es útil para incluir la salida dentro del fichero HTML de resultados.
<?php void passthru (string command [, int return_var]); ?>
- Ejecuta command y le envia el resultado directamente al navegador.
- Es útil cuando la salida es binaria.
Control de acceso con apache
- Con el fichero .htaccess se puede cambiar el comportamiento del servidor Apache en el directorio en el que esté alojado dicho fichero y todos sus subdirectorios.
- En la configuración de Apache debe estar habilitado que el fichero .htaccess puede sobre escribir la configuración principal establecida para ese directorio.
- Se puede utilizar para restringir el acceso a las páginas web situadas en un determinado directorio.
ErrorDocument 401 /home/ssaez/php/include/error_401.php
AuthUserFile /home/ssaez/php/user.passwd
AuthGroupFile /home/ssaez/php/group.passwd
AuthName "Curso de PHP y MySQL"
AuthType Basic
require valid-user
Control de acceso con apache (cont.)
- ErrorDocument error_code URL
- Indica qué página debe mostrarse en caso de error. 401 es acceso denegado.
- AuthUserFile file y AuthGroupFile file
- Le indica a Apache dónde encontrar las claves de acceso para usuarios y los nombres de los grupos.
Este fichero se puede crear y actualizar con la orden htpasswd.
- AuthName "name"
- Nombre de la zona restringida. Se le muestra al usuario para indicarle qué clave se le está solicitando.
- AuthType Basic
- Indica que vamos a utilizar el mecanismo básico de autentificación. No hay otro implementado ;-)
- require who_is_authorized
- Indica a quién se le autoriza a acceder: usuarios y grupos concretos o cualquiera que sea un usuario válido.
Información de seguridad
- En el vector $_SERVER tenemos información sobre la conexión
- PHP_AUTH_USER o REMOTE_USER
- Contiene el usuario que se ha autentificado.
- PHP_AUTH_PW
- Contiene la clave con la que se ha autentificado sin cifrar.
- HTTP_REFERER
- Contiene la página desde la que hemos llegado a la página actual. Se puede utilizar para eliminar los accesos directos desde el exterior.