Formularios 101: Validación y Envio

  • Ene
  • 28

6 comentarios! 432 palabras - 1 hits

Scripts de validación y envío para un formulario de contacto.

En esta segunda parte tratare de mostrar algunas técnicas de validación y envió mediante lenguaje de servidor, mas concretamente utilizando lenguaje PHP.

Hablando en seudocodigo lo que vamos a hacer es comprobar que todos los campos requeridos contengan datos y que estos estén en el formato adecuado, informado al usuario del error en el caso de que esto no se cumpla o enviando el correo una vez se cumplan todas las condiciones.

Para empezar definimos las variables con las que trabajaremos,

  1.  
  2.     <?php
  3.         // Desactivamos el control de errores de PHP
  4.         ini_set('display_errors',0);
  5.  
  6.         // Saneamos la variable $_POST
  7.         $_POST = (get_magic_quotes_gpc() ? array_map('stripslashes', $_POST) : $_POST);
  8.  
  9.         // Capturamos los datos en variables
  10.         $name = $_POST['cname'];
  11.         $email = $_POST['cmail'];
  12.         $note = $_POST['ctext'];
  13.  
  14.         // Expresión regular para comprobar los intentos de abuso
  15.         $header_injection_regex = "(\r|\n)(content-type|Content-Type|to:|from:|cc:|bcc:)";
  16.  
  17.         // Array con los nombres de los campos obligatorios
  18.         $req_fields = array(
  19.             "cname"=> nombre,
  20.             "cmail"=> email,
  21.             "ctext"=> mensaje
  22.         );
  23.    
  24.         // Comprobación del estado de la variable register_globals
  25.         $register_globals = (bool) ini_get('register_gobals');
  26.     ?>
  27.  

Para facilitarnos el trabajo a posteriori estas variables las definimos en un fichero aparte que llamare config.inc.php.

El siguiente paso es definir las funciones que utilizaremos para procesar los datos, existen numerosos métodos para comprobar una dirección de correo y otros tantos para enviar un correo con PHP, en este ejercicio utilizare algunas funciones básicas mas que nada por ilustrar de manera sencilla los pasos a dar.

La primera función comprueba el formato de la dirección de correo mediante expresiones regulares, sin duda esta es la función mas controvertida debido a la amplia variedad de direcciones de correo existentes. Después de probar muchos métodos he decidido utilizar este por considerarlo el que mas variantes acepta.

La función devolverá true o false y utiliza una variable de $_SESSION para contener los mensajes de error.

  1.  
  2.     <?php
  3.         function check_email_address() {
  4.             global $mail; // utilizamos la variable $mail definida de manera global
  5.             if (!ereg("^[^@]{1,64}@[^@]{1,255}$", $email)) {
  6.                     $_SESSION['error'] = '';
  7.                     return false;
  8.             }
  9.             $email_array = explode("@", $email);
  10.             $local_array = explode(".", $email_array[0]);
  11.             for ($i = 0; $i < sizeof($local_array); $i++) {
  12.                 if (!ereg("^(([A-Za-z0-9!#$%&'*+/=?^_`{|}~-][A-Za-z0-9!#$%&'*+/=?^_`{|}~\.-]{0,63})|(\"[^(\\|\")]{0,62}\"))$", $local_array[$i])) {
  13.                     $_SESSION['error'] = '';
  14.                     return false;
  15.                 }
  16.             }
  17.             if (!ereg("^\[?[0-9\.]+\]?$", $email_array[1])) {
  18.                 $domain_array = explode(".", $email_array[1]);
  19.                 if (sizeof($domain_array) < 2) {
  20.                     $_SESSION['error'] = '';
  21.                     return false;
  22.                 }
  23.                 for ($i = 0; $i < sizeof($domain_array); $i++) {
  24.                     if (!ereg("^(([A-Za-z0-9][A-Za-z0-9-]{0,61}[A-Za-z0-9])|([A-Za-z0-9]+))$", $domain_array[$i])) {
  25.                         $_SESSION['error'] = '';
  26.                         return false;
  27.                     }
  28.                 }
  29.             }
  30.             return true;
  31.         }
  32.     ?>
  33.  

La siguiente función se encarga de comprobar que los campos obligatorios no estén vacíos, para ello creamos un array que contenga los nombres de dichos campos. La función devuelve true o false y una variable de $_SESSION para contener los mensajes de error.

  1.  
  2.     <?php
  3.     function check_empty_fields($method = "post") {                                                                                
  4.         global $req_fields; // variable global que contiene el array de campos obligatorios                                                                              
  5.             $errors = ""; // variable temporal que contendrá el array con los errores
  6.             $count_empty = 0;                                                                                                        
  7.             foreach ($req_fields as $key => $val) {                                                                                    
  8.                 $field_name = (array_key_exists($key, $req_fields)) ?  $req_fields[$key] : $key;                                      
  9.                 if (empty($_POST[$key])) {                                                                                            
  10.                     $_SESSION[$key] = true;                                                                                            
  11.                     $errors .= "|".$field_name;                                                                                        
  12.                     $count_empty++;                                                                                                    
  13.                 } else {                                                                                                              
  14.                     $_SESSION[$key] = false;                                                                                          
  15.                 }                                                                                                                      
  16.            }
  17.            if ($count_empty == 0) {                                                                                                  
  18.                return true;
  19.            } else {
  20.                $_SESSION['error'] = '';                  
  21.                $_SESSION['error'] .= "<ul>\n";                                                                                        
  22.                $msg_parts = explode("|", ltrim($errors, "|"));                                                                        
  23.                $num_parts = count($msg_parts);                                                                                        
  24.                for ($i = 0; $i < $num_parts; $i++) {                                                                                  
  25.                    $_SESSION['error'] .= $msg_parts[$i];                                                                              
  26.                    if ($i <= $num_parts - 2) {                                                                                        
  27.                        $_SESSION['error'] .= ($i == $num_parts - 2) ? " &amp; " : ", ";                                              
  28.                    }                                                                                                                  
  29.                }                                                                                                                      
  30.                $_SESSION['error'] .= "</ul>\n";                                                                                      
  31.                return false;                                                                                                          
  32.           }                                                                                                                          
  33.     }
  34.     ?>
  35.  

Para acabar con las funciones de validación, queda la función que comprobara que no se esta utilizando el formulario con fines fraudulentos, para conseguir esto utilizamos una serie de expresiones regulares que devolverán verdadero o falso

  1.  
  2.     <?php
  3.         function headerInjectionFilter($reply_to_field, $reply_to_name) {                                                              
  4.             global $header_injection_regex;                                                                                             // variable global que contiene la expresión regular
  5.             if(strlen($reply_to_field) <= 0) return false;                                                                            
  6.             if(eregi($header_injection_regex,$reply_to_field)) return false;                                                          
  7.             if(eregi($header_injection_regex,$reply_to_name)) return false;                                                            
  8.             return true;                                                                                                              
  9.        }
  10.     ?>
  11.  

Todas estas funciones las guardaremos en un fichero al que llamare functions.inc.php, podríamos realizar muchas mas comprobaciones, si buscamos un poco en la red, encontraremos infinidad de scripts que nos pueden dar ideas de como asegurar un poco mas este tipo de procesos.

Para acabar con nuestro sistema de contacto solo nos queda el script que recogerá los datos del formulario y los procesara utilizando las funciones que acabamos de definir, le llamaremos queries.php,

  1.  
  2.     <?php
  3.         session_start();                                                                                                              
  4.         require_once('functions.inc.php');                                                                                      
  5.         if(isset($_POST['cvalid'])) {                                                                                                    
  6.             $valid = $_POST['cvalid'];                                                                                                      
  7.             switch($valid) {
  8.                 case true :                                                                                                        
  9.                 if(check_empty_fields()) {                                                                                        
  10.                     if(headerInjectionFilter($_POST['cmail'], $_POST['cname'])) {                                            
  11.                         if(check_email_address()) {                                                                  
  12.                             send_email();                                                                                          
  13.                         }                                                                                                          
  14.                     } else {                                                                                                      
  15.                         $_SESSION['error'] = '';
  16.                     }                                                                                                              
  17.                 }                                                                                                                  
  18.                 $_SESSION['msg'] = $_SESSION['error'];                                                                            
  19.                 unset($_SESSION['error']);                                                                                        
  20.                 header('Location: '.$referringPage);                                                                              
  21.                 break;                                                                                                                
  22.                 default:                                                                                                              
  23.                     die('Error de parametros');                                                                                        
  24.                 break;
  25.             }
  26.         }
  27.         ?>
  28.  

En esta fase de nuestro ejercicio ya tenemos un formulario funcional, dejo disponibles para descargar todos los scripts que he utilizado:

Para acabar esta serie, con el siguiente articulo tratare de ilustrar como es posible mejorar la experiencia del usuario aprovechando la potencia de la librería jquery.

6 comentarios

  • Ene
  • 29

# Escrito por Chris Hoeppner [TypeKey Profile Page] hace 3 años, 1 mes

Para comprobar las direcciones de email, podrías usar la expresión regular creada por shaun inman. Es la solución más completa de la que tengo noticia.


  • Feb
  • 01

# Escrito por teimagino.com hace 3 años, 1 mes

Gracias por esta estupenda referencia. Me ha parecido un tema muy interesante.

Sigo tu blog habitualmente, me encanta lo que estas haciendo y te animo a seguir por este camino..

Mi blog recoge temas muy similares y hay muchas referencias culturales, tecnológicas, politicas… Te invito a visitarlo. De verdad que tengo material MUY bien seleccionado. Recibe mi apoyo y un saludo afectuoso

http://teimagino.com/index.php/


  • Feb
  • 01

# Escrito por Diego hace 3 años, 1 mes

Warning: Invalid argument supplied for foreach() in /home/kerberos/public_html/blog/wp-content/themes/mi estilo/contact/scripts/contact.php on line 141

Estoy probando el formulario que hiciste denominado AjaxContactForm y me sale ese error me puedes ayudar?


  • Feb
  • 06

# Escrito por carmen hace 3 años, 1 mes

hola recién te escribí que no podía usar el formulario , me sugeriste usara este otro, lo hice pero no encuentro dónde debo poner mi mail para recibirlo Gracias por contestarme Carmen


  • Feb
  • 20

# Escrito por Jose Manuel hace 3 años

Hola, Como estan todos, el formulario aparente mente funciona, no muestra ningun error, el problema es que el mensaje no llega a mi correo, lo he probado con los dos formularios y nada, no se si hotmail o gmail tiene que ver algo o no se, quisiera que porfavor unos de ustedes me ayude, Gracias..


  • Mar
  • 15

# Escrito por Alberto hace 2 años, 12 meses

Hola, los artículos sobre el formulario PHP son muy interesantes. No obstante, me gustaría saber qué scripts deben utilizarse para que cada usuario efectúe un único envío de datos (imaginemos a un spamer lanzando andanadas continuas desde el formulario), y también para que esos datos no aparezcan al retroceder el navegador. Asimismo sería interesante conocer cómo evitar que un usuario envíe caracteres no autorizados, esto es, que no se envíen letras desde campos de texto reservado para números y viceversa.


Escribe tu comentario

Puedes utilizar este formulario para escribir tu opinion sobre esta entrada, no existe ningun tipo de limitacion a la hora de enviar opiniones, tan solo sigue unas reglas basicas de cortesia y todos estaremos mas contentos.

Puedes identificarte utilizando OpenID, solo tienes que introducir tu URL OpenID en el siguiente campo y pulsar el boton de validar.





Instrucciones para los comentarios

El simbolo * indica que se trata de un campo obligatorio.

Este sitio usa Markdown junto con Smartypants para educar los textos, tambien esta disponible para los comentarios.

A continuación os muestro algunas de las equivalencias:

  • [enlace de ejemplo](http://example.com/) resulta enlace de ejemplo.
  • **Texto en Negrita**
  • _Italica_
  • > blockquote
  • > > nested blockquote
  • * Esto es un elemento de una lista desordenada (ul)
  • 1. Esto es un elemento de una lista ordenada (ol)

MC Puedes seguir las respuestas a tus comentarios con MyComments.