sexta-feira, 8 de junho de 2012

Validador PHP de Expressões Regulares

 

Olá o assunto hoje é Expressão Regular no PHP.

Talvez você, assim como eu, já quis facilitar seu trabalho de programação na hora de validar um campo, seja ele CPF, CNPJ entre outros. O caminho, via de regra, é "if s intemináveis", aquele monte de comparação, para cada tipo de caracter, etc. Ou aquelas equações cheias de {}[]()/.\/ entre outros símbolos que assustam.
Bom, me assustei bastante, mas continuei, insisti e vi que era legal. Então vou tentar compartilhar um pouco do apreendido com as experiências, e mais, acabei por construir um simples, mas útil Validador de Expressões Regulares. 

Expressão Regular é algo que lhe permite diminuir para uma linha uma dezena de IFs. Pra compreender o que é, existe o  EXCELENTE LIVRO DO AURÉLIO MARINHO gratuito e online. 

O Projeto é bastante simples e consiste de duas páginas php. 

Aqui você pode testá-lo:  Projeto no Ar

Pra executar em modo local, na sua máquina, é necessário ter o PHP e o Apache configurados, e pra quem ainda não tem recomendo o WAMPSERVER, que instala e configura tudo pra você. 

Como editor de texto você pode usar até o bloco de notas, mas existem alguns que lhe facilitam demais a vida. O que costumo usar é o Notepad++ que além de permitir a sintaxe PHP,  também é gratuito. Outra característica muito interessante pra quem faz sites compatíveis com UTF-8 é a opção de  formatar e salvar o arquivo já nesse formato, para que as palavras com acento apareçam corretamente.

Links:

FONTES DO PROJETO

Você já deve ter procurado muito sobre esse assunto na internet, de forma que serei breve e passarei ao código fonte.

Para utilizar, abra o Notepad++, menu Formatar e  marque "Codificação em UTF-8 (sem BOM)", com isso as palavras sairão acentuadas corretamente. Isso é necessário porque estou especificando no < head > esse charset.

Cole o conteúdo do arquivo abaixo e salve-o como INDEX.PHP. Repita para o EXP_REG.PHP.

Salve ambos na pasta www que o WAMPSERVER criou pra você, ela deve estar em: C:\wamp\www\

Agora, entre no seu navegador  e digite: LOCALHOST/INDEX.PHP



Este arquivo é o INDEX.PHP


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="title" content="Validador de Expressões Regulares">
  <meta name="description" content="Valida expressões regulares">
  <meta name="keywords" content="validador,expressões regulares,php">
  <meta name="autor" content="Claudio Segura">
  <meta name="revisit-after" content="15">
 
  <style type="text/css">
    #formulario {
        background-color: #61B5D4;
        float:left;
    }   
    #formulario h1{
        font: bold 20px Trebuchet Ms, Verdana, Arial, Tahoma, Sans-Serif;
        color: #426B00;
        text-transform:uppercase;
        text-align: center;
        margin-top: 7px;
    }
   
    #corpo {
        clear:both;
        background-color: #AAAA77;
       
    }
    #corpo h3{
        font: bold 14px Trebuchet Ms, Verdana, Arial, Tahoma, Sans-Serif;
        color: #426B00;
        text-transform:uppercase;   
    }
    #corpo p{
        font: 14px/20px   Arial,Tahoma, Sans-Serif;
        color: #164348;
        margin-botton:0px;    
       
    }
    #exemplo1{
        float:left;   
        margin-left: 20px;   
    }
    #exemplo2{
        float:left;   
        margin-left: 20px;
    }
  </style>
</head>

<body>

    <div id="formulario">
        <table border=1><tr><td>
        <h1>Validador PHP de Experessões Regulares</h1>
        <form method="post" action="exp_reg.php">
           
            <fieldset>
                <p><label><Input type = 'Radio' Name ='tipo' value= 'match'>Preg_match (Encontrar uma coincidência no texto)</label></p>
                <p><label><Input type = 'Radio' Name ='tipo' value= 'replace'>Preg_replace (Encontrar no texto e substituir pelo conteúdo)</label></p>
                Escolha do menu a Expressão Regular
                <select name="dropdown" value="options">
                    <option value="">Digitar uma expressão</option>
                    <option value="(^([\d]|1[0,1,2])/([0-9]|[0,1,2][0-9]|3[0,1])/\d{4}$)">Data</option>
                    <option value="(^([0-9a-zA-Z]+([_.-]?[0-9a-zA-Z]+)*@[0-9a-zA-Z]+[0-9,a-z,A-Z,.,-]*(.){1}[a-zA-Z]{2,4})+$)">Email</option>
                    <option value="(\b([0-9]{3}\.?){3}\-?[0-9]{2}\b)">CPF</option>
                    <option value="(\b([0-9]{2}\.?)([0-9]{3}\.?){2}\/?([0-9]{4})\-?([0-9]{2})\b)">CNPJ</option>
                    <option value="(\b[0-9]{2}\.?[0-9]{3}-[0-9]{3}\b)">CEP</option>
                </select>
                <p><label>ou digite uma Expressão: <input name="expressao" type="text" size="100"/></label></p>
                <p><label>Conteudo: <input name="conteudo" type="text" size="100"/></label></p>
                <p><label>Texto: <input name="texto" type="text" size="100"/></label>
               
            </fieldset>
           
            <p>

            <input type="submit" value="  Enviar  " name="submit">
            <input type="reset" value="  Limpar  " name="reset">

        </form>
        </td></tr></table>
    </div>
    <div id='corpo'>
        <div id='Exemplo1'>
            <p>Exemplo: preg_replace:</p>
            <h3>Retirar formatação de um CPF ou CNPJ:</h3>
            <p>Selecione: preg_replace</p>
            <p>Expressão: ([\.\-\/\' '])</p>
            <p>Conteúdo: deixe em branco equivale a ' '</p>
            <p>texto:12.234.345/0002-23</p>
            <hr>
            <h3>Formatar CPF:</h3>
            <p>Selecione: preg_replace</p>
            <p>Expressão: (([0-9]{3})([0-9]{3})([0-9]{3})([0-9]{2}))</p>
            <p>Conteúdo: $1.$2.$3-$4</p>
            <p>texto:12234345023</p>
            <hr>
            <h3>Formatar CNPJ:</h3>
            <p>Selecione: preg_replace</p>
            <p>Expressão: (([0-9]{2})([0-9]{3})([0-9]{3})([0-9]{4})([0-9]{2}))</p>
            <p>Conteúdo: $1.$2.$3/$4-$5</p>
            <p>texto:12234345000134</p>
            <hr>
        </div>
        <div id='Exemplo2'>
            <p>exemplo: preg_match:</p>
            <h3>Procurar CPF:</h3>
            <p>Selecione: preg_match</p>
            <p>Expressão: Selecione do menu CPF</p>
            <p>Conteúdo: deixe em branco</p>
            <p>texto:01.234.567-89</p>
            <hr>
            <h3>Procurar CNPJ:</h3>
            <p>Selecione: preg_replace</p>
            <p>Expressão: Selecione do menu CNPJ</p>
            <p>Conteúdo: deixe em branco</p>
            <p>texto:12.234.345/0002-23</p>
            <hr>
               
        </div>
    </div>
   
   
   
</body>
</html>



Este outro é o  EXP_REG.PHP


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="title" content="Validador de Expressões Regulares">
  <meta name="description" content="Valida expressões regulares">
  <meta name="keywords" content="validador,expressões regulares,php">
  <meta name="autor" content="Claudio Segura">
  <meta name="revisit-after" content="15">
</head>

<body>

<?php

$expressao=$_POST['dropdown'];

if ($expressao==""){
    $expressao=$_POST['expressao'];
}

$conteudo=$_POST['conteudo'];
$texto=$_POST['texto'];



if ($_POST['tipo']=='match'){
    if (preg_match($expressao,$texto,$resp)){
        echo 'Expressão: '.$expressao;
        echo '<p>';
        echo 'Texto: '.$texto;
        echo '<p>';
        echo 'Resultado: [POSITIVO] - '.$resp[0].' encontrado';
    }else{
        echo 'Resultado: [NEGATIVO] - O texto não apresenta nada como a expressão sugere.';
    }
}else{
    $resp=preg_replace($expressao,$conteudo,$texto);
    echo 'Expressão: '.$expressao;
    echo '<p>';
    echo 'Conteúdo: '.$conteudo;
    echo '<p>';
    echo 'Texto: '.$texto;
    echo '<p>';
    echo 'Resultado: '.$resp;   
   
}

echo "<a href='index.php'>Retornar</a>";

?>

</body>
</html>


Bom então é isso. Bom divertimento.   :)

quinta-feira, 17 de fevereiro de 2011

Download com pausa e resume com Indy

Olá Pessoal,


vamos exemplificar com um pequeno aplicativo completo e funcional para baixar um programa da internet possibilitando parar e continuar mais tarde.

Esta rotina tem partes de outros exemplos tirados da própria Web, mas aqui foram juntadas, e adaptadas para tornar-se fácil de ser implementada em seu aplicativo. É comum encontrar exemplos falhos, incompletos ou difíceis de reaproveitar, muitas vezes por falta de um pequeno esforço de quem os está publicando, que com um pouco mais de zê-lo torna-los-iam muito mais úteis.

Precisei desta rotina recentemente, para possibilitar um live-update na minha aplicação, e tive aí uma semana de muita procura na web com pouco sucesso, então segue minha pequena contribuição. :)

Utilizaremos o componente TidHTTP do Indy, mas não será preciso arrasta-lo, pois vamos declará-lo em uma Thread que não tem formulário.

O projeto consta de duas Units, uma com o Form e a outra com a Thread citada, foi compilado com a versão do Delphi 2007.


Link para os fontes.

Inicie um novo projeto no Delphi, e no form1 coloque:
2 Edit
2 Button
3 Label
1 Gauge

Renomeie os componentes como segue, e mantenha sua ordem no form:

Label1 - Caption= Endereço web do arquivo a ser baixado
Edit1 - Edt_web

Label2 - Caption= Endereço no HD Local para salvar o arquivo
Edit2 - Edt_local

Button1 - Btn_baixar
Button2 - Btn_parar

Gauge1

Label3 - renomeie para Lbl_Status e seu Caption= Status


Na cláusula Uses coloque:

Uses  
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,Math,
  StdCtrls, ComCtrls, Gauges,unit2;

E antes do implementation:

var
  Form1: TForm1;
  ThreadBaixar: TBaixar;
  parar:boolean=false;


Dê dois cliques no Btn_Baixar e cole o código:

//=======================================================
procedure TForm1.Btn_baixarClick(Sender: TObject);
begin

  btn_parar.enabled:=true;
  btn_baixar.Enabled:=false;
  parar:=false;

  ThreadBaixar := TBaixar.Create (true);
  ThreadBaixar.FreeOnTerminate := True;
  ThreadBaixar.Resume;

  Application.ProcessMessages;
end;
//=========================================================

Faça o mesmo para o Btn_Parar:

//========================================================
procedure TForm1.Btn_PararClick(Sender: TObject);
begin
  btn_parar.enabled:=false;
  btn_baixar.Enabled:=true;
  parar:=true;
end;
//===========================================================

Vamos agora acrescentar ao projeto uma nova Unit:
Vá em File / New Unit for Delphi Win32

A nova unit (Unit2) está agora disponível para receber a nossa thread.

O código completo da Unit2 segue:

//========================================================
unit Unit2;
interface
uses Classes,IdBaseComponent, IdComponent, IdTCPConnection,Dialogs,
  IdTCPClient, IdHTTP,SysUtils,Math;

type
  TBaixar=class(TThread)
  Http: TIdHTTP;
  fFileStream: TFileStream;
  Tam_Tot_arq: Integer;
  quant_baixada_arq: Integer;
  ja_baixado: integer;

  protected
  procedure Execute; override;
  procedure HTTPWork(ASender: TObject; AWorkMode: TWorkMode;
            AWorkCount: Integer);
  procedure HTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
            AWorkCountMax: Integer);
  procedure HTTPWorkEnd(ASender: TObject; AWorkMode: TWorkMode);

end;

implementation

uses
  unit1;


procedure TBaixar.Execute;
var
  terminado:Boolean;
begin
  Http  := TIdHTTP.Create(nil);
  fFileStream:=nil;
  try
    try
      Http.OnWorkBegin := HTTPWorkBegin;
      Http.OnWork:= HTTPWork;
      Http.OnWorkEnd := HTTPWorkEnd;


      // * * * * * * * * * * * * * *  NOVO * * * * * * * * * * * * * *
      //dava erro 403 forbidden, porque haviam mudado de 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1';
      HTTP.Request.UserAgent :='Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
      Http.Request.CacheControl := 'no-cache'; //Para não utilizar o cache, sempre baixar do site
  // * * * * * * * * * * * * * *  FIM  * * * * * * * * * * * * * *


      Http.Head(Form1.Edt_web.Text); //Arquivo à baixar
      Tam_Tot_arq := Http.Response.ContentLength;//tamanho total do arquivo
      terminado:=false;
      repeat //Vai continuar tentando... ( until abaixo )
        if Unit1.parar then
          Http.Free;

        if not FileExists(Form1.Edt_local.Text) then begin
          fFileStream := TFileStream.Create(Form1.Edt_local.Text, fmCreate);
        end
        else begin
          fFileStream := TFileStream.Create(Form1.Edt_local.Text, fmOpenReadWrite);
          terminado:= fFileStream.Size >= Tam_Tot_arq; //se quantidade baixada = tam do arquivo do serv
          ja_baixado:=fFileStream.Size;
          if not terminado then
            fFileStream.Seek(Max(0, fFileStream.Size-4096), soFromBeginning);
        end;
        try
          quant_baixada_arq:=fFileStream.Size + 50000;//Acrescido em 50kb para garantir chegar ao fim
          if quant_baixada_arq < Tam_Tot_arq then begin
            Http.Request.Range := IntToStr(fFileStream.Position) + '-'+  IntToStr(quant_baixada_arq);
          end
          else begin
            Http.Request.Range := IntToStr(fFileStream.Position) + '-';
            terminado:=true;
          end;
          Http.Get(Form1.Edt_web.Text, fFileStream);//Ajusta nome do arquivo à baixar
        finally
          fFileStream.Free;
        end;
     until terminado; //Até que a variável Exit seja true (veja variavel exit acima)
     Http.Disconnect;
    except
      on E : Exception do
      Begin
       //AddLog(E.Message);  //Você pode criar uma rotina de arquivo.log e colocar os erros
      end;
    end;
  finally
    Http.Free;
  end;
end;


procedure TBaixar.HTTPWork(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Integer);
begin
   //101 para compensar o trunc que corta a parte decimal
   Form1.Gauge1.Progress:= Trunc((ja_baixado/Tam_Tot_arq)*101);
   //se quiser representar em MB (MiB) basta dividir por 1024*1024 =  1048576
   form1.lbl_status.caption:=inttostr(trunc(ja_baixado/1024))+' de '+inttostr(trunc(Tam_Tot_arq/1024))+' kb';
   form1.lbl_status.Refresh;
end;

procedure TBaixar.HTTPWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Integer);
begin
   form1.Lbl_Status.Caption:='Iniciando Download';
end;

procedure TBaixar.HTTPWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
   if Form1.Gauge1.Progress=100 then
     form1.Lbl_Status.Caption:='Download Completo.';

   if unit1.parar then
     form1.Lbl_Status.Caption:='Download pausado...'
end;


end.

//==================================================================

// * * * * * * * * * * * * * * NOVO
Havia sido mudado a string o que ocasionava erro de download
// * * * * * * * * * * * * * *

Há alguns comentários no código, e procurou-se nomear variáveis em portugues que talvez possam ajudar na compreenção do mesmo.

Bem é isso. Espero ter sido útil com essa humilde iniciativa. Desejo a todos felicidades e bons retornos com seus sistemas.

Lembrando que se for útil pra você, coloque links em outras foruns para que mais gente se beneficie.

Grato pela companhia.

Até mais.

Claudio Segura