PHP é à quinta-feira – Validação de dados introduzidos
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).
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</em> |
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 '&'
- '"' passa a '"' se a flag ENT_NOQUOTES não estiver activa.
- ''' passa a ''' só se a flag ENT_QUOTES estiver activa.
- '<' passa a '<'
- '>' passa a '>'
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)) {</em> 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= ‘http://pplware.sapo.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="http://pplware.sapo.pt">outro texto</a>'; |
echo strip_tags($texto); // Teste outro texto
É possível permitir algumas tags usando o segundo parâmetro
// Permitir <p> e <a> echo strip_tags($texto, '<p><a>'); //<p>Teste </p> <a href="http://pplware.sapo.pt">outro texto</a> |
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 <b>bold</b>"; 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); } |
Este artigo tem mais de um ano
Muito bom!!! era isto mm que precisava. Obrigado!!
Precisavas disto? LOL….
-.-”
….
Também eu xD
lol tb eu
LOLd
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.
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.
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!
Parabéns Pedro pelo excelente tutorial !! PHP Rullez 🙂
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
Boa noite, obrigado. É bom que opinem para que saiba o qual o ruma a dar nos próximos artigos. 🙂
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.
Boa noite, porque diz que não está correcta?
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.
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.
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
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;
}
Preciso retirar o campo data da validação vazio, alguém pode me ajudar. Passo mais detalhes no email.