Posts Tagged php

Captcha – Confirmação Visual

Depois de um bom tempo com o blog parado, vou voltar explicando um modo de desenvolver um captcha utilizando a biblioteca GD do php. O captcha é um teste de turing reverso, pois é a máquina que  testa se o usuário é humano. Este teste evita que sistemas automatizados enviem spans pelos formulários de seu site.
A idéia é bem simples. Vamos ter um arquivo php que gera uma imagem, podendo ser exibido como se de fato fosse uma imagem:

<img src=”geraImagemConfirmacao.php” alt=”Captcha” />

Essa imagem será gerada, e o conteúdo gravado em um cookie. Este cookie será utilizado na ação de seu formulário, quando deverá ser comparado com o texto digitado pelo usuário. Vou procurar fazer o mais simples possível:

<form action=”acaoConfirmaCodigo.php” method=”post”><img src=”geraImagemConfirmacao.php” alt=”Captcha” />
<input name=”palavraUsuario” type=”text” />

<input type=”submit” />

</form>

Salve este arquivo com um nome qualquer.

No arquivo acaoConfirmaCodigo.php, coloque algo do tipo:

<?php

$palavraUsuario = strtolower($_POST['palavraUsuario']);
$palavraGerada = strtolower($_COOKIE['palavraGerada']);

if($palavraUsuario == $palavraGerada)
echo “Confirmação visual correta.”;
else
echo “Por favor, tente novamente.”;
?>

O que este arquivo faz nada mais é do que pegar a palavra digitada pelo usuário (enviada pelo POST) e a palavra armazenada no cookie, passando ambas para a forma minúscula, e então  comparando-as.

Agora vamos à parte realmente interessante, o arquivo geraImagemConfirmacao.php:

<?php

$larguraImg = 100;
$alturaImg = 30;

$espacoMinLetrasX = 15;
$espacoMaxLetrasX = 20;

$espacoMinLetrasY = 5;
$espacoMaxLetrasY = 10;

$numLetras = 4;

$letras = array(’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9′, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘Z’, ‘K’, ‘M’, ‘X’);

// cria uma imagem
$imagem = imagecreate($larguraImg, $alturaImg);

/* Cores para utilizar na imagem imagem */
$cinza = imagecolorallocate($imagem,0xF8,0xF8,0xF8);
$cinza_escuro = imagecolorallocate($imagem,0xAC,0xAC,0xAC);
$vermelho = imagecolorallocate($imagem,0xFF,0×00,0×00);
$azul = imagecolorallocate($imagem,0x0F,0×93,0xFF);
$verde = imagecolorallocate($imagem,0×00,0×66,0×00);
$preto = imagecolorallocate($imagem,0×00,0×00,0×00);
$laranja = imagecolorallocate($imagem,0xFF,0x8C,0×24);

$cores = array($vermelho, $azul, $verde, $preto);

$tamanho_letras = count($letras)-1;
$tamanho_cores = count($cores)-1;

/* Escrevendo as letras… */
$palavraGerada = ”;
$x = 0;

for($i=0;$i<$numLetras;$i++){

$x += rand($espacoMinLetrasX, $espacoMaxLetrasX); //localizacao horizontal
$y = rand($espacoMinLetrasY, $espacoMaxLetrasY);

$j = rand(0,$tamanho_cores);

$k = rand(0,$tamanho_letras);
$palavraGerada .= $letras[$k];

imagestring($imagem, 5, $x, $y, $letras[$k], $cores[$j]); //escreve a letra na imagem
}

setcookie(‘palavraGerada’, $palavraGerada, time()+7200);

header(“Content-type: image/jpeg”);
imagejpeg($imagem);
imagedestroy($imagem);
?>

A primeira parte é apenas para configurar a imagem que será gerada:

$larguraImg = 100;
$alturaImg = 30;

Note que essas dimensões têm que ser compatíveis com a quantidade de letras e o espaçamento das letras que você deseja gerar, caso contrário algumas letras ficarão fora da imagem simplesmente por falta de espaço.

$espacoMinLetrasX = 15;
$espacoMaxLetrasX = 20;
$espacoMinLetrasY = 5;
$espacoMaxLetrasY = 10;
$numLetras = 4;

Aqui são determinados os intervalos das posições das letras na imagem. Por exemplo, a posição horizontal (espaço entre as letras) irá variar de 15 a 20px. Para realizar essa variação, utilizamos a função rand(min, max) do php.
E também aqui é determinada a quantidade de letras que serão geradas na imagem.

$letras = array(’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9′, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘Z’, ‘K’, ‘M’, ‘X’);

Esse array contém as letras que poderão ser sorteadas e aparecer na imagem. Procure evitar letras como O, I, L… e os números 0 e 1, pois podem ser confundidos com facilidade.

// cria uma imagem
$imagem = imagecreate($larguraImg, $alturaImg);

/* Cores para utilizar na imagem imagem */
$cinza = imagecolorallocate($imagem,0xF8,0xF8,0xF8);
$cinza_escuro = imagecolorallocate($imagem,0xAC,0xAC,0xAC);
$vermelho = imagecolorallocate($imagem,0xFF,0×00,0×00);
$azul = imagecolorallocate($imagem,0x0F,0×93,0xFF);
$verde = imagecolorallocate($imagem,0×00,0×66,0×00);
$preto = imagecolorallocate($imagem,0×00,0×00,0×00);
$laranja = imagecolorallocate($imagem,0xFF,0x8C,0×24);

$cores = array($vermelho, $azul, $verde, $preto);

Neste ponto, criamos a imagem, e associamos as cores que utilizaremos na imagem. Além disso, coloco no array $cores as cores que serão sorteadas para cada letra. (Note mais uma vez que você deve facilitar a vida do usuário, então utilize cores fortes nas letras).

$palavraGerada = ”;
$x = 0;
for($i=0;$i<$numLetras;$i++){

$x += rand($espacoMinLetrasX, $espacoMaxLetrasX); //localizacao horizontal
$y = rand($espacoMinLetrasY, $espacoMaxLetrasY);

$j = rand(0,$tamanho_cores);

$k = rand(0,$tamanho_letras);
$palavraGerada .= $letras[$k];

imagestring($imagem, 5, $x, $y, $letras[$k], $cores[$j]); //escreve a letra na imagem
}

Aqui é onde acontece toda a mágica. É executado um laço, com o for varrendo a quantidade de letras de sua imagem, e para cada letra sortea-se a posição x e y, dentro do intervalo configurado. Note que o intervalo x deve ser incrementado a cada iteração, caso contrário todas as letras ficariam dentro de um mesmo intervalo na horizontal (experimente trocar o += por =, para ver como fica).

Também são sorteadas a letra e sua cor, dentro do array pré-determinado. Só então a letra é gravada na imagem, com a função imagestring() do php.

setcookie(‘palavraGerada’, $palavraGerada, time()+7200);

header(“Content-type: image/jpeg”);
imagejpeg($imagem);

Finalmente a imagem é gravada no cookie e criada na tela, utilizando o cabeçalho Content-type: image/jpeg. Pronto!

Se achar conveniente, você pode utilizar outras funções da GD como imagearc, imagelin.. para “dificultar” a visualização da imagem (cuidado para não deixar a imagem imcompreensível). Pode também utilizar outra fonte para as letras, outra cor de fundo na imagem..

4 Comments

URLs Amigáveis – .htaccess

Urls amigáveis são as urls “semânticamente corretas”; possuem um sentido e são compreensíveis a usuários leigos. Além da vantagem estética, as urls amigáveis ajudam as máquinas de busca na indexação, e são interessantes no sentido de “esconder” a tecnologia que está sendo utilizada.

Por exemplo:
www.meusite.com.br/exibeFotos.php?idAlbum=2&idFoto=35

Nesta url, vê-se que seu site utiliza o php, além de serem exibidas explicitamente duas variáveis GET.

Com a url amigável, você poderia deixar:
www.meusite.com.br/exibeFotos/2/35

Vou explicar aqui um modo de fazer, utilizando o arquivo .htaccess e php.

O .htaccess é um arquivo do apache, utilizado por exemplo para dar permissão de acesso à pastas do servidor. No nosso caso, ele será o “tradutor” das urls.

O .htaccess não transforma a url comum em url amigável. Ao contrário, traduz a url amigável em url “normal”. O que ele faz basicamente é ler a url do browser do usuário (a url amigável), enviada na forma de requisição para o servidor web, e tenta “casar” a url com uma séria de regrinhas. Ao encontrar uma regra que se encaixa com a url, ela traduz para o termo correspondente, ou seja, a url normal. E é esta url que é enxergada pelo php no servidor.

Crie, ou se já existir, edite o .htaccess da pasta raiz de seu site. (sugiro que leiam um pouco sobre o .htaccess antes de prosseguir). No seu .htaccess ficarão as regras de reescrita, ou rewrite rules.

OBS: lembre-se de ativar o mod rewrite no seu servidor, para que as regras funcionem.

Vamos ao nosso .htaccess. Para que nosso exemplo funcione, coloque o seguinte:

RewriteEngine on
RewriteRule ^exibeFotos/([0-9]+)\/([0-9]+)\/?$ exibeFotos.php?idAlbum=$1&idFoto=$2

Pronto! Não vou explicar as expressões regulares, mas vamos tentar entender o que foi feito:

“RewriteRule ^” inicia uma regra de reescrita. Tudo o que aparece do “^” até o “$” é uma expressão regular. É essa expressão que deverá casar com a url amigável que você utilizará em seu site.

Comparem a url com a expressão regular. No nosso caso, nossa url é a seguinte:
www.meusite.com.br/exibeFotos/2/35
exibeFotos/([0-9]+)\/([0-9]+)\/

Nossa url possui a string “exibeFotos”, seguidos de dois números. Como a url casa corretamente com a regra, o endereço será convertido na segunda parte:
exibeFotos.php?idAlbum=$1&idFoto=$2

Basicamente é isso. Não vou explorar mais como fazer as regras de reescrita. Agora vamos às implicações sobre o site.

Se seu site já estava pronto, você deverá substituir TODAS os links de seu site pelas novas urls. Por exemplo, se você tiver um link na sua pagina da seguinte forma:

<a href=”xxxx.php?id=23&x=5”>Ir</a>

Você deverá trocar pela correspondente url amigável. Isso parece idiota, mas muita gente tem dificuldade de entender que o .htaccess não vai transformar as url do seu site. É você que deve fazer isso manualmente. Ele apenas pegará essa nova url e traduzirá para a url normal.

Outro ponto que dará bastante trabalho: suponha que sua url ficou da seguinte forma:
www.meusite.com.br/exibeFotos/2/35
e que seu .htaccess está traduzindo corretamente essa url.

Então para a parte da aplicação que roda no servidor está tudo bem. O php receberá todas as referências do arquivo corretamente. Mas o html é interpretado no browser do usuário. Isso quer dizer que o browser não saberá interpretar corretamente as referências de arquivos, pois não sabe que suas regras de reescrita existem.

Resumindo, isso acontecerá com todos as suas referências no html à imagens, arquivos css e arquivos de mídia.

Por exemplo, se você chama a imagem: <img src=”img/teste.jpg” /> no seu arquivo exibeFotos.php, o browser interpretará sua url amigável como um monte de pastas. Então ele irá procurar a imagem que você colocou na seguinte pasta no servidor:
exibeFotos/2/35/img/teste.jpg, e não encontrará o arquivo.

Uma forma de resolver isso é colocando as referências absolutas, ou seja, a url completa. No nosso caso:
<img src=”http://www.meusite.com.br/img/teste.jpg” />

Para fazer isso de forma a não comprometer seu site, fazendo-o dependente do domínio, sugiro um código simples em php para pegar a url correta:

<?php
$server = $_SERVER['SERVER_NAME'];
$urlPrincipal = “http://”.$server.”/”;
?>

Nas suas referências, coloque:

<img src=”<?=$urlPrincipal?>img/teste.jpg” />

Pronto. Algumas referências:
http://forum.imasters.uol.com.br/index.php?showtopic=203965

http://www.vivaolinux.com.br/dica/Utilizando-URL-Amigavel-no-Apache

4 Comments

Classe de Conexão – PHP

Hoje vou mostrar como utilizar uma classe de conexão php/mysql. Quando comecei a trabalhar com php, fazia a conexão em cada página. Com isso, além de demandar muito tempo, se eu precisasse alterar o host de conexão, por exemplo, tinha que mexer em todos os arquivos que utilizavam aquele trecho de código.

Depois de um tempo, comecei a colocar essas configurações em um arquivo separado, e incluir este arquivo em minhas páginas. Se precisasse alterar algo relacionado com a configuração da conexão, alterava em um único arquivo.

Mas ainda existiam problemas. Escrever as funções mysql_fetch_array, mysql_num_rows, além de deixar o código “sujo”, deixa o sistema muito preso na tecnologia utilizada. Por exemplo, e se eu quisesse utilizar SQL Server, ao invés de mySql? Deveria alterar todas as menções de mysql_xxx para mssql_xxx, por exemplo (claro que nem todas as consultas sql seriam compatíveis, mas isto é outro assunto).

Por isso veio a necessidade de ENCAPSULAR essas funcionalidades relacionadas à conexão.

Então comecei a utilizar classe para realizar conexão. Vou mostrar uma das classes de conexão que desenvolvi, e que utilizo em meus projetos. Para não deixar esse post muito grande, não vou explicar o que significa cada detalhe da implementação (que não é complicada).

<?php

class Conexao{
/*
——————————————
| Classe de conexão
——————————————
| Adriano Godoy
——————————————
| www.adrianogodoy.com
——————————————
| Métodos:
| * desconectar -> encerra a conexão
| * consulta -> executa query sql
| * conta -> número de reultados
| * busca -> array resultado do select
|——————————————|
| Utilize à vontade ;- )
——————————————
*/

protected $user = “root”; // Usuário do banco de dados
protected $senha = “123″; // Senha do banco de dados
protected $bd = “banco_de_dados”; // Nome do Banco de dados MySQL
protected $server = “localhost”; //host – servidor
protected $con;

//Construtor
public function __construct() {
$this->con = mysql_connect($this->server, $this->user, $this->senha) or die(“Falha ao conectar com o banco de dados”);
mysql_select_db($this->bd, $this->con);
}

//Encerra a conexão
public function desconectar() {
mysql_close($this->con);
}

//Executa query sql
public function consulta($sql) {
$res = mysql_query($sql,$this->con);
if(!$res){
return false;
}else{
if(substr($sql,0,6) == “INSERT” && mysql_insert_id($this->con)){
return mysql_insert_id($this->con);
}else{
return $res;
}
}
}

//Número de resultados que atendem a uma dada consulta
public function conta($res) {
if($res){
return mysql_num_rows($res);
}
}

//Array resultado do select
public function busca($res) {
if($res){
return mysql_fetch_array($res);
}
}
} //fim da classe
?>

Para utilizá-la, no início de seu código você deve incluir o arquivo com essa classe (lembre-se de seguir convenções: inicie nome de classes com letra maiúscula, e o nome do arquivo deve ser o mesmo da classe) e instancia um objeto da classe, da seguinte forma:

include_once(“classes/Conexao.php”); //inclui
$conexao = new Conexao(); //instancia

Pronto! Agora, para realizar uma consulta:

$consulta1 = $conexao->consulta(“SELECT * FROM tabela WHERE x = y”);

e para obter os dados (mysql_fetch_array):

$dados1 = $conexao->busca($consulta1);

vale dentro do while também, caso a consulta vá retornar mais de um registro:

while($dados1 = $conexao->busca($consulta1))

Você pode contar quantos registros foram afetados pela consulta:

$cont1 = $conexao->conta($consulta1);

e, após terminar suas consultas, fechar a conexão:

$conexao->desconectar();

É isso, espero que seja útil para quem está começando. Abraço.

12 Comments