PHP é à quinta-feira – Validação de dados introduzidos

17 Comentários

Por Pedro Peixoto para o PPLWARE

No último artigo tivemos a necessidade de efectuar a conversão entre diferentes tipos de codificação. Esta tarefa ocorre mais frequentemente quando é necessário ler, armazenar ou apresentar dados em diferentes charsets. Um vez que o armazenamento e a apresentação dos dados são tarefas controladas pelo programador, é aquando da introdução dos dados que temos de ter mais atenção. O utilizador é imprevisível, é alguem em quem nunca podemos confiar, o elo mais frágil num sistema que a qualquer altura, seja acidentalmente ou intencionalmente, pode estragar o programa.

Hoje vamos aprender a controlar com segurança a introdução de dados por parte de um utilizador.

Entre as inúmeras possibilidades de erros que o utilizador pode causar, podemos destacar algumas que passaremos a explicar e a propôr uma solução (entre tantas outras).

php

Introdução de caracteres de outra codificação

Podem causar uma má apresentação/armazenamento de dados

Devemos ter em atenção qual o tipo de codificação usado na base de dados, e qual usamos na apresentação dos mesmos. Como usamos uma linguagem com codificação iso-8859-1 as duas função mais usadas serão :

$stringconvertida=utf8_encode($stringporconverter) ; //recebe uma string Latin1 e retorna a string em UTF8

$stringconvertida=utf8_decode($stringporconverter) ; //recebe uma string UTF8 e retorna a string Latin1

Introdução de aspas, plicas ou caracteres especiais

Podem danificar uma query sendo interpretadas pelo driver

Usualmente os drivers das bases de dados para PHP interpretam as plicas/aspas como caracteres de delimitação de strings, assim temos de evitar a sua presença no texto digitado pelo utilizador.

Para converter caracteres especiais (&,plicas,aspas,>,<) em códigos html não interpretados pelo driver vamos usar a seguinte função :

stringconvertida=htmlspecialchars($stringporconverter,ENT_QUOTES,’ISO8859-1’) ;
  • ‘&’ passa a ‘&amp;’
  • ‘”‘ passa a ‘&quot;’ se a flag ENT_NOQUOTES não estiver activa.
  • ”’ passa a ‘&#039;’ só se a flag ENT_QUOTES estiver activa.
  • ‘<‘ passa a ‘&lt;’
  • ‘>’ passa a ‘&gt;’

Introdução de um texto com tamanho superior ao definido na base de dados

Causa um erro na query de inserção na base de dados

$stringcortada=substr ($stringinteira , $inicio, $fim )

Esta função corta a string devolvendo apenas o texto entre a posição de início e de fim. Para o nosso caso o $inicio será 0 e o $fim sera o número máximo de caracteres a usar :

$res = substr('abcdef', 0, 4);  // abcd

No entanto podem-se usar combinações mais complexas para outros efeitos. Por exemplo :

$res = substr('abcdef', 1);         // bcdef
$res = substr('abcdef', 1, 3);     // bcd
$res = substr('abcdef', 0, 8);     // abcdef
$res = substr("abcdef", 0,4);     // abcd
$res = substr("abcdef", -1);      // f
$res = substr("abcdef", -2);      // ef
$res = substr("abcdef", -3, 1);  // d

Introdução de um texto com um tipo de dados errado

Podemos deduzir que os dados estão errados

Quando temos campos como email, telefone ou até mesmo NIF, convém validar se o valor introduzido está no formato correcto. Para isso recorremos a expressões regulares. Uma expressão regular é uma string com um formato padrão. Mas só as expressões regulares davam outro artigo, por isso deixo aqui o link para uma página com vários exemplos : http://www.roscripts.com/PHP_regular_expressions_examples-136.html

A função preg_match permite-nos verificar se uma determinada string cumpre o padrão da expressão regular.

if (preg_match ( $expressaoregular, $string)) 
 
echo ‘valido’ ;
 else
 echo ‘invalido’ ;

No exemplo a seguir efectuamos a validação de um número decimal :

$valorintroduzido = "9,99";
 
if (preg_match( '/^[\-+]?[0-9]*\.*\,?[0-9]+$/', $valorintroduzido)) {
return true;
 }

Para efectuar a validação de outro tipo de dados, bastava substituir a expressão respectiva, por exemplo, para validar um email a expressão regular seria : ‘^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$’.

Introdução de código HTML

Pode ser desde simples tags que alteram a apresentação dos dados, até ao uso de javscript que será interpretado pelo browser aquando da apresentação

Este é sem dúvida um ponto crítico, imaginemos que estamos a fazer um guestbook em PHP e não validamos o texto introduzido. Um utilizador pode introduzir na mensagem o seguinte texto :

<script>window.location= ‘https://pplware.sitedev.pt’</script>

A partir desse momento os utilizadores que abrissem o guestbook seriam reencaminhados para a nossa página.

Outro utilizador poderia também colocar o seu comentário entre as tags <h1> para o destacar em relação aos outros… No fundo é uma porta aberta para utilizadores mal intencionados.

Assim sendo, e para solucionar este problema recorremos à função strip_tags :

$texto = '<p>Teste </p> <a href="https://pplware.sitedev.pt">outro texto</a>';

echo strip_tags($texto); // Teste outro texto

É possível permitir algumas tags usando o segundo parâmetro

// Permitir 

e echo strip_tags($texto, '

'); //

Teste

outro texto

Para além desta função podemos recorrer á htmlentities() que tem um comportamento semelhante à htmlspecialchars() que já vimos num ponto acima, a diferença é que esta transforma todas as tags em código HTML, pode ser usada por exemplo quando queremos permitir que o utilizador escreva código HTML, mas sem que ele seja interpretado pelo browser.

$string = "Exemplo  usando bold";
echo htmlentities($str); // Exemplo usando <b>bold</b>

Conclusão

Quando usadas em conjunto estas funções permitem um controlo seguro da introdução de dados por parte dos utilizadores. Cabe a cada um adapta restas funções às suas necessidades. Sugerímos a construção de uma função que conjugue algumas destas regras de modo a ser usada cada vez que inserimos dados na base de dados. Aqui fica um exemplo :

function preparaString($str,$maxlength)
         {
                   return substr(utf8_decode(htmlspecialchars(strip_tags($str), ENT_QUOTES,'ISO8859-1')),0,$maxlength);
         }

Partilhar:
Tags:

Comentários

17

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

  1. Avatar de Mestre
    Mestre

    Muito bom!!! era isto mm que precisava. Obrigado!!

    1. Avatar de Renato
      Renato

      Precisavas disto? LOL….
      -.-”
      ….

      Também eu xD

  2. Avatar de César Couto

    function clear($var) { $var = trim($var); $var = strip_tags($var); $var = htmlspecialchars($var); return $var; }
    function clear_db($var) { $var = trim($var); $var = strip_tags($var); $var = htmlspecialchars($var); $var = (! get_magic_quotes_gpc ()) ? addslashes ($var) : $var; return $var; }
    function magic($var) { $var = trim($var); $var = strip_tags($var); $var = (!get_magic_quotes_gpc ()) ? addslashes ($var) : $var; return $var; }
    function blank($content) { $check = str_replace(” “, “”, $content); if ($check) return false; else return true; }
    function clear_slashes($var) { $var = str_replace(‘”‘,”,$var); $var = str_replace(‘\”,”,$var); return $var; }

    Esta são algumas das mini funções que uso constantemente ora no desenvolvimento de páginas web (nas administrações, formulários de contactos, etc) e também em software web desenvolvido em PHP/MYSQL/ETC.

    Uma das que uso mais é a magic e adiciono o trim para remover espaços vazios porque as vezes as pessoas fazem copy paste e deixa espaços vazios no fim ou no inicio das strings e é sempre bom limpar e a função get_magic_quotes_gpc para ver se será necessário converter ou não as slashes quando são inseridas nas base de dados.

    1. Avatar de Rogério
      Rogério

      Não uses o get_magic_quotes_gpc, é vulnerável a SQLInjection, usa antes o mysql_real_escape_string, foi adicionado com o propósito de substituir o get_magic_quotes_gpc, é muito mais seguro e escapa mais caracteres que o addslashes.

      Certifica-te de que o get_magic_quotes_gpc está desactivado no php.ini, não vá a porca torcer o rabo.

      Já agora, muito bom tópico, apesar de isto ser o básico das validações / seguranças que os programadores devem ter em conta quando criam as suas páginas web.

      Validações por expressões regulares, são muito mais fiáveis e seguras, pois basta haver algo na string que a expressão regular não valide, para dar logo erro.

  3. Avatar de Ricardo Elias
    Ricardo Elias

    Excelente tutorial Pedro Peixoto! Parabens!


    “magic_quotes_gpc: Este recurso tornou-se OBSOLETO a partir do PHP 5.3.0 REMOVIDO do PHP 6.0.0. Confiar neste recurso é extremamente não recomendado.”
    http://www.php.net/manual/pt_BR/security.magicquotes.php

    Fiquem Bem!

  4. Avatar de Pedro Pinto

    Parabéns Pedro pelo excelente tutorial !! PHP Rullez 🙂

  5. Avatar de Carlos Martins
    Carlos Martins

    Boas

    Desde o PHP5 que estão disponiveis filtros para limpar e validar dados.

    Para quem precisa, pode ser uma leitura interessante
    PHP Filter -> http://www.w3schools.com/php/php_ref_filter.asp

  6. Avatar de Pedro Peixoto

    Boa noite, obrigado. É bom que opinem para que saiba o qual o ruma a dar nos próximos artigos. 🙂

  7. Avatar de Boas Oportunidades

    Penso que o exemplo de validação do endereço de email não está correcto.

    A título de exemplo, pode-se aceitar, mas não usem essa expressão num sistema que necessite mesmo de validar endereços.

    1. Avatar de Pedro Peixoto

      Boa noite, porque diz que não está correcta?

      1. Avatar de Boas Oportunidades

        Porque logo para começar, aceita endereços que começem por um ponto, e esses não são válidos.
        Também não aceita todos os caracteres que deveria aceitar de acordo com o RFC.

        1. Avatar de Renato
          Renato

          pois.. concordo com isso… este é só um exemplo de validação…
          Por falar em validação… penso que deveriam incluir um tutorial de RegEx juntamente, ou antes de falarem em validações que utilizem essa forma de expressão.

          1. Avatar de Pedro Peixoto

            Certo. Existem muitas maneiras de construir uma expressão regular que valide emails ou outro tipo de dados. Normalmente todas têm falhas, e quanto menos falhas têm mais complexas ficam. O objectivo foi só mesmo exemplificar. Copiei uma expressão do site que inclui no artigo, só para emails têm la 4 ou 5. De qualquer forma podem partilhar as que vocês usam para podermos comparar. Abraço

    2. Avatar de DreamWave
      DreamWave

      Pois aparentemente não valida um endereço de email correctamente , por exemplo nao aceitaria um email “meu+email@gmail.com” ou “email@dominio.co.uk”

      Costumo uitilizar esta função, (se o wordpress cortar alguma parte do codigo podem ver aqui http://pastebin.com/2HnGi2Kw) :

      function validEmail($email, $checkDNS=false){
      $isValid = true;
      $atIndex = strrpos($email, “@”);
      if (is_bool($atIndex) && !$atIndex){
      $isValid = false;
      } else {
      $domain = substr($email, $atIndex+1);
      $local = substr($email, 0, $atIndex);
      $localLen = strlen($local);
      $domainLen = strlen($domain);
      if ($localLen 64) {
      // local part length exceeded
      $isValid = false;
      } else if ($domainLen 255){
      // domain part length exceeded
      $isValid = false;
      } else if ($local[0] == ‘.’ || $local[$localLen-1] == ‘.’){
      // local part starts or ends with ‘.’
      $isValid = false;
      } else if (preg_match(‘/\\.\\./’, $local)){
      // local part has two consecutive dots
      $isValid = false;
      } else if (!preg_match(‘/^[A-Za-z0-9\\-\\.]+$/’, $domain)) {
      // character not valid in domain part
      $isValid = false;
      } else if (preg_match(‘/\\.\\./’, $domain)){
      // domain part has two consecutive dots
      $isValid = false;
      } else if (!preg_match(‘/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\’*+?^{}|~.-])+$/’, str_replace(“\\\\”,””,$local))){
      // character not valid in local part unless
      // local part is quoted
      if (!preg_match(‘/^”(\\\\”|[^”])+”$/’, str_replace(“\\\\”,””,$local))) {
      $isValid = false;
      }
      }
      if($checkDNS){
      if ($isValid && !(checkdnsrr($domain,”MX”) || checkdnsrr($domain,”A”))){
      // domain not found in DNS
      $isValid = false;
      }
      }
      }
      return $isValid;
      }

  8. Avatar de Nilton
    Nilton

    Preciso retirar o campo data da validação vazio, alguém pode me ajudar. Passo mais detalhes no email.