Captcha usando o vendor PhpCaptcha

Postado por Carlitos | Tags , , , , | Postado em 18:35

0

Bom, alguns dias sem postar nada e eu procurando algo interessante para compartilhar com vocês. Vamos lá então...

Estava quebrando a cabeça para implementar um Captcha (Isso mesmo! CAPTCHA, ou seja, aquelas letrinhas todas bagunçadas que impedem que um "não-humano" consiga submeter um formulário automaticamente... se bem que as vezes até um humano não consegue identificar as letras, mas vamos lá).

Baseado neste artigo que vi no Bakery vamos utilizar o PhpCaptcha como vendor. Segue os passos:

1) Faça o download do PhpCaptcha através do link http://www.ejeliot.com/pages/2 e descompacte o arquivo em "app/vendors/phpcaptcha" (crie este diretório caso não exista).

2) Faça o download dos arquivos de fontes Vera do GNOME através do link http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/ttf-bitstream-vera-1.10.zip e descompacte o arquivo em "app/vendors/phpcaptcha/fonts/".

3) Vamos criar o componente Captcha:

<?php

// Salve em app/controllers/componentes/captcha.php

App::import('Vendor','PhpCaptcha' ,array('file'=>'phpcaptcha'.DS.'php-captcha.inc.php'));

class CaptchaComponent extends Object
{
  var $controller;

  function startup( &$controller ) {
    $this->controller = &$controller;
  }

  function image(){

    $imagesPath = APP . 'vendors' . DS . 'phpcaptcha'.'/fonts/';

    $aFonts = array(
      $imagesPath.'VeraBd.ttf',
      $imagesPath.'VeraIt.ttf',
      $imagesPath.'Vera.ttf'
    );

    $oVisualCaptcha = new PhpCaptcha($aFonts, 200, 60);

    $oVisualCaptcha->UseColour(true);
    //$oVisualCaptcha->SetOwnerText('Source: '.FULL_BASE_URL);
    //$oVisualCaptcha->SetNumChars(6);
    $oVisualCaptcha->Create();
  }

  function audio(){
    $oAudioCaptcha = new AudioPhpCaptcha('/usr/bin/flite', '/tmp/');
    $oAudioCaptcha->Create();
  }

  function check($userCode, $caseInsensitive = true){
    if ($caseInsensitive) {
      $userCode = strtoupper($userCode);
    }

    if (!empty($_SESSION[CAPTCHA_SESSION_ID]) && $userCode == $_SESSION[CAPTCHA_SESSION_ID]) {
      // clear to prevent re-use
      unset($_SESSION[CAPTCHA_SESSION_ID]);

      return true;
    }
    else
      return false;
  }
}
?>

4) Adicione os métodos aos controllers que desejar. No caso vou adicionar ao controller Users:
<?php
class UsersController extends AppController
{
  ...
  // Adicione o componente Captcha ao controller
  var $components = array('Captcha');
  ...
  function captcha_image(){
    Configure::write('debug',0);
    $this->layout = null;
    $this->Captcha->image();
    $this->render();
  }

  // Não vou entrar no mérito do captcha com audio
  function captcha_audio()
  {
    $this->Captcha->audio();
  }
  ...
}
?>

5) Na view invoque o método captcha_image:
<img id="captcha" src="<?php echo $html->url('/users/captcha_image'); ?>" alt="" />

6) Agora para verificar se o usuário digitou corretamente os caracteres do Captcha usamos a função check, veja:
// Suponha que o campo texto onde o usuário preencheu os caracteres que leu
// no captcha seja "captcha", então temos
if(!$this->Captcha->check($this->data['User']['captcha'])){
  $this->Session->setFlash('Você não preencheu corretamente as letras da imagem!');
}


Veja como fica o resultado deste captcha colorido:


Bom, espero que funcione, pois aqui funcionou. Tem outros captchas para Cake e PHP também, veja aqui.

Abração!

Exportar dados - O príncipio...

Postado por Carlitos | Tags , , , | Postado em 19:23

1

Bom, sempre é preciso exportar dados (se vc ainda não fez isso, certamente num futuro próximo fará :P).

Missão: implementar um exportação de dados (para formatos: .xls - Excel, .doc - Word e .pdf, Adobe Reader) usando o CakePHP.

Colhendo dados: achei uma solução pronta para o .xls no Bakery - http://bakery.cakephp.org/articles/view/generate-excel-spreadsheets-from-your-database, li por cima mas não implementei. Achei também outra solução no CodigoFonte do UOL para implementar o .xls, essa eu testei e funcionou, falta apenas adicionar ao Cake pois esta em php simples. E achei também, neste blog aqui, uma implementação para .doc e para .xls, mas não testei ainda. Para o PDF usei uma solução pronta do Bakery usando o FPDF.

Cenas do próximo capítulo: Testar os scripts e ver qual possui o melhor desempenho. Verificar qual a melhor forma de acopla-los ao Cake (se via Helper ou Component).

Abraço,

Criando componentes

Postado por Carlitos | Tags , , , | Postado em 12:03

0

Bom dia povo! Ontem eu vi que havia um trecho de código que sempre se repetia ao longo de alguns controllers de um sistema em Cake que estou desenvolvendo e resolvi criar um componente com esta funcionalidade e aproveitar o reuso de código de forma limpa né ;)

Bom, vamos lá... mãos a obra!

O código é simples, trata-se de uma função que retorna o nome do navegador (browser) que o usuário está utilizando e qual a versão dele. Mas pra que usar isto, mano? Bom, é muito útil quando há alguma parte do seu site/sistema que "não funciona" em determinado navegador. Por exemplo, no meu caso existe uns getgads (firulas) na parte de validação de formulário que "não funciona" no IE 6 ou inferior.

Os componentes devem ficar dentro da pasta "./app/controllers/components/". O nome do meu componente é "Navegador", então criei o arquivo "./app/controllers/components/navegador.php", com o código

<?php
class NavegadorComponent extends Object {
}
?>

Depois adicionei a função que retorna as informações sobre o navegador
<?php
class NavegadorComponent extends Object {
  // Função que retorna o Brownser que está sendo usado
  function getBrowser(){
    $var = $_SERVER['HTTP_USER_AGENT'];
    $info['browser'] = "OTHER";
    // valid brosers array
    $browser = array ("MSIE", "OPERA", "FIREFOX", "MOZILLA", "NETSCAPE", "SAFARI", "LYNX", "KONQUEROR");
    // bots = ignore
    $bots = array('GOOGLEBOT', 'MSNBOT', 'SLURP');

    foreach ($bots as $bot)
    // if bot, returns OTHER
    if (strpos(strtoupper($var), $bot) !== FALSE)
      return $info;

    // loop the valid browsers
    foreach ($browser as $parent){
      $s = strpos(strtoupper($var), $parent);
      $f = $s + strlen($parent);
      $version = substr($var, $f, 5);
      $version = preg_replace('/[^0-9,.]/','',$version);
      if (strpos(strtoupper($var), $parent) !== FALSE){
        $info['browser'] = $parent;
        $info['version'] = $version;
        return $info;
      }
    }
    return $info;
  }
}
?>

Agora para poder ter acesso a esta nova funcionalidade você deverá adicionar o componente "Navegador" ao seu controller. Mas como? Veja exemplo abaixo
<?php
class TestesController extends AppController{
  $components = array('Navegador'); // Adiciono o componente "Navegador" ao  controller Testes

  function add(){
    /* guardo na variável 'browser' o array retornado pela função getBrowser do
    * meu componente Navegador com os dados do navegador do usuário 
    * como usei o $this->set, esta informação estará disponível para a view add
    * através da variável $browser, que é um array. */

    $this->set('browser', $this->Navegador->getBrowser());
  }
}
?>

Simples não? Espero que tenham entendido e que seja útil!
Consultem também a documentação oficial do CakePHP sobre o uso e criação de componentes aqui!

Abração,

Adicionar Syntax Highlight ao layout do Blogger/Blogspot

Postado por Carlitos | Tags , | Postado em 18:10

0

É muito ruim ler um código sem syntax highlight, não é? Pois é, passei alguns duas postando aqui no cakenaveia e resolvi procurar esse recurso para adicionar ao bloguezito... achei um muito legal que atende a diversas linguagens: PHP, HTML, CSS, JScript, Java, Perl e etc. O projeto é velhinho já (desde 2007) e muito bacana, veja aqui no site do script deles (mas só fiquei sabendo deles através do artigo deste camarada aqui {créditos}.

Então mãos a obra:
1º) baixe os scripts aqui, em seguida hospede eles em algum lugar.
2º) Acesse o painel de controle do seu blog (blogspot/blogger - mas vale para qualquer outro feito em Wordpress), vá até a aba Layout em seguida HTML.
3º) Dentro do HEAD do html do blog adicione os scripts do syntaxhighlight das linguagens que você vai precisar, veja:


<script language='javascript' src='http://...seusite.../shCore.js'/>

<script language='javascript' src='http://...seusite.../shBrushJava.js'/>

<script language='javascript' src='http://...seusite.../shBrushPhp.js'/>

<script language='javascript' src='http://...seusite.../shBrushJScript.js'/>

Adicione também o CSS do syntaxhighlight
<link href='http://...seusite.../SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>

4º)Antes da </body> adicione o código
<script language='javascript'>
  dp.SyntaxHighlighter.ClipboardSwf = 'http://...seusite.../clipboard.swf';
  dp.SyntaxHighlighter.BloggerMode();
  dp.SyntaxHighlighter.HighlightAll('code');
</script>

5º) Pronto! Agora para usar basta escrevesr os códigos dentro de um tag <pre name='code' class='php ou css ou html.. (a linguagem que vc está escrevendo)> seus codigos <pre> e eles aparecerão bonitinhos para os leitores.

Abração pra todos!

Mensagem carregando... usando CSS e Javascript

Postado por Carlitos | Tags , , | Postado em 13:54

3

Corri atrás de uma forma simples de mostrar uma mensagem de "Carregando..." quando o usuário clica em um link e aguarda o processamento das informações. Bom, depois de muito camelar pela internet colhi algumas informações e fiz um bem simples usando o atributo FIXED do CSS. Mãos a obra!!!

1º) Bom, primeiro adicionamos o script abaixo no head do layout default. No meu caso é o default.ctp.

//Mostra o carregador
function __loadMostra(){
  var objLoader = document.getElementById("carregador_pai");
  objLoader.style.display = "block";
  objLoader.style.visibility = "visible";
}

Este código "mostra" (atribui 'block' e 'visible' para ele) o elemento carregando.

2º) Adicione a DIV que contém a mensagem de carregando.

Observe que declarei que a DIV deve ficar escondida (display: none; visibility: hidden;).
Como eu uso o CakePHP eu adicionei uma imagem (aqui neste site tem várias imagens de Carregando para escolher):
echo image('carregando.gif', array('alt' => 'Carregando...', 'border' => 0));

3º)Adicione o seguinte CSS:
#carregador_pai{
  width: 100%;
  height:100%;
  position: absolute;
  text-align: center;
  background-color:#414141;
  filter:alpha(opacity=90);
  opacity:0.9;
  overflow: auto;
  top: 0;
  left: 0;
  z-index:2;
}

#carregador_fundo{
  font-size: 1px;
  left: 8px;
  width: 113px;
  position: relative;
  top: 50px;
  height: 7px;
  background-color: #ebebe4
}
#carregador_posicao{
  padding-top:20%;
}
#carregador{
  border-right: #6a6a6a 1px solid;
  padding: 0px 10px 0px 16px;
  border-top: #6a6a6a 1px solid;
  display: block;
  font-size: 11px;
  z-index: 2;
  margin: 0px auto;
  border-left: #6a6a6a 1px solid;
  width: 250px;
  height:70px;
  color: #000000;
  border-bottom: #6a6a6a 1px solid;
  font-family: Tahoma, Helvetica, sans;
  background-color: #ffffff;
  text-align: left;
}

@media screen{
  body>div#carregador_pai{
    position: fixed;
  }
}
Esse CSS cria uma tela como na imagem abaixo.


Ah! Esse CSS não funciona no IE¨6 ou inferior. Mas quem liga né? ;) Desde já estou fazendo minha parte no movimento ATUALIZE SEU IE! E outra coisa, o único problema que os usuários do Internet Explorer 6 ou inferior terão é que não verão a tela de Carregando, mas o carregamento da página não é afetado.

4º) Guenta aí, tá quase acabando ;). Agora sempre que você tiver um link basta adicionar a função
onclick = "__loadMostra();";

Ou seja, ao clicar ele mostra a DIV do Carregando... e assim que a próxima página termina de ser carregada a DIV volta a ser ocultada. Dá para adicionar ele nos formulário também, excluindo o botão de submit e criando um INPUT type BUTTON e adicionando o __loadMostra() seguido do submit().
onclick = "__loadMostra(); submit();";

Com o CakePHP fica assim
// Cria o botão de Enviar que submete o formulário
echo $form->button('Enviar', array('onclick' => '__loadMostra(); submit();'));
// Cria a tag /FORM
echo $form->end();

Simples não? Dúvidas? Eu gostei do resultado final. Se tiver algo errado comentem aí!

Ah! Na imagem parece que estou usando o IE8 né? Não... esse é o Firefox "camuflado" com o thema "ie8fox".

Abração!

Confirmação de senha

Postado por Carlitos | Tags , , , | Postado em 18:43

0

Poxa, havia criado um formulário para criação de um novo usuário com os campos: username, password e email. Hoje precisei implementar um novo campo (Repita a senha)... como uso o "Auth" sempre que há um array contendo as chaves "username" e "password" ele automágicamente (como dizem a galerinha do CakeBook) encriptografa o campo password usando as configurações de Salt definidas no core.php (Blz, mas isso não vem ao caso).

Bom, o problema é que quando comparava

if($this->data['User']['password'] == $this->data['User']['confirm_password']) 

dava errado... depois de uns debugs no array $this->data percebi que o password já chegava ao controller encriptado, então a solução descobri aqui. Basta usar o metódo $this->Auth->password que encripta de acordo com as definições do Salt definidas no core.php, assim podemos comparar
$this->data['User']['password'] == $this->Auth->password($this->data['User']['confirm_password'])
Rá!

P.S.: Agora, sempre que o usuário retornava a tela do formulário (por erro em algum campo) o campo senha ficava enorme, pois estava preenchido com a senha encriptada. Para isso sempre que ocorre um erro de confirmação de senha eu limpo o password e o confirm_password, e quando ocorre erro em outro campo eu copio o valor do confirm_password para o password!

Abração,