Nov
13

¿Como filtrar información que llega desde un formulario con PHP?

Esta entrada sólo es para presumir un poco de mis ideas locas para el filtrado de datos que llegan desde algún formulario.

Lo que hago es obtener todos los campos mediante un arreglo donde especifico cada unos de los campos que deberán o deberían estar ahí, y después los dejo listos para ser filtrados o guardados.

Así de fácil, simple y rápido:

Primer paso: Preparo un arreglo con los campos que debo filtrar ya sea para verificar que no estén vacíos o que simplemente existan, y filtrarlos.

php:
$campos = array(
        'tipo',
        'descripcion'=>"<b>Por favor introduce una descripci&oacute;n. Este campo es necesario\n",
        'autor',
        'nombre'=>"<p>Por favor, tu nombre es necesario. Escr&iacute;belo :)</p>\n",
        'url'
        );

Imaginariamente (lógica o internamente en la aplicación) estoy formando una agrupación de los datos así:

CampoMensaje de error
tipo 
descripcion<b>Por favor introduce una descripción. Este campo es necesario</p>\n
autor 
nombre<p>Por favor, tu nombre es necesario. Escríbelo :)</p>
url 

¿Que hago o para que me sirve este arreglo?

En la parte derecha tengo los nombres de los campos de los cuales suponemos que recibiremos información, y en la izquierda un mensaje de error en caso de que sea necesario mostrarlo al usuario que está enviándonos los datos.

  • Los campos que contienen vacía la columna mensaje de error, pueden o no existir en la entrada de datos desde el formulario (dicho con otras palabras: el usuario puede enviar vacío este campo.)
  • Los campos que si contienen un mensaje de error, deberán ser validados para forzar al usuario a que introduzca esta información.

Segundo paso: con el siguiente código, hago un recorrido por el arreglo en busca de cada uno de los campos y verifico que existan en _POST.

php:
                foreach($campos as $k => $v){
                                if(isset($k[1])){//El campo deberá existir
                                        if(!isset($_POST[$k]) or eregi('^ *$', $_POST[$k])){
                                                        $error = true;
                                                        echo $v;
                                                }else
                                                        $$v = $_POST[$k];
                                }else{//puede o no existir el campo
                                        if(isset($_POST[$v]))
                                                $$v = $_POST[$v];
                                                        else
                                                $$v = '';
                                }
                        }

Estos son los 4 casos que se presentan, y la solución que les doy:

  1. No exista el campo, pero si haya mensaje de error: muestro mensaje de error.
  2. Exista el campo, pero esté vacío: muestro mensaje de error.
  3. No exista el campo, pero no haya mensaje de error: dejo la variable de salida vacía.
  4. Exista el campo, pero no haya mensaje de error: Asigno el dato a la variable.

Nota: Si esto no queda claro, sigue leyendo al ver el resultado podría ser que se entienda un poco mejor esto.

Dicho el paso anterior, la información está lista para usarse, y debe quedar almacenada en las variables:

  • $tipo
  • $descripcion
  • $autor
  • $nombre
  • $url

Claro que si quisiéramos utilizar un arreglo para los datos de salida en vez de utilizar variables independientes, sólo hacemos unos cuantos cambios en el código:

php:
                foreach($campos as $k => $v){
                                if(isset($k[1])){//El campo deberá existir
                                        if(!isset($_POST[$k]) or eregi('^ *$', $_POST[$k])){
                                                        $error = true;
                                                        echo $v;
                                                }else
                                                        $campos[$v] = $_POST[$k];
                                }else{//puede o no existir el campo
                                        if(isset($_POST[$v]))
                                                $campos[$v] = $_POST[$v];
                                                        else
                                                $campos[$v] = '';
                                }
                        }

Y ahora obtenemos un resultado algo así:

  • $campos['descripcion']
  • $campos['autor']
  • $campos['nombre']
  • $campos['url']

Yo se que no es la gran cosa todo esto pero me ha ahorrado mucho tiempo y esfuerzo este pequeño script.

Si por favor, si. No olvides comentar!! Así que, por adelantado, gracias por tu comment, :P No seas malvado con mi código y apórtale alguna buena idea ;) Que aquí me tienes chambeando... :D

11 Comments

Make A Comment
  • a gravatar Edgar J. Suárez Said:

    Es una muy buena idea, simple pero poderosa :)

    Aunque.... la verdad es que soy muy flojo y por eso me cambié de PHP a Rails[1] jeje.

    [1] http://mimbles.net/articles/2007/09/24/validaciones-en-rails

  • a gravatar Stan Said:

    Te estas aventando unos post's muy interesantes de un tiempo para aca, vere que se puede hacer :D

  • a gravatar Victor De la Rocha Said:

    @Edgar J. Suárez: uff, yo mas flojo, por eso, no me cambio a rails :P ...

    @Stan: Pues ánimo :D póngase a aprender :) ... Aquí estamos pa lo que se ofrezca.

  • a gravatar Jesús Said:

    hola, que tal?? he estado leyendo un poco tus codigos y particularmente este, pero de verdad no entiendo mucho para que sirve. a ver segun pude entender quieres filtrar a que ninghun campo quede vacio verdad???? creo que eso es más facil con un javascript y aparte no te saca de la pagina, bueno todo esto en mi humilde opinión. cuando tenga mas tiempo seguire hechando un ojo en tu web quew en general esta muy buena para compartir conocimientos entre la comunidad de programadores

  • a gravatar Victor De la Rocha Said:

    Hola Jesús, gracias por tu dejarme tu punto de vista.

    Lo que trato de hacer con este código es filtrar, recibir o validar uno a uno los campos que recibo desde un formulario que entran en un documento.

    Se me da mucho la situación de que cambio de campos una y otra vez debido a cuestiones de trabajo por lo que tengo que estar haciendo un movedero de pequeños bloques de código para validar cada uno de los campos.

    Este código hace que yo no tenga que estar haciendo un pequeño bloque de código para validar (o recibir, filtrar) cada uno de los datos (o campos) y hacer todo de un solo golpe.

    Hacerlo con JavaScript es una solución siempre y cuando esté activado el JavaScript en el navegador, pero y... ¿si no está activado? Todos los campos se van ir sin validar. Es por eso que considero hacerlo desde PHP :)

    Gracias por dejar tu punto de vista, es muy bien bienvenido :D

  • a gravatar Victor De la Rocha Said:

    uuh! la onda con estas funciones de PHP5 para el filtrado y validado de datos provenientes de alguna fuente insegura :D

    http://www.php.net/manual/en/ref.filter.php

    De lujo!! ;)

  • a gravatar Juan Carlos Said:

    Ante todo mis disculpas por utilizar un comentario en un tema que no tiene nada que ver. Pero no encontré en el sitio un lugar de contacto. Agradecería me pudieras comentar como has logrado que en tu sabros.us se vean los thumbnails de los links. Desde ya muchas gracias.

  • a gravatar Victor De la Rocha Said:

    Hola @Juan Carlos, no te preocupes, todo bien.

    Para lograr que se vean los thumbnails, es necesario buscar en index.php al rededor de la línea 165, donde está algo como esto:

    php:
    echo "\t\t<img class=\"preview\" src=\"http://www.webshotspro.com/thumb.php?url=&quot;.htmlspecialchars($row["enlace"])."\" alt=\"".htmlspecialchars($row["title"])."\" />";

    y sustituirlo por esto:

    php:
    echo "\t\t<img class=\"preview\" src=\"http://sabros.us/thumbs/?url=&quot;.htmlspecialchars($row["enlace"])."&size=T\" alt=\"".htmlspecialchars($row["title"])."\" />";

    Esta información la obtuve de los foros de sabrosus (Aquí) No es cierto, no recuerdo de donde la obtuve, sólo recuerdo que de alguna forma Pedro Santana tuvo que ver en esto :) ... De cualquier forma jé, esa es la solución :D

  • a gravatar jonaytom Said:

    Aparte de la validación javascript antes de enviar el formulario, Para evitar que los hackers inserten código no deseado hagan sql o email injection también es recomendable hacer una validacion en el lado del servidor. Recomiendo usar una función como esta:

    php:
    function ValidarDatos($campo){
    //Array con las posibles cadenas a utilizar por un hacker
    $CadenasProhibidas = array("Content-Type:",
    //evita email injection
    "MIME-Version:", "Content-Transfer-Encoding:","Return-path:","Subject:","From:","Envelope-to:","To:","bcc:","cc:",
    "UNION",
    // evita sql injection
    "DELETE","DROP","SELECT","INSERT","UPDATE","CRERATE","TRUNCATE","ALTER","INTO","DISTINCT","GROUP BY","WHERE","RENAME","DEFINE","UNDEFINE","PROMPT","ACCEPT","VIEW","COUNT","HAVING","'",'"',"{","}","[","]",
     // evita introducir direcciones web
    "HOTMAIL","WWW",".COM","@","W W W",". c o m","http://",
    //variables y comodines
    "$", "&amp;","*");
     
    //Comprobamos que entre los datos no se encuentre alguna de
    //las cadenas del array. Si se encuentra alguna cadena se
    //dirige a la página anterior

    foreach($CadenasProhibidas as $valor){
        if(strpos(strtolower($campo), strtolower($valor)) !== false){
                    echo("
            alert('No puede introducir direcciones web, comillas, corchetes, código de programación o cualquier dato no relativo a los campos del formulario');
                    history.back();"
    );
            exit;
            }
        }
    }
    //Asignamos la variable POST y llamada a la función Validardatos($texto)
    $texto= $_POST["texto"];
    ValidarDatos($texto);

  • a gravatar Victor De la Rocha Said:

    Si, buen punto. Antes deutilizar cualquier tipo de dato en una consulta sql o en un envío de emails hay que sanitizar los datos.

    Para utilizar en consultas SQL utilizo una función mas sencilla:

    php:
    function sql_quote($value){
            if(get_magic_quotes_gpc())
            $value = stripslashes($value);
           
            //check if this function exists
            if(function_exists("mysql_real_escape_string"))
                    $value = mysql_real_escape_string( $value );
                else//for PHP version < 4.3.0 use addslashes
                    $value = addslashes( $value );
           
            return $value;
        }

    Para utilizarla, solo hay que aplicarle a la cadena a filtrar la función y listo.

    php:
    $password = sql_quote($_POST['password']);
    $query = mysql_query("SELECT * FROM usuarios WHERE usuario='admin' AND password='$password');

    Y para evitar la alteración de el funcionamiento normal de las funciones de envío de emails, realmente no tengo idea pero creo que al final de cuentas es lo mismo.

    Para evitar eso siempre utilizo procedimientos para asegurarme de que el email al que enviaré la información "REALMENTE sea un email", y en cuanto a las cabeceras (o headers), no las verifico y ni tampoco permito al usuario que las modifique.

    Algo así hago para el envío de emails, aunque ya tengo mi versión mejorada en algúna de mis aplicaciones que estoy trabajando, pero esta es la versión que tengo online y la pueden encontrar en el código de sabros.us.

    php:
    /// Funcion sacada de sabrosus, modificada por Victor Bracco...
    function enviaMail($to, $title, $body, $from) {
           $rp     =
    trim($from);
           $org    = " sabros.us";
           $mailer = "sabros.us Mailer";

           $head   = '';
           $head  .= "Content-Type: text/html \r\n";
           $head  .= "Date: ". date('r'). " \r\n";
           $head  .= "Return-Path: $rp \r\n";
           $head  .= "From: $from \r\n";
           $head  .= "Sender: $from \r\n";
           $head  .= "Reply-To: $from \r\n";
           $head  .= "Organization: $org \r\n";
           $head  .= "X-Sender: $from \r\n";
           $head  .= "X-Priority: 3 \r\n";
           $head  .= "X-Mailer: $mailer \r\n";

           $body   = str_replace("\r\n", "\n", $body);
           $body   = str_replace("\n", "\r\n", $body);
           if(is_array($to)
           {
                for_each($to as $suscriptor)
                {
                        @mail($to, $title, $body, $head);
                }
           } else {
                        @mail($to, $title, $body, $head);
           }

  • a gravatar Victor De la Rocha Said:

    uff, que apuro me está sacando este código en estos momentos... uff uff uff

Comments RSS Feed   TrackBack URL

Leave a comment

top