<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4030446995309883641</id><updated>2011-11-27T15:36:33.042-08:00</updated><category term='global'/><category term='processos'/><category term='orientação a objetos'/><category term='ETL'/><category term='seguranca programacao'/><category term='php'/><category term='patterns'/><category term='processo de desenvolvimento'/><category term='php dicas'/><category term='prototipacao'/><category term='metricas'/><category term='trim'/><category term='snipet'/><category term='classbuilder'/><category term='gerência de projetos'/><category term='CASE'/><category term='array'/><category term='solução'/><category term='desenvolvimento'/><title type='text'>php-eduluz</title><subtitle type='html'>Postagens de soluções e comentários sobre desenvolvimento em PHP.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>25</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-6141132448874780051</id><published>2009-06-10T09:03:00.000-07:00</published><updated>2009-06-10T09:10:58.822-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='processo de desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Artigo interessante</title><content type='html'>Hoje encontrei um artigo interessante: a apresentação 'Enterprise PHP development', feita por Ivo Jansch em fevereiro de 2008, na PHPLondon Conference, fala essencialmente de como desenvolver projetos sérios, de médio para grande porte, em PHP. &lt;a href="http://www.google.com.br/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=3&amp;amp;url=http%3A%2F%2Fwww.phplondon.org%2Fconference%2F2008%2Fmedia%2Fdocs%2Fivo_jansch_enterprise_php.pdf&amp;amp;ei=ZdkvSrQM0K-3B-24nIIM&amp;amp;usg=AFQjCNHJGJUAH8xGgcnNCjrZGjlvCOFJzw&amp;amp;sig2=Oflbcqzw5MSGNb-CkPoE-Q"&gt;Baixe aqui o artigo&lt;/a&gt;. Quem quiser ouvir a palestra, basta clicar &lt;a href="http://www.phplondon.org/conference/2008/media/audio/ivo_jansch_final.mp3"&gt;aqui&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;O autor dá uma visão geral de como profissionalizar o desenvolvimento de um projeto, usando algumas figuras de linguagem bem humoradas. Vale a pena ler.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-6141132448874780051?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/6141132448874780051/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=6141132448874780051' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/6141132448874780051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/6141132448874780051'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/06/artigo-interessante.html' title='Artigo interessante'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-5184758117786951843</id><published>2009-04-06T11:11:00.000-07:00</published><updated>2009-04-06T11:22:17.593-07:00</updated><title type='text'>Os 5 Ms de Ahonen</title><content type='html'>Tony Ahonen escreveu um livro entitulado "&lt;span style="font-style: italic;"&gt;m-Profits – Making Money from 3G Services&lt;/span&gt;", onde discute amplamente o tema. Neste livro ele menciona os 5 Ms dos serviços 3G: "cinco elementos dos serviços 3G que agregam valor ao usuário, e lucro para a operadora".&lt;br /&gt;&lt;br /&gt;Os 5 Ms de Ahonen&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;1. Movement&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;(Movimento) - Escapando de um lugar fixo&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;2. Moment&lt;/span&gt;&lt;span style="font-style: italic;"&gt; &lt;/span&gt;(Momento) - Expandindo o conceito de tempo&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;3. Me&lt;/span&gt; (Eu) - Extentendo a mim mesmo e a minha comunidade&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;4. Money&lt;/span&gt; (Dinheiro) - Gastando recursos financeiros&lt;br /&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;5. Machines &lt;/span&gt;(Máquinas / dispositivos) - "Turbinando" dispositivos&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Movement.&lt;/span&gt;&lt;br /&gt;O movimento é a habilidade do serviço a continuar operando de modo significativo enquanto que o usuário se desloca, seja por locais próximos, seja para longas distâncias.&lt;br /&gt;Até aqui nenhuma novidade; o que Ahonen enfatiza como ponto-chave, é que se o serviço possuir elementos que variam de acordo com a localização do usuário, então este comportamento deve ser realizado; Ele exemplifica a previsão de tempo: se o usuário estiver transitando de uma cidade para outra, o sistema deve verificar a previsão desta nova cidade.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Moment&lt;/span&gt;&lt;br /&gt;O Momento é o conceito de possibilitar a gerenciar o tempo de modo a adaptar-se a situação em que se encontra; Um bom exemplo é o serviço de mensagens publicitárias baseadas na localização do usuário: um restaurante pode ter seus anúncions distribuídos próximos do almoço, e não as 23hs da noite, para os usuários que estiverem próximos.&lt;br /&gt;Outro ponto de vista do conceito de 'Moment' é a possibilidade de serem executadas várias tarefas simultaneamente: em um fluxo bem definido, tarefas relacionadas a um determinado fim podem ser distribuídas ou realizadas em paralelo, e sincronizadas pelo próprio sistema. Uma variante típica é a de iniciar uma tarefa que ficará "pendente" até o "momento certo": um exemplo é disparar a solicitação de um serviço (presencial), que será atendido daqui a 2 horas; quando chegar no local, o serviço será executado.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Me&lt;/span&gt;&lt;br /&gt;"Me" é o conceito de personalização, que tem sido bem compreendido em alguns serviços Web, que adaptam-se de acordo com as configurações e perfil do usuário. Perceba que um ponto importante é o de que alguns parâmetros de configuração consistem de variáveis como o tempo (moment) e a localização (movement).&lt;br /&gt;Ahonem indica que o "Me" é o atributo mais vital dos 5 apresentados: é o ingrediente crítico para um serviço móvel bem-sucedido.&lt;br /&gt;Isso quer dizer que precisamos de uma plataforma flexível, o que implica em tecnologias que podem suportar um alto grau de customização, incluindo o conceito de que serviços podem algumas vezes serem construídos em tempo de execução, surgindo para atender demandas pontuais do usuário.&lt;br /&gt;A criação de serviços sob demanda é um novo elemento para a provisão de serviços no contexto móvel.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Money&lt;/span&gt;&lt;br /&gt;Este é simplesmente o suporte para transações financeiras, onde quer que surja a necessidade.&lt;br /&gt;Evidentemente, um framework é necessário para permitir esse trabalho, dada a complexidade e a segurança envolvidas em transações de pagamentos.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;5. Machines&lt;/span&gt;&lt;br /&gt;O último 'M' é o conceito que permite que máquinas comuniquem-se através de redes WAN. Isso é algumas vezes chamado de M2M (machine to machine), e algumas vezes incrementado com a idéia de telemetria ou medições remotas sem a necessidade de pessoal de campo.&lt;br /&gt;Um bom exemplo são as máquinas de venda eletrônica, como máquinas de refrigerante, que "ligam" para a central e reportam os produtos que estão acabando.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Tecendo minhas considerações&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Eu creio que dos 5 Ms, os 3 primeiros são os principais, para aplicações centradas em conteúdo móvel; para tanto, o estabelecimento de uma infraestrutura lógica é fundamental, e as 3 variáveis principais são, em ordem de importância: Identificação do usuário, Localização física e Tempo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-5184758117786951843?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/5184758117786951843/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=5184758117786951843' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5184758117786951843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5184758117786951843'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/04/os-5-ms-de-ahonen.html' title='Os 5 Ms de Ahonen'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-8858356648399595921</id><published>2009-03-05T10:27:00.000-08:00</published><updated>2009-03-05T10:30:58.194-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='php dicas'/><title type='text'>Filtragem de caracteres indesejáveis</title><content type='html'>Hoje o Juliano entrou em contato, pedindo uma ajuda para filtrar caracteres indesejáveis que vinham nos arquivos de dados...&lt;br /&gt;&lt;br /&gt;Depois de muito quebrar a cabeça, conseguimos o seguinte:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Mudar o locale para português-Brasil&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;setlocale(LC_ALL,"pt_BR.ISO8859-1");&lt;/span&gt;&lt;br /&gt;ou&lt;br /&gt;&lt;span style="font-size:100%;"&gt;setlocale(LC_ALL,"pt_BR.UTF-8");&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Filtrar&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;$v = preg_replace('/[^[:blank:]|[:space:]|[:alnum:]|[:punct:]]/', ' ', $v);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-8858356648399595921?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/8858356648399595921/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=8858356648399595921' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8858356648399595921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8858356648399595921'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/03/filtragem-de-caracteres-indesejaveis.html' title='Filtragem de caracteres indesejáveis'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-2788421306166663809</id><published>2009-03-02T07:56:00.000-08:00</published><updated>2009-03-05T12:55:31.740-08:00</updated><title type='text'>#1 - Validação de Entrada de dados (primeira parte)</title><content type='html'>&lt;span style="font-weight: bold; color: rgb(0, 0, 102);font-size:180%;" &gt;Origem dos dados&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Originalmente, os programadores PHP acessavam dados enviados pelos usuários através dos mecanismos de "register globals".&lt;br /&gt;&lt;br /&gt;Usando "register globals", qualquer parâmetro passado para o script é disponibilizado como uma variável com o mesmo nome do parâmetro.&lt;br /&gt;&lt;br /&gt;Embora o mecanismo de "register globals" seja uma abordagem para capturar parâmetros pelos scripts, é uma vulnerabilidade e possível fonte de exploração por parte de hackers.&lt;br /&gt;&lt;br /&gt;Um dos problemas é o conflito entre os parâmetros de entrada: Dados fornecidos ao script podem vir de várias fontes, incluindo requisições GET, POST, cookies, variáveis de ambiente do servidor e variáveis de ambiente do sistema - nenhuma delas é exclusiva.&lt;br /&gt;&lt;br /&gt;Então, se as fontes são muitas, o PHP é forçado a mesclá-las, algumas vezes substituindo o valor de uma por outra de mesmo nome. Aqui reside o perigo: se temos uma variável esperada via cookie, um atacante pode enviá-la via método GET, e o script nem perceber a diferença, se usar a variável global.&lt;br /&gt;&lt;br /&gt;Portanto, é importante usar mecanismos que forcem a verificação da origem dos dados vindos do usuário.&lt;br /&gt;&lt;br /&gt;No arquivo de configuração PHP.INI existem duas diretivas de controle que são usadas como parâmetros para que o interpretador faça o merge: &lt;span style="font-style: italic;"&gt;gps_order&lt;/span&gt; e &lt;span style="font-style: italic;"&gt;variables_order&lt;/span&gt;. Ambos parâmetros refletem a prioridade relativa das fontes de entrada de dados.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;Não vamos entrar muito neste assunto, visto que já presumimos que usamos as variáveis superglobais ($_GET, $_POST, etc) para acessar tais dados.&lt;/span&gt; &lt;span style="color: rgb(0, 0, 102);"&gt;&lt;span style="font-weight: bold;"&gt;Entretanto, cabe uma orientação&lt;/span&gt;: mesmo usando as superglobais, existe um risco especialmente em casos em que criamos variáveis para verificar se um dado script foi carregado ou não (ou se tal arquivo pode ser incluído ou não) - nestes casos, como a variável pode estar exposta à configuração do servidor, cabe uma advertência: é melhor usar constantes (define) ao invés de usar uma variável simples. Isso porque a variável simples pode ser substituída por um parâmetro injetado por um atacante, se não estiver inicializada e dependendo da configuração do servidor.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;Outra observação importante, é o uso da superglobal  $_REQUEST - ela mistura as variáveis GET, POST e COOKIES em um mesmo array. É o mesmo problema da register globals, embora em menor grau. Portanto, prefira o uso de $_GET ou $_POST.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102); font-weight: bold;font-size:180%;" &gt;Conteúdo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;É importante sempre verificar a natureza do parâmetro de entrada e validá-lo para evitar problemas depois.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Dados numéricos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Se o dado esperado é numérico, simplesmente usamos o recurso de &lt;span style="font-style: italic;"&gt;casting&lt;/span&gt; para obter o valor. Veja os exemplos a seguir:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;$id_produto = (int) $_GET['id_produto'];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;$valor_salario = (float) $_POST['valor_salario'];&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Para melhorar um pouco mais, podemos centralizar o casting onde de direito: nos getter e setters das classes:&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  class Funcionario {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;     private $valorSalario;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;   public function getValorSalario() {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     return $this-&gt;valorSalario;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;   public setValorSalario($valor) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;      $this-&gt;valorSalario = (float) $valor;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;      if (!$this-&gt;valorSalario) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;         $e = new Exception('Valor do salario deve ser float',999);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;         throw $e;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;      }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;     }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Veja que no exemplo acima se ocorre um erro de tipo, uma excessão é imediatamente emitida e o programador já mata o problema na raiz. A abordagem acima pode ser melhorada incluindo na mensagem o valor que se está passando para o atributo em questão.&lt;br /&gt;&lt;br /&gt;Um ponto que deve ser observado com cuidado é a precisão do tipo numérico que se espera. Por exemplo: para validar um inteiro, em sistemas de 32 bits, é 2,147,483,647. Se uma string "1000000000000000000"  for convertida para integer, ela vai estourar o container e haverá perda de dados. No caso, o resultado final será truncado no máximo possível, que é 2147483647.&lt;br /&gt;Então, fazendo o casting de números grandes na notação científica evitará a perda de dados:&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;echo (int)"100000000000000000"; // 2147483647&lt;br /&gt;echo (float)"100000000000000000"; // float(1.0E+17)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Enquanto que o casting funciona bem para inteiros e números de ponto-flutuante, valores em hexadecimal, octal e descritos em notação científica não são tratados automaticamente - é necessário implementar mecanismos adicionais de validação. O mais lento mas mais eficaz é a instrução "is_numeric" - Ela suporta todos os tipos de valores numéricos, e retorna True se o valor é válido.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(153, 0, 0);font-size:130%;" &gt;Problemas de internacionalização&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Algumas vezes números de ponto-flutuante são representados de várias formas ao redor do mundo, mas tanto o casting quanto  o "&lt;span style="font-style: italic;"&gt;is_numeric&lt;/span&gt;" consideram números que não usam o "ponto" (.) como separador decimal  como inválido.&lt;br /&gt;&lt;br /&gt;O problema é que para a validação em si, não encontrei recursos nativos no PHP que consideram a entrada de dados em localizações (locales) diferentes. Os mecanismos de locales funcionam muito bem para exibir o resultado de valores no formato esperado na língua selecionada. Por isso, recomendo que se use rotinas que façam a conversão do conteúdo logo na entrada dos dados. Para o caso de dados númericos de ponto flutuante, eu uso:&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;$r = setlocale(LC_ALL, 'ptb');&lt;br /&gt;$locale_info = localeconv();&lt;br /&gt;&lt;br /&gt;$numero = str_replace($locale_info['thousands_sep'],"",$numero_input);&lt;br /&gt;$numero = str_replace($locale_info['decimal_point'],".",$numero);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Com a lógica acima, o script "sabe" quais caracteres espera que sejam entrados pelo usuário como separador decimal e de milhar. Automaticamente o valor é convertido para o formato que o interpretador "entende", e daí para adiante o valor é processado e depois inserido/atualizado no banco de dados; Depois, a exibição do dado fica por conta do interpretador, que vai considerar o locale selecionado. No caso do exemplo acima, defini a localização como sendo Português Brasileiro.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 102);font-size:130%;" &gt;Validação de String&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A validação de string não é tão simples quanto a de um atributo numérico, uma vez que o casting não é suficiente para garantir que o valor entrado é o esperado - existem algumas variantes que precisam ser consideradas. O primeiro ponto é o formato do valor entrado, que pode ser um CPF, número de telefone, URL, CEP, etc.&lt;br /&gt;&lt;br /&gt;Para verificar se uma string possui apenas caracteres alfabéticos, não sendo admitido qualquer número ou pontuação, pode-se usar a instrução 'ctype_alpha()'. A extensão CTYPE é habilitada por padrão no PHP. Existem outras instruções dessa extensão que podem ser úteis em questões bem particulares, mas nenhuma delas consiste regras de formação mais complexas. Veja ainda que a Ctype considera o locale ativo. Portanto, caracteres que são considerados inválidos no alfabeto inglês (como 'ç'), serão considerados válidos pela Ctype quando o locale PTB estiver setado.&lt;br /&gt;&lt;br /&gt;Quando o ctype é inútil para resolver um determinado problema de validação, recomenda-se usar expressões regulares. Com expressões regulares é possível realizar uma série de verificações bem complexas, tanto de conteúdo quanto do posicionamento deste no corpo do texto, e também múltiplas ocorrências de padrões de conteúdo.&lt;br /&gt;Para fazer tais verificações com o PHP, pode-se usar as instruções 'ereg' e seus semelhantes, bem como as instruções presentes na extensão PCRE, como a preg_match. Veja maiores detalhes do uso de cada uma destas opções no manual do PHP.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 102);font-size:130%;" &gt;Validação de tamanho de conteúdo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Assim como dados numéricos, entradas de strings precisam atender certas especificações. As expressões regulares podem validar a sintaxe dos dados entrados, mas tabém é importante validar o tamanho da entrada.&lt;br /&gt;&lt;br /&gt;Uma falha que pode ser explorada por um atacante, consiste na geração de um valor que excede o tamanho do campo no banco de dados, e com isso um erro de banco será emitido - se este erro não for tratado, informações valiosas para o atacante poderão ser dadas.&lt;br /&gt;&lt;br /&gt;A solução deste problema possui duas partes: criar os formulários com mecanismos de verificação do conteúdo antes do envio dos dados ao servidor, e a verificação dos mesmos na entrada do script. Nos formulários os campos de textos podem ter tamanho máximo, com o atributo maxlength. Para campos de texto-livre (textarea) é necessário verificar o tamanho do conteúdo ao se enviar os dados, com funções javascript.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);font-size:130%;" &gt;&lt;span style="font-weight: bold;"&gt;Validação de Listas de Seleção&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Listas de valores onde o usuário pode selecionar um item (ou mesmo mais) é outro foco de atenção que o desenvolvedor deve ter. Veja que um atacante pode emular uma requisição injetando novos valores, que podem causar desde erros de processamento, passando por inconsistências, chegando a danificar parcialmente ou consideravelmente o sistema. Portanto, valores discretos como strings que podem ser usadas como chaves em listas de seleção, e até mesmo valores numéricos, devem ser verificados no lado do servidor antes de se prosseguir com o processamento da requisição.&lt;br /&gt;Para realizar essa validação, recomenda-se o uso de uma lista de valores em um array, que será usado na verificação da consistência do valor informado.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-2788421306166663809?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/2788421306166663809/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=2788421306166663809' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2788421306166663809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2788421306166663809'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/03/1-validacao-de-entrada-de-dados.html' title='#1 - Validação de Entrada de dados (primeira parte)'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-5468092703315070956</id><published>2009-02-27T06:07:00.000-08:00</published><updated>2009-02-27T07:40:20.286-08:00</updated><title type='text'>Um pouco mais sobre segurança de arquiteturas web</title><content type='html'>&lt;span style="font-weight: bold;font-size:130%;" &gt;Autenticação&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Dicas importantes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use senhas fortes&lt;/li&gt;&lt;li&gt;Não armazene credenciais sem estarem codificadas em arquivos de codificação&lt;/li&gt;&lt;li&gt;Não transmita arquivos sem estarem criptografados pela rede&lt;/li&gt;&lt;li&gt;Não permita contas super-privilegiadas&lt;/li&gt;&lt;li&gt;Não permita sessões com tempo de vida prolongado&lt;/li&gt;&lt;li&gt;Permita a personalização e o armazenamento de informações de autenticação&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Autenticação de Realm&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Realm significa 'domínio' ou 'reino'. Tratando-se de ambiente de aplicações web, 'realm' significa uma área protegida.&lt;br /&gt;&lt;br /&gt;Autenticação de Realm é usada para proteger recursos dentro de um domínio que está disponível apenas para usuários autorizados.&lt;br /&gt;&lt;br /&gt;O método de autenticação para um 'realm' consiste em registrar um módulo de autenticação para o domínio e definir os atributos de configuração. Isso é feito a nível de servidor web.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Passo-a-passo&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Quando um recurso em particular dentro do domínio é protegido usando a autenticação básica, e quando um usuário tenta acessá-lo, o servidor web envia um cabeçalho de requisição de autenticação (código 401) para o requisitante. Isso notifica o navegador que o recurso não pode ser acessado sem autenticação; em resposta, as credenciais do usuário devem ser supridas para que o recurso requisitado possa ser recuperado. Um formulário de login e senha é aberto pelo browser solicitando ao usuário que entre com seu username e senha. Você pode definir o método de autenticação como Basic ou Digest.&lt;br /&gt;&lt;br /&gt;Nunca use o método básico, porque nesta forma o usuário e a senha são enviados com cleartext, enquanto que no modo Digest a senha é codificada pelo browser usando o algoritmo MD5. Assim, se algum sniffer capturar os dados trocados entre o cliente e o servidor, só terá o hash, e não a senha.&lt;br /&gt;&lt;br /&gt;A autenticação baseada em &lt;span style="font-style: italic;"&gt;Realm &lt;/span&gt;é diferente da autenticação de '&lt;span style="font-style: italic;"&gt;Realm&lt;/span&gt;'; Na autenticação baseada em &lt;span style="font-style: italic;"&gt;Realm&lt;/span&gt;, o usuário pode se autenticar para um domínio ou subdomínio (&lt;span style="font-style: italic;"&gt;subrealm&lt;/span&gt;). Você define diferentes domínios para recursos diferentes, e a autenticação do realm pode ser especificada em uma interface de login como parte da URL pela definição do parâmetro do realm ou parâmetro do domínio.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Gerenciamento de Arquivos de Configuração&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Um sistema é a coleção de muitas partes. Estas partes geralmente incluem programas executáveis, arquivos de parâmetros para customizar o software para um determinado ambiente, e dados.&lt;br /&gt;Se um adversário obtém o arquivo de configuração, todo o sistema pode vir a estar vulnerável.&lt;br /&gt;Por isso é especialmente crítico que estes arquivos de parâmetros e de configuração sejam mantidos em segurança. Além disso, todos os aplicativos que acessem tais arquivos devem ter os privilégios adequados. Para maior proteção da segurança, as seguintes medidas precisam ser tomadas:&lt;br /&gt;       &lt;ul&gt;&lt;li&gt;Use interfaces de administração seguras;&lt;/li&gt;&lt;li&gt;Armazene as informações de configuração em áreas de armazenamento seguras;&lt;/li&gt;&lt;li&gt;Qualquer dado sensível que está sendo armazenado em bases persistentes como seus resultados parciais devem ser atômicos - sempre delete se a transação for tanto bem-sucedida quanto quando falhar - &lt;span style="color: rgb(0, 0, 153);font-size:85%;" &gt;Isso é especialmente útil para evitar que um atacante venha a tentar "quebrar" a aplicação para deixar o arquivo intermediário disponível para leitura.&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Evita armazenar dados de configuração em cleartext.&lt;/li&gt;&lt;li&gt;Evite muitos administradores e múltiplas interfaces de administração.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Gerenciamento de Sessões&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Partindo do princípio de que o protocolo HTTP é stateless, é necessário que se mantenha o estado das aplicações através de sessões. As informações de estado da sessão é transferida do browser em algum formato que sempre é devolvido para o servidor como o contexto do cliente. Esta informação do contexto é crítica para o gerenciamento da sessão e o estado do contexto da mesma. Se um adversário rouba o contexto e o usa em outro terminal dentro do período válido, é possível que ele possa roubar a sessão e assumir a identidade do usuário real.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Passe os identificadores da sessão apenas por canais criptografados;&lt;/li&gt;&lt;li&gt;Não permita sessões com tempo de vida muito prolongados &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Não armazene o estado da sessão em um repositório inseguro - &lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;cuidado especial com a localização do arquivo ou tabela onde são armazenados os dados da sessão, pois se um atacante obtém acesso a eles, pode obter informações valiosas além do identificador da sessão em si.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Evite colocar o identificador de sessão em URLs.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Estas medidas vão ajudar a evitar ataques como '&lt;span style="font-style: italic;"&gt;session hijacking&lt;/span&gt;', '&lt;span style="font-style: italic;"&gt;session replay&lt;/span&gt;', e '&lt;span style="font-style: italic;"&gt;man-in-the middle&lt;/span&gt;'.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Code Injection&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;No ambiente web, a maioria dos relatos de &lt;span style="font-style: italic;"&gt;code injection&lt;/span&gt; são de códigos SQL aplicados com o intuito de obter acesso às bases de dados.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Aqui o atacante pode querer acesso a áreas que normalmente estão disponíveis apenas para usuários com outros níveis de acesso.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Podem querer também roubar informações importantes, como dados pessoais, dados bancários, de cartões de crédito e identificações de outros sistemas.&lt;/li&gt;&lt;li&gt;Em casos de espionagem industrial, o atacante pode querer adulterar a base de dados.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Por fim, um atacante pode tentar excluir completamente uma base de dados, causando DoS (&lt;span style="font-style: italic;"&gt;Denial of Service&lt;/span&gt; - Negação de Serviço)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;A raiz de todos os problemas de &lt;span style="font-style: italic;"&gt;code injection&lt;/span&gt; é que os desenvolvedores colocam muita confiança nos usuários das aplicações. Entretanto, nem todos os usuários na web farão o que o desenvolvedor da aplicação espera.&lt;br /&gt;&lt;br /&gt;Como exemplo, uma pessoa não precisa necessariamente de um browser para acessar a aplicação. De fato, um atacante experiente não usará um browser como o Internet Explorer ou Firefox: o atacante usará um navegador feito especificamente para toda a sorte de coisas ilícitas.&lt;br /&gt;&lt;br /&gt;Como arquiteto de segurança, você não deve nunca confiar no usuário, ou acreditar que ele está operando a aplicação de modo seguro e esperar que ele aja da forma como você deseja. Esta é uma vulnerabilidade relacionada com a programação da aplicação.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Ataque Denial-of-Service (DoS)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Em um ataque DoS, o atacante dispara diferentes ataques de segurança para encontrar uma aplicação ou serviço que não possa ser usado por usuários legitimados. Então, forçando o serviço a estar indisponível é considerado um ataque DoS. Isto pode ocorrer nas seguintes áreas:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;SO&lt;/span&gt;: Ele pode ser a nível de servidor, que está hospedando uma aplicação ou servidor web - o ataque pode ser centrado em alguma vulnerabilidade do sistema operacional, com o intuito de quebrá-lo.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Protocolo&lt;/span&gt;: O ataque também pode ser focado no protocolo TCP/IP. Um ataque comum é o 'half open TCP', onde o buffer TCP é exaurido para disparar o ataque.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Servidor Web&lt;/span&gt;: Pode ser em uma vulnerabilidade do servidor Web. Neste tipo de ataque, o atacante explora uma vulnerabilidade do servidor Web, como um IIS ou Apache.&lt;/li&gt;&lt;li style="color: rgb(204, 0, 0);"&gt;&lt;span style="font-weight: bold;"&gt;Aplicação&lt;/span&gt;: Pode ser uma vulnerabilidade da aplicação. Isso pode ser feito forçando a aplicação a entrar em &lt;span style="font-style: italic;"&gt;looping&lt;/span&gt;, quebrar ou mesmo entrar em &lt;span style="font-style: italic;"&gt;deadlock&lt;/span&gt;.&lt;/li&gt;&lt;/ol&gt;As condições 1 a 3 não estão ligadas diretamente a codificação segura ou a arquitetura da aplicação. Entretanto, a condição 4 está diretamente relacionada com a segurança da arquitetura da aplicação. Está também relacionada com a programação para o ambiente web. Entretanto, se você debugar seu programa para garantir que não há &lt;span style="font-style: italic;"&gt;buffer overflow&lt;/span&gt; ou processos em &lt;span style="font-style: italic;"&gt;looping&lt;/span&gt;, você pode estar seguro.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;"&gt;Tratamento de erros&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Para tornar o software mais amigável, nós geramos mensagens de erros mais acessíveis. De acordo com a prática de engenharia de software, é recomendado que as mensagens de erro sejam incluídas como parte do projeto. Além disso, tais mensagens devem ter significado claro e devem ser detalhadas. A filosofia por trás da mensagem de erro é que o usuário deve obter informações o suficiente para corrigir o erro e executar os próximos passos corretamente.  As mensagens de erro possuem informações de alto-nível sobre o sistema, e isso é um risco em aplicações web;&lt;br /&gt;&lt;br /&gt;Geralmente atacantes deliberadamente entram com entradas incorretas para verificar o comportamento do sistema.  Alguns campos são esperados que sejam preenchidos na interface do usuário; mensagens de erro detalhadas podem ajudar o atacante a conhecer o comportamento do programa. Portanto, enquanto você está projetando o sistema, você deve manter uma coisa em mente: você deve dar o mínimo possível, mas necessárias, informações nas mensagens de erro.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;Fonte: &lt;span style="font-style: italic;"&gt;Architecting Secure Software Systems&lt;/span&gt;,&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-5468092703315070956?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/5468092703315070956/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=5468092703315070956' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5468092703315070956'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5468092703315070956'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/02/um-pouco-mais-sobre-seguranca-de.html' title='Um pouco mais sobre segurança de arquiteturas web'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-8636980511464521153</id><published>2009-02-26T18:11:00.000-08:00</published><updated>2009-03-02T10:47:45.143-08:00</updated><title type='text'>1. Validação de Entrada de dados</title><content type='html'>Um dos princípios que devem ser sempre observados em sistemas web, é o de que as entradas de dados são essencialmente inseguras - isso quer dizer que os dados são geralmente não confiáveis.&lt;br /&gt;&lt;br /&gt;Até o momento em que os dados chegam ao script PHP, estes saíram do browser do cliente, passaram por um conjunto de nós de rede que incluem proxys, firewals, ferramentas de filtragem, etc. Qualquer um destes passos possui atrelada uma oportunidade - seja intencional ou acidental, de corromper ou alterar os dados de modo inesperado.&lt;br /&gt;&lt;br /&gt;Considerando ainda que os dados podem ser adulterados neste longo caminho, ou mesmo forjados por atacantes que obtiveram informações privilegiadas a partir deste ou de outros sistemas, é absolutamente imperativo que todos os dados de entrada no sistema sejam validados para garantir que eles batam com os formatos e conteúdos esperados.&lt;br /&gt;&lt;br /&gt;Embora a validação dos dados não seja a solução universal para todos os problemas de segurança que possam haver em um sistema, boa parte das falhas podem ser corrigidas assumindo a postura de validação total.&lt;br /&gt;&lt;br /&gt;Isso inclui:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;a verificação dos tipos de dados - como datas, numéricos, alfanuméricos, etc.&lt;/li&gt;&lt;li&gt;a checagem do tamanho máximo permitido - um campo deve ter especificado o número mínimo e máximo de caracteres que deve ser informado; evidentemente que campos não obrigatórios possuem o tamanho mínimo igual a zero.&lt;/li&gt;&lt;li&gt;a verificação da consistência do conteúdo tem como objetivo analisar se o padrão do conteúdo está dentro do esperado - campos com máscara ou formato tais como CEP, CPF, CNPJ, são bons exemplos disso.&lt;/li&gt;&lt;li&gt;o teste de consistência lógica - códigos informados podem ser verificados antes de proceder com as demais atividades; isso quer dizer, que em alguns casos, podemos verificar se determinado registro existe na base de dados.&lt;/li&gt;&lt;li&gt;o teste de código injetado - verificar se o campo possui código suspeito, como instruções SQL, HTML ou javascript.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-8636980511464521153?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/8636980511464521153/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=8636980511464521153' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8636980511464521153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8636980511464521153'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/02/1-validacao-de-entrada-de-dados.html' title='1. Validação de Entrada de dados'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-875226935363113073</id><published>2009-02-26T18:09:00.000-08:00</published><updated>2009-02-26T18:11:20.875-08:00</updated><title type='text'>Guide to PHP Security #1</title><content type='html'>Este é o início de uma série que pretendo postar, onde vou traduzir e comentar trechos do Guia para Segurança em PHP (Guide to PHP Security).&lt;br /&gt;&lt;br /&gt;Abaixo seguem os capítulos do livro:&lt;br /&gt;&lt;br /&gt;1. Validação de Entrada de dados&lt;br /&gt;2. Prevenção de Cross-Site Scripting (CSS)&lt;br /&gt;3. SQL Injection&lt;br /&gt;4. Preveningo Code Injection&lt;br /&gt;5. Command Injection&lt;br /&gt;6. Segurança de Sessão&lt;br /&gt;7. Segurança de acesso a arquivos&lt;br /&gt;8. Segurança através da obscuridade&lt;br /&gt;9. Sandboxes e Tar Pits&lt;br /&gt;10. Fazendo com que sua aplicação seja segura&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-875226935363113073?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/875226935363113073/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=875226935363113073' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/875226935363113073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/875226935363113073'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/02/guide-to-php-security-1.html' title='Guide to PHP Security #1'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-4143827780454698861</id><published>2009-02-25T17:41:00.000-08:00</published><updated>2009-03-02T10:47:45.236-08:00</updated><title type='text'>Vulnerabilidades de uma aplicacao Web</title><content type='html'>Podemos notar alguns pontos de vulnerabilidades em sistemas web, tais como:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Web-client&lt;/span&gt; - browser e outros aplicativos que se comunicam com o sistema; pode sofrer ataques de engenharia reversa, onde falhas de seguranca sao procuradas e exploradas pelo atacante.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Comunicacao entre o web-client e o web-server&lt;/span&gt; - o canal de comunicacao entre os dois componentes, pode ser investigado atraves de sniffers e outras ferramentas. Os ataques podem ser adulteracao de conteudo (&lt;span style="font-style: italic;"&gt;Parameter tampering&lt;/span&gt;) e negacao de servicos (&lt;span style="font-style: italic;"&gt;Denial of service&lt;/span&gt;). &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-4143827780454698861?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/4143827780454698861/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=4143827780454698861' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/4143827780454698861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/4143827780454698861'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/02/vulnerabilidades-de-uma-aplicacao-web.html' title='Vulnerabilidades de uma aplicacao Web'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-5962063515214410774</id><published>2009-02-25T17:29:00.000-08:00</published><updated>2009-02-25T17:39:46.251-08:00</updated><title type='text'>Principios de seguranca de sistemas Web</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Principio #1 &lt;/span&gt;- O defensor deve defender todos os pontos; o atacante pode escolher o ponto mais fraco.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Principio #2&lt;/span&gt; - O defensor pode defender somente contra ataques conhecidos; o ataque pode testar por vulnerabilidades desconhecidas.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Principio #3&lt;/span&gt; - O defensor deve estar constantemente vigilante; o atacante podera atacar quando ele puder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Principio #4&lt;/span&gt; - O defensor deve jogar pelas regras; o atacante pode jogar sujo.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Principio #5&lt;/span&gt; - O defensor deve ser bem-sucedido em todo o tempo, defendendo seu sistema; o atacante precisa ser bem-sucedido apenas uma vez.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Principio #6 &lt;/span&gt;- O protetor precisa conhecer o sistema a ser protegido e como protege-lo de ataques; o atacante usa aplicativos-robos para gerar combinacoes e padroes de ataque que sao lancados arbitrariamente sem se preocupar com os recursos - para o atacante, a unica restricao e o tempo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-5962063515214410774?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/5962063515214410774/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=5962063515214410774' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5962063515214410774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5962063515214410774'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/02/principios-de-seguranca-de-sistemas-web.html' title='Principios de seguranca de sistemas Web'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-60981021575783033</id><published>2009-01-07T18:08:00.000-08:00</published><updated>2009-02-27T09:25:47.015-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='prototipacao'/><category scheme='http://www.blogger.com/atom/ns#' term='processo de desenvolvimento'/><title type='text'>Prototipando interface de usuario</title><content type='html'>Pensando muito no processo de desenvolvimento, entendi que é muito importante que seja feita a prototipação da interface com o usuário. Mas existem questões como:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;criar protótipo dinâmico ou estático?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;criar um protótipo reutilizável?&lt;/li&gt;&lt;li&gt;o que fazer com o protótipo na fase de construção?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Penso que para responder a estas perguntas temos que definir alguns principios e uma linha-mestra que vai dirigir esta reflexão.&lt;br /&gt;&lt;br /&gt;Em primeiro lugar, temos que definir a necessidade do protótipo visual, e seu papel no processo de desenvolvimento. Na minha opinião, o protótipo visual servirá para obter a aprovação junto ao usuário, do que é esperado como interface com o sistema. Então uma premissa que deve ser estabelecida é: a &lt;span style="font-weight: bold;"&gt;criação do protótipo deve ser feita na frente do usuário&lt;/span&gt;. Isso porque se formos fazer anotações e depois montar o protótipo, apresentando-o em outro momento, podemos perder detalhes do que foi conversado, e o usuario poderá esquecer de itens que foram tratados ou até mesmo já ter criado novas espectativas. Isso nos leva a outro ponto muito importante: &lt;span style="font-weight: bold;"&gt;Para que o protótipo seja feito na frente do usuário, a ferramenta de desenho deve ser ágil e produtiva&lt;/span&gt;: se a sessão de prototipação demorar demais, podemos perder a atenção do usuário, e assim tornar a reunião cansativa demais. Assim, ou adotamos uma ferramenta digital, como a &lt;a href="http://www.balsamiq.com/products/mockups"&gt;Balsamiq Mockups&lt;/a&gt;,  ou desenhamos em folhas de papel, que depois podem ser digitalizadas. A vantagem da folha de papel é a liberdade em desenhar componentes e fazer anotações. Seus problemas são a leitura de letras de difícil compreensão e a dificuldade de rearranjar facilmente os componentes. A vantagem de uma ferramenta como a Balsamiq é que o desenho, embora não funcional, já fica armazenado e permite mudanças rápidas. É bem amigável e funciona bem para interfaces relativamente complexas. Podemos até arriscar a deixar um cliente mais experiente no uso do computador desenhando as telas desejadas. O problema é quando se deseja usar componentes que não existem - neste caso recomendo usar anotações mesmo.&lt;br /&gt;&lt;br /&gt;Bom, já comecamos definindo implicitamente que o protótipo não sera funcional, ou seja, será apenas um anexo na documentação de análise. Entretanto, a menos que use uma ferramenta como o Adobe Flex Builder, ou interface de linguagem de 4a geração, podemos perder mais tempo desenhando uma interface bem elaborada, quando poderíamos deixar os detalhes para depois. Então, a menos que se tenha um ferramental ágil para desenvolver o protótipo funcional inicial, vamos optar pelo estático mesmo.&lt;br /&gt;&lt;br /&gt;Uma vez que o protótipo tenha sido desenhado e pré-aprovado pelo cliente, então podemos partir para desenvolver a interface do usuário, mandando as imagens do rascunho inicial para que o designer possa desenvolver os componentes. Recomendo que nesta fase, que pode ser realizada enquanto se faz o projeto físico, faça-se apenas os formulários, sem atuação de um componente &lt;span style="font-style: italic;"&gt;Action&lt;/span&gt; (ainda).  A idéia é que no final da etapa de projeto lógico e físico, seja apresentada a interface para o usuário - dependendo do grau de experiência do cliente, do tempo disponível e da dimensão do sistema, podemos apresentar o protótipo inicial, as telas como vão ficar, os casos de uso, a lista de requisitos e o modelo de domínio simplificado.&lt;br /&gt;&lt;br /&gt;Uma vez aprovado, podemos partir para o desenvolvimento dos &lt;span style="font-style: italic;"&gt;actions&lt;/span&gt; com as respostas e apresentar logo em seguida - isso dará um senso de organização e de que o trabalho esta fluindo bem.&lt;br /&gt;&lt;br /&gt;Já que firmamos a linha-mestra e alguns princípios, vamos discutir um pouco mais sobre como funcionarão as coisas em um caso tipico.&lt;br /&gt;&lt;br /&gt;Considerando um sistema simples, com a maioria dos formulários sendo apenas CRUD, podemos focar apenas em um ou dois para obter o sentimento do usuário, e depois dar maior importância para os formulários mais complexos. A desenhos do protótipo inicial deverão ser arquivados junto com o modelo do sistema, ficando disponíveis para todos envolvidos no projeto. Para isso, cria-se um objeto "artifact" no modelo do EA, associando-o com  arquivo do protótipo.  Após sua aprovação formal pelo usuário (que preferencialmente deve ocorrer no momento da entrevista), o &lt;span style="font-style: italic;"&gt;designer&lt;/span&gt; entra em ação, criando a interface em HTML e javascript propriamente dita. As alterações que forem sendo feitas não precisam necessariamente ser replicadas no desenho feito, mas recomenda-se pelo menos documentar as mudancas feitas, justificando o porque de não fazer, fazer diferente ou incluir determinado componente. Este tipo de registro deve ser feito no EA, como uma lista de questões ligadas a este artefato. Estas questões deverão ser recuperadas pelo sistema gestão de desenvolvimento e manutenção (atrelado ao Dotproject), e serão usados no relatório do projeto.&lt;br /&gt;O resultado final poderá também  gerar um &lt;span style="font-style: italic;"&gt;screenshot&lt;/span&gt; que será anexado ao mesmo artifact (com o label de  "feito").&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-60981021575783033?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/60981021575783033/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=60981021575783033' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/60981021575783033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/60981021575783033'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/01/prototipando-interface-de-usuario.html' title='Prototipando interface de usuario'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-3789539938059031513</id><published>2009-01-06T18:41:00.000-08:00</published><updated>2009-01-07T17:05:58.400-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='processo de desenvolvimento'/><title type='text'>Engenharia de Negocios para o Desenvolvimento Agil</title><content type='html'>A partir desta introducao de arquitetura de negocios, vamos...&lt;br /&gt;A abordagem tipica que e' usada para projetar e construir sistemas empresariais com metodos de desenvolvimento de sistemas tradicionais, pode ser resumida como:&lt;br /&gt;1) Os requisitos de sistemas sao tipicamente definidos pela equipe de TI, atraves de entrevistas com usuarios, para determinar suas necessidades operacionais e de negocio;&lt;br /&gt;2) O projeto que e' definido e' tanto baseado na tecnologia, com projeto da aplicacao, de banco de dados e objetos, refletindo esta tecnologia;&lt;br /&gt;3) Este projeto e' implementado para atender os requisitos desejados para o negocio.&lt;br /&gt;&lt;br /&gt;Esta abordagem tradicional para desenvolvimento de sistemas tem sido dependente da tecnologia, e sua adocao resulta nos seguintes problemas:&lt;br /&gt;1) As necessidades de negocio sao dificeis de se determinar - se uma necessidade nao for compreendida ou expressa claramente, o projetista de sistemas nao a enderecara as reais necessidades dos usuarios e dos gerentes;&lt;br /&gt;2) Os sistemas que sao desenvolvidos nao sao alinhados com os objetivos corporativos que definem as direcoes para o futuro. Este e' um dos maiores problemas com o desenvolvimento de sistemas atualmente.&lt;br /&gt;3) As direcoes estrategicas nao sao claras - ainda assim elas devem ser compreendidas pela area de TI, para projetar sistemas flexiveis que suportem mudancas estrategicas de direcao.&lt;br /&gt;&lt;br /&gt;Na realidade, os problemas com os metodos tradicionais de desenvolvimento sao muito maiores que o sugerido na lista acima. As necessidades do negocio tem sido tradicionalmente sido decididas pela revisao dos processos operacionais do negocio. Estes processos foram determinados baseando-se nos planos estrategicos tipicamente definidos muitos anos atras, algumas vezes, mais de uma decada atras.&lt;br /&gt;Ainda na decada de 90, nao temos ideia de que seria possivel fazer as coisas que fazemos, ou o que podemos fazer atraves da comunicacao instantanea com os clientes, fornecedores e parceiros de negocios em qualquer lugar do mundo, atraves da Internet. O ambiente que aceitamos hoje como normal estava alem da imaginacao da maioria.&lt;br /&gt;Os planos estrategicos definidos na decada de 90 nao anteciparam o que estas organizacoes poderiam fazer hoje, comunicando-se com cada um em poucos segundos. Eles assumiram que as comunicacoes seriam sempre feitas via cartas, ou talvez por fax, com respostas recebidas dias ou semanas depois. Assumia-se que as respostas mais rapida destes processos de negocio seriam feitas em horas. Os processos de negocio nao foram projetados para serem respondidos em segundos.&lt;br /&gt;Este ponto e' de importancia vital e deve ser enfatizado:&lt;br /&gt;*As abordagens tradicionais de desenvolvimento de sistemas - baseadas em entrevistas com usuarios em processos de negocio e identificando suas necessidades futuras - nao trabalha bem com periodos em que as mudancas ocorrem muito rapidamente, como atualmente.*&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;pg 49&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-3789539938059031513?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/3789539938059031513/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=3789539938059031513' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/3789539938059031513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/3789539938059031513'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2009/01/engenharia-de-negocios-para-o.html' title='Engenharia de Negocios para o Desenvolvimento Agil'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-1192626021088944384</id><published>2008-12-26T16:32:00.000-08:00</published><updated>2008-12-30T15:59:08.723-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='seguranca programacao'/><title type='text'>Programacao Segura</title><content type='html'>&lt;span style="font-size:130%;"&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;Atributos de Seguranca&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Existem muitos atributos para seguranca que sao essenciais na programacao segura. Estes atributos sao confidencialidade, integridade, disponibilidade, autenticacao, autorizacao, contabilidade (auditoria) e anonimicidade. Algumas literaturas definem atributos adicionais, mas nada mais sao do que variacoes destas.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;1. Confidencialidade&lt;/span&gt;&lt;br /&gt;Confidencialidade e o mecanismo atraves do qual mantemos o significado das informacoes ou dados secretos. Em outras literaturas esta propriedade e' tambem conhecida como privacidade ou criptografia. No caso de seguranca de rede, confidencialidade e atingida pela alteracao do significado dos dados atraves de criptografia. Em programacao segura voce precisa garantir que o programa que voce escreve ira manter o dado em segredo. Em outras palavras, ninguem devera poder facilmente aplicar engenharia reversa na logica do programa e acessar os dados. Considerando a situacao onde voce como um programador escreve um software que sera usado por um banco. Havendo um bug de seguranca em seu programa, permitira que um hacker transfira milhoes de dolares do banco. Alem disso, como programador voce devera garantir que seu programa nao quebre, causando um DoS.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;2. Integridade&lt;/span&gt;&lt;br /&gt;Esta e' a propriedade atraves da qual voce pode detectar se sua mensagem ou dado foi corrompido ou adulterada. Isso e' muito util na deteccao de ataques ativos em seus dados. Para garantir a integridade voce gera informacoes adicionais para verificar a integridade da acao. Por exemplo, quando voce recebe algum dado de outro programa, voce verifica o valor do checksum do dado, ou a assinatura digital, para garantir que a integridade dos dados seja preservada.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;3. Disponibilidade&lt;/span&gt;&lt;br /&gt;Se o programa que voce escreve nao rodar quando ele for mais necessario, entao o proposito do programa nao foi atingido. Assumamos que voce tenha desenvolvido uma aplicacao App1 para Empresa1. Possuindo algum bug, uma das funcoes desta aplicacao entra em looping indefinidamente. Chega ao conhecimento deste bug a um competidor da Empresa1, possibilitando-o a gerar uma entrada de dados que explora este bug. Durante a hora de pico dos negocios, alguem explora este bug para fazer com que o programa entre em looping, resultando em aplicacoes ficando indisponiveis aproximadamente meia-hora. Este e um exemplo de bugs de seguranca relacionados a disponibilidade.&lt;br /&gt;Disponibilidade e um atributo de seguranca onde e' necessario que o servico esteja disponivel em um periodo de adversidade. Qualquer ataque na disponibilidade e chamado de DoS (Denial of Service). No mundo interconectado de hoje, a escalabilidade de sistemas tambem pode ser categorizado como parte do desafio da disponibilidade.  Existem muitos ataques que sao especialmente dirigidos para o aspecto da disponibilidade do servico. Programacao segura pode enderecar algums dos desafios da disponibilidade relacionados ao programa. Outros desafios da disponibilidade precisam ser enderecados atraves da seguranca do perimetro.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;4. Autenticacao&lt;br /&gt;&lt;/span&gt;Autenticacao e nao-repudiacao sao alguns propriedades que estao relacionados entre si. Autenticacao e' o processo atraves do qual validamos a identidade das partes envolvidas em uma transacao. Na nao-repudiacao nos identificamos que a identidade das partes nao possui duvidas. Assinatura digital pode alcancar a nao-repudiacao. A maioria das autenticacoes que voce ve ao redor sao autenticacoes ditas 'single-factor'. Entretanto, autenticacao multifatorial e' preferida em certas circunstancias. Vamos descrever o que e' isso mais adiante.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;5. Autorizacao&lt;/span&gt;&lt;br /&gt;Nesta propriedade, voce adiciona restricoes de uso a objetos com niveis de seguranca ou privilegios. A menos que o usuario seja membro de um grupo com certos privilegios, o usuario nao podera acessar determinados recursos. Isto pode ser considerado como nivel de confianca do usuario.&lt;br /&gt;Este atributo tambem e' chamado de controle de acesso de baixa granularidade ou seguranca baseada no papel.&lt;br /&gt;A industria de telecomunicacoes, operadoreas de telefonia movel ou fixa, provisiona diferentes servicos para seus assinantes. Concessao significa que servicos estao disponiveis para um dado assinante. Por exemplo, uma chamada pode ser originada enquanto que uma roaming pode ser barrada.&lt;br /&gt;Concessao em telecomunicacoes e' equivalente ao atributo de autorizacao em seguranca ds computacao.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;6. Contabilidade&lt;/span&gt;&lt;br /&gt;Para qualquer servico, o provedor de servicos precisa ser pago. Auditoria e' o processo pelo qual o uso do servico e' medido. Baseado no uso, o provedor de servicos coleta as taxas do consumidor. Trilhas de auditoria e logs de transacoes em aplicacao pode ser considerada como parte da informacao da contabilidade; estes arquivos precisam estar seguros, evitando que adversarios deletem ou adultere-os. o nao-pagamento para uma chamada telefonica e' um risco de seguranca para funcoes de contabilidade para a operadora de telecomunicacoes.&lt;br /&gt;De modo similar, acessando transacoes bancarias mas nao sendo registradas e' uma ameaca de seguranca para a aplicacao bancaria.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;7. Anonimicidade&lt;/span&gt;&lt;br /&gt;Anonimicidade e' outra propriedade de seguranca. A anonimicidade e' a propriedade atraves da qual o usuario permanece anonimo para o mundo externo. Por exemplo: em um sistema de votacao eletronica, o votante precisa permanecer anonimo para que ninguem possa saber em quem ele votou. Incluimos esta propriedade aqui para completar e enfatizar a propriedade de seguranca, mas nao trataremos da anonimicidade neste livro.&lt;br /&gt;&lt;br /&gt;Trecho extraido do livro "&lt;span style="font-style: italic;"&gt;Architecting Secure Software Systems&lt;/span&gt;".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-1192626021088944384?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/1192626021088944384/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=1192626021088944384' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/1192626021088944384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/1192626021088944384'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/12/programacao-segura.html' title='Programacao Segura'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-2403797105096620319</id><published>2008-07-09T20:11:00.000-07:00</published><updated>2008-07-09T20:38:49.422-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='processo de desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='gerência de projetos'/><category scheme='http://www.blogger.com/atom/ns#' term='classbuilder'/><title type='text'>Gerenciamento de Projetos</title><content type='html'>Para facilitar o trabalho de GP, penso que posso adotar algumas praticas:&lt;br /&gt;&lt;br /&gt;1) Ao planejar um sistema, posso organizar a WBS da seguinte forma: No primeiro nivel, coloco as fases; No segundo nivel,  posso organizar as iteracoes;  Depois coloco os produtos/artefatos que deverao ser gerados para se completar a  iteracao; por fim, posso colocar as tarefas dentro de cada produto.&lt;br /&gt;&lt;br /&gt;2)  As tarefas devem estar enquadradas nas disciplinas existentes no processo;&lt;br /&gt;&lt;br /&gt;WBS tipica:&lt;br /&gt;1. Iniciacao&lt;br /&gt;1.1 Iteracao 1&lt;br /&gt;1.1.1. Documento de Visao&lt;br /&gt;1.1.1.1. GP.01 - Elaborar Documento de Visao&lt;br /&gt;1.1.1.2. GP.02 - Elaborar Cronograma&lt;br /&gt;2. Elaboracao&lt;br /&gt;2.1. Iteracao 1&lt;br /&gt;2.1.1. Modelo de Requisitos&lt;br /&gt;2.1.1.1.  REQ.01 - Elicitar Requisitos&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Organizando desta forma, fica mais facil de padronizar os cronogramas.&lt;br /&gt;&lt;br /&gt;Veja que podemos aproveitar as "visoes" do modelo do EA para montar a WBS. A unica dificuldade pode estar na divisao em iteracoes. Dai a solucao pode ser usar o campo 'fase' ou 'versao' dos artefatos. Se houverem tarefas que nao existam no "manual de processo", depois acrescenta-se.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Sera necessario cadastrar o processo no dot, para que possa mapear os artefatos lidos pelo classbuilder com o processo, e gerar o projeto.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-2403797105096620319?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/2403797105096620319/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=2403797105096620319' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2403797105096620319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2403797105096620319'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/07/gerenciamento-de-projetos.html' title='Gerenciamento de Projetos'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-8595260090490726118</id><published>2008-05-01T17:37:00.001-07:00</published><updated>2008-05-01T18:26:21.426-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gerência de projetos'/><category scheme='http://www.blogger.com/atom/ns#' term='metricas'/><title type='text'>Metricas...</title><content type='html'>Talvez uma das maiores dificuldades em projetos de desenvolvimento de sistemas, do ponto de vista comercial, e' a estimativa acurada dos recursos necessarios, prazo e custo. Em (grande) parte, a culpa pode ser atribuida aos requisitos mal-definidos no comeco, ou a mudanca destes ao longo do projeto, fruto da falta de compreensao ou experiencia do cliente sobre suas reais necessidades ou processos de negocio mal-definidos.&lt;br /&gt;&lt;br /&gt;Entretanto, nao podemos deixar de considerar o fato de que as ferramentas de medicao existente sao pouco eficazes na estimacao de projetos de software. Estudando os elementos que compoem o universo envolvido no processo de especificacao de software, posso identificar:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;cliente (usuarios, gerentes),&lt;br /&gt;&lt;/li&gt;&lt;li&gt;processos de negocio,&lt;br /&gt;&lt;/li&gt;&lt;li&gt;requisitos (informados pelo cliente e usuario)&lt;/li&gt;&lt;li&gt;reais necessidades&lt;br /&gt;&lt;/li&gt;&lt;li&gt;tecnologias, ferramentas tecnologicas e metodologias  (tanto as existentes no cliente quanto as usadas pelo fornecedor),&lt;br /&gt;&lt;/li&gt;&lt;li&gt;ambientes de producao (cliente),&lt;br /&gt;&lt;/li&gt;&lt;li&gt;ambiente de desenvolvimento&lt;/li&gt;&lt;li&gt;tecnicas e ferramentas de comunicacao entre cliente-fornecedor,  equipes internas de desenvolvimento, e entre os usuarios do proprio cliente&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Vejam que todos estes componentes afetam, em maior ou menor grau, os projetos de software. Nao considerei aqui nenhum artefato usado por quaisquer metodologia, como modelos de casos de uso, modelos de dados, fluxogramas, diagramas de classes, etc.&lt;br /&gt;&lt;br /&gt;Observem que quando um cliente solicita a proposta de um sistema, muito pouco se sabe das reais necessidades. Dai surgem duas situacoes: ou se faz um levantamento de requisitos muito superficial, que dara poucos subsidios para uma estimacao bem feita, ou se investe recursos proprios para se fazer um bom levantamento de requisitos, que dara um bom nivel de detalhamento para se fazer a estimacao, mas que podera nao gerar retorno (pois orcamento nao sera necessariamente aceito pelo cliente). Do ponto de vista comercial e tatico, este e' um problema, pois demanda um esforco que nem sempre esta disponivel. Por outro lado, se aceitarmos fazer apenas uma estimativa fraca, baseada no levantamento de requisitos superficial, corremos o risco de perder o contrato se adotarmos a estrategia de super-estimar o  projeto, ou  obte-lo sub-dimensionando-o. Neste caso, podemos perder ao financia-lo. Ja vi varios casos onde assumir um projeto sem conhece-lo adequadamento deu prejuizo. Isso porque depois que um contrato foi feito, e boa parte do cinheiro pago, na &lt;span style="font-style: italic;"&gt;last-mile&lt;/span&gt; do novo sistema podem ser descobertas novos detalhes antes nao detectados, que podem fazer com que o fornecedor necessite alocar recursos antes nao dimensionados, gerando um custo nao previsto.&lt;br /&gt;&lt;br /&gt;Vamos estudar estes aspectos em separado, e depois propor um metodo de estimacao de projetos de software. Nos proximos posts vou trabalhar nisso.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-8595260090490726118?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/8595260090490726118/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=8595260090490726118' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8595260090490726118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8595260090490726118'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/05/metricas.html' title='Metricas...'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-2888360016043559299</id><published>2008-03-21T13:46:00.001-07:00</published><updated>2008-03-21T14:00:01.954-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='ETL'/><category scheme='http://www.blogger.com/atom/ns#' term='orientação a objetos'/><title type='text'>Padrao de ETL</title><content type='html'>Refletindo um pouco sobre a quantidade de coisas que terao que se comportar como ferramentas de ETL (Extract, Transform and Load), pensei que seria interessante definir um padrao que otimize nossos esforcos em desenvolver tais ferramentas.&lt;br /&gt;&lt;br /&gt;Talvez um modelo interessante seja o de se ter uma classe Processadora que contenha pelo menos 5 atributos&lt;br /&gt;&lt;br /&gt;class ProcessadoraAbstract {&lt;br /&gt;    private $E = new ExtractorBase();&lt;br /&gt;    private $ETI;&lt;br /&gt;    private $T = new TransformerBase();&lt;br /&gt;    private $TLI;&lt;br /&gt;    private $L = new LoaderBase();&lt;br /&gt;&lt;br /&gt;     public function exec($parmExtract) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;O objeto E e' responsavel pela carga dos dados. Quando o objeto processador for executado, devera ser passado como parametro o path ou os dados a se tratar; O processador invoca entao o E que faz o trabalho da carga e depois coloca o resultado na variave ETI (Extract Transform Interface), que ficara disponivel para o objeto T, que fara as transformacoes necessarias e coloca o resultado em TLI (Transform Load Interface), que faz a carga final dos dados no destino.&lt;br /&gt;Organizando as coisas desse jeito, podemos criar, por exemplo, um driver especializado na leitura de um arquivo texto que esta em um servidor FTP, como uma instancia de E. Depois, sem alterar os demais processos, podemos fazer um driver que acesse um banco de dados SQLServer; Desde que se obedeca fielmente os padroes ETI e TLI, conseguimos isso facilmente.&lt;br /&gt;&lt;br /&gt;Para o projeto Progem, isso sera especialmente util, uma vez que teremos que prever varias formas de importacao dos dados, e agindo assim podemos deixar as coisas mais preparadas para varios niveis de adaptacao.&lt;br /&gt;&lt;br /&gt;Poderiamos ate pensar em adotar uma ferramenta ETL convencional ou ate comercial, mas o custo de adaptacao em relacao a complexidade dos nossos problemas nao me leva a crer que valha a pena. Alem do mais, se a complexidade aumentar, temos plenas condicoes de alterar as classes e adequa-las para novas realidades, o que poderia ser mais dificil se pensar em ferramentas de terceiros.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-2888360016043559299?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/2888360016043559299/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=2888360016043559299' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2888360016043559299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2888360016043559299'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/padrao-de-etl.html' title='Padrao de ETL'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-5904894881123940879</id><published>2008-03-20T07:05:00.000-07:00</published><updated>2008-03-20T15:40:03.120-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><category scheme='http://www.blogger.com/atom/ns#' term='orientação a objetos'/><title type='text'>Uma visão da nova arquitetura</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Xn9qMcEj48M/R-LVAnLVU1I/AAAAAAAAAtw/bP_N9yqMykM/s1600-h/Modelo+OO.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://4.bp.blogspot.com/_Xn9qMcEj48M/R-LVAnLVU1I/AAAAAAAAAtw/bP_N9yqMykM/s320/Modelo+OO.png" alt="" id="BLOGGER_PHOTO_ID_5179936727922725714" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Pensando e repensando em nossos objetivos, em se adotando a tal da arquitetura em 3 camadas, vi que existem algumas questões que precisam ficar bem esclarecidas. Só que agora o foco não está no nível puramente conceitual, mas sim na aplicação prática do modelo.&lt;br /&gt;&lt;br /&gt;Por isso decidi postar este artigo, descrevendo um pouco mais a arquitetura e com isso, ajudar a defini-la o mais rápido possível.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 102);font-family:arial;font-size:180%;"  &gt;Conceitos básicos&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0); font-style: italic;"&gt;Action &lt;/span&gt;(&lt;a href="http://en.wikipedia.org/wiki/Command_pattern"&gt;link&lt;/a&gt; - &lt;span style="font-size:78%;"&gt;também conhecido como padrão &lt;span style="font-style: italic;"&gt;Command&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;Responsável pelas interações com o usuário, seja ele um navegador, um dispositivo móvel ou qualquer outro "robô". Recebe uma requisição de uma operação, conceitualmente atômica, que deverá ser realizada pelo sistema. Ele invoca quem sabe realizar a tal tarefa, e depois formata o resultado da forma mais conveniente.&lt;br /&gt;As responsabilidade dos &lt;span style="font-style: italic;"&gt;Actions &lt;/span&gt;são:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Receber a requisição de execução de uma operação;&lt;/li&gt;&lt;li&gt;Receber e tratar os dados enviados;&lt;/li&gt;&lt;li&gt;Delegar a execução a quem de direito;&lt;/li&gt;&lt;li&gt;Obter o resultado das operações;&lt;/li&gt;&lt;li&gt;Formatar os dados para exibição;&lt;/li&gt;&lt;li&gt;Enviar as respostas ao solicitante;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold; color: rgb(255, 0, 0);"&gt;Business Objects&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt; (BO) &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Business_object_%28computer_science%29"&gt;(link)&lt;/a&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;&lt;span style="font-size:85%;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Um objeto de negócio é uma classe que geralmente está no modelo de domínio dos processos de negócio. Ele pode ser persistente ou não, mas possui tanto os atributos quanto os métodos de negócio.&lt;br /&gt;Ele não deve ser entendida como um simples mapeamento para a camada de dados, uma vez que quem faz isso é o &lt;span style="font-style: italic;"&gt;Active Record &lt;/span&gt;(AR).&lt;br /&gt;O BO concentra os métodos de acesso aos atributos (&lt;span style="font-style: italic;"&gt;getters e setters&lt;/span&gt;) e os de negócio, onde estão encapsuladas as regras de negócio.&lt;br /&gt;O ato de persisitir um BO consiste em um conjunto de operações de instanciação de objetos AR, atribuição de valores, testes e efetivação da gravação. Um BO pode ter mais de um AR associado, e por isso o processo pode ser complexo.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold; color: rgb(255, 0, 0);"&gt;Active Record &lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;(AR) &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Active_record_pattern"&gt;(link)&lt;/a&gt;&lt;br /&gt;O &lt;span style="font-style: italic;"&gt;Active Record&lt;/span&gt; é um objeto que mapeia a tabela no banco, permitindo o fácil acesso à base, através de uma camada de abstração de banco de dados.&lt;br /&gt;Os nomes dos atributos devem ser iguais às das colunas nas tabelas do banco de dados, e a classe possui apenas os métodos &lt;span style="font-style: italic;"&gt;getters &lt;/span&gt;e &lt;span style="font-style: italic;"&gt;setters&lt;/span&gt;.&lt;br /&gt;A importância do AR está na sua simplicidade, visto que seu papel é apenas um: transportar dados entre a camada de negócios e a de persistência.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic; font-weight: bold; color: rgb(255, 0, 0);"&gt;Data Access Object&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt; (DAO) &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Data_Access_Object"&gt;(link)&lt;/a&gt;&lt;br /&gt;O &lt;span style="font-style: italic;"&gt;Data Access Object&lt;/span&gt; é responsável pelo trânsito de dados entre o sistema e o "mundo externo". O mundo externo pode ser outros sistemas, serviços, arquivos hospedados em servidores FTP, HTTP, webservices, etc. É um objeto que realiza serviços de integração. Seu uso depende do tipo de sistema e das necessidades de integração.  Alguns tipos de integração permitem que um serviço rode periodicamente e realize a integração entre os sistemas; já outros precisam que   a integração seja imediata. O uso do DAO deve ser visto com muito cuidado, e exige um bom planejamento.&lt;br /&gt;&lt;span style="font-size:180%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;span style="font-size:180%;"&gt;&lt;span style="color: rgb(0, 0, 102);font-family:arial;" &gt;Perguntas e Respostas&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;P. Posso usar operações com lógica de negócio embutida, em classes AR?&lt;/span&gt;&lt;br /&gt;R. Até poderiamos fazer isso, mas a complexidade dos ARs poderia dificultar as manutenções. Além disso, o AR é o mapeamento fiel ao modelo de dados, e nem sempre teremos classes de negócio que reflitam exatamente o modelo persistente. Assim, o melhor será separar o controle (BO) da persistência (AR), e colocar nos BOs a lógica de negócio.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Um BO pode acessar mais de um AR?&lt;/span&gt;&lt;br /&gt;R. Sim. Embora na maioria dos casos o BO será um espelho de um AR, podem haver casos em que um BO tenha que recuperar um AR e atualizar outro. Além disso, por questões de performance, podemos criar um BO que tenha atributos de ARs diferentes. Por fim, o BO é um modelo de classe de negócio, e por isso, poderá conter elementos como listas e objetos, coisa que um AR não terá.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Por que 'burocratizar' as operações simples, como a pesquisa de um registro no banco, tendo que obrigatoriamente passar pelo BO?&lt;/span&gt;&lt;br /&gt;R. Embora o acesso direto seja mais prático e rápido de se implementar, o uso de etapas e responsabilidades em camadas dá um isolamento entre estas, que permite uma manutenção com pouco impacto final nas demais. A inclusão de um campo, ou mudança de tipo, pode afetar menos um projeto grande do que se o mesmo fosse todo feito usando acessos diretos.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Como faço para recuperar um objeto que é atributo de um BO ?&lt;/span&gt;&lt;br /&gt;R. Quando um atributo de um BO for na verdade um outro objeto BO,  ao invés de um inteiro simples que contenha o &lt;span style="font-style: italic;"&gt;ObjectID&lt;/span&gt;, recomenda-se manter o objeto e quando na recuperação do AR do banco de dados, instanciar o BO e atribuir sua chave. Quando for acessar algum outro atributo deste BO, então invoca-se o método de carga e ele é completado. Estou estudando uma forma de implementar o padrão &lt;a href="http://en.wikipedia.org/wiki/Lazy_loading"&gt;&lt;span style="font-style: italic;"&gt;lazy-load&lt;/span&gt;&lt;/a&gt;, como no &lt;a href="http://www.hibernate.org/"&gt;&lt;span style="font-style: italic;"&gt;Hibernate&lt;/span&gt; &lt;/a&gt;do Java.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Um &lt;span style="font-style: italic;"&gt;Action&lt;/span&gt; pode acessar diretamente um AR, para fazer gravações simples?&lt;/span&gt;&lt;br /&gt;R. Não. Se começarmos a simplificar nesse ponto, teremos problemas mais tarde. Imagine quando, por exemplo, for necessário dar manutenção em um sistema, onde deverá ser inserido um tratamento de verificação de dados antes de ser gravado; Se os actions acessarem diretamente o AR em questão, será necessário ir de action em action fazendo a manutenção, enquanto que se for centralizado no BO, o ponto de manutenção é um só.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Pode haver um BO que não seja persistido?&lt;/span&gt;&lt;br /&gt;R. Sim. Os BOs que realizam operações de negócio, dentro do escopo do sistema, como a geração de relatórios específicos e cálculos , por exemplo, além daqueles que possuem apenas regras de negócio, funcionando como &lt;span style="font-style: italic;"&gt;helpers&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Quando usar DAO?&lt;/span&gt;&lt;br /&gt;R.  O DAO deve ser usado quando for necessário realizar alguma comunicação de algum componente do sistema com o mundo externo, como a consulta de dados disponíveis em uma página na web, por exemplo. Outros exemplos seriam a leitura ou gravação de arquivos em servidores de FTP, acesso a bancos de dados de terceiros, importação e parsing de arquivos CSV. Se a integração for assíncrona, recomenda-se registrar o serviço em uma instância do PHPCron, por exemplo; já se for necessário realizar o sincronismo no momento das operações de persistência, recomenda-se usar os métodos do DAO a partir dos BOs - nestes casos, cria-se métodos do tipo 'preInserir', 'preAtualizar', 'preExcluir', 'posInserir', etc., e neles coloca-se as chamadas aos métodos dos DAOs correspondentes;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Quando devo usar o BO?&lt;/span&gt;&lt;br /&gt;R. Sempre. Todo &lt;span style="font-style: italic;"&gt;Action &lt;/span&gt;deve reponder com o resultado do processamento do sistema - e neste caso, a ponte é o &lt;span style="font-style: italic;"&gt;Action&lt;/span&gt;, e a "cabeceira" é o BO. A menos em um protótipo visual que apenas simule o funcionamento do sistema, qualquer sistema deverá ter seus BOs implementados. A política de agrupar funcionalidades em um mesmo BO só deve ser usada quando o mesmo é uma entidade abstrata do modelo de domínio.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Quando devo usar o AR?&lt;/span&gt;&lt;br /&gt;R. O AR deve ser usado sempre para mapear uma tabela do banco de dados no sistema. Eventualmente podemos pensar em ARs associados aos DAOs - um DAO pode retornar uma lista de ARs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Quando devo usar o &lt;span style="font-style: italic;"&gt;Action&lt;/span&gt;?&lt;/span&gt;&lt;br /&gt;R. O &lt;span style="font-style: italic;"&gt;Action&lt;/span&gt; é a interface entre o sistema e o mundo real (&lt;span style="font-style: italic;"&gt;frontend&lt;/span&gt;), que disponibiliza um serviço, onde o cliente faz uma solicitação e recebe uma resposta.   Então, sempre que for necessária uma interface com o cliente, esta será um &lt;span style="font-style: italic;"&gt;Action&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Em algumas arquitetura os elementos de persistência (AR) possuem um método bind, onde passo um vetor associativo e o objeto "se vira" para atribuir os valores. Como funcionará na nova arquitetura?&lt;/span&gt;&lt;br /&gt;R. O bind provavelmente será implementado, mas com algumas restrições: já que não estamos mapeando fielmente os campos dos formulários para tabelas, ou mesmo para objetos intermediários (BOs), o método deverá ser sobrecarregado nas classes finais. Assim, um BO terá um método bind que saberá que campos vindos do formulário vão ser atribuídos aos seus atributos; O AR poderá ter a mesma coisa. Embora haja um trabalho um pouco maior, isso dá uma certa segurança haja visto que todos os atributos  que forem aceitos no bind  serão de conhecimento do desenvolvedor.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;P. Na nova arquitetura, o que preciso fazer para criar um novo "serviço" disponibilizado por um dado &lt;/span&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Action&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;?&lt;/span&gt;&lt;br /&gt;R. No construtor do Action em questão, o método deverá ser registrado, para evitar que um hacker subverta o sistema solicitando um método não-registrado. Depois, implemente o método normalmente. Os links que darão acesso ao novo método deverão conter o parâmetro 'acao' com o valor do nome do novo método.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-5904894881123940879?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/5904894881123940879/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=5904894881123940879' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5904894881123940879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5904894881123940879'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/uma-viso-da-nova-arquitetura.html' title='Uma visão da nova arquitetura'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Xn9qMcEj48M/R-LVAnLVU1I/AAAAAAAAAtw/bP_N9yqMykM/s72-c/Modelo+OO.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-7808412516516363260</id><published>2008-03-13T06:16:00.000-07:00</published><updated>2008-03-13T07:11:53.802-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='CASE'/><category scheme='http://www.blogger.com/atom/ns#' term='processos'/><title type='text'>Ferramentas de desenvolvimento rápido... As Concorrentes</title><content type='html'>Na busca pela minimização dos custos com desenvolvedores de software, do tempo de desenvolvimento de soluções contratadas, e na redução dos erros de programação, adotam-se ferramentas de apoio ao desenvolvimento.  Hoje por acaso achei uma de tantas ferramentas que prometem o desenvolvimento rápido de sistemas web, independente de linguagem, 100% visual, independente de banco de dados,  multi-camadas, etc.&lt;br /&gt;&lt;br /&gt;Claro que fui dar uma espiada no dito-cujo, e quem vê se impressiona. Uma ferramenta onde você pode especificar até o layout dos formulários com uma IDE similar ao Delphi. Você chega ao ponto de descrever o fluxo de funcionamento da aplicação com um fluxograma!!! Que maravilha! &lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;- Bom, eu não acho&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Dentre alguns dos pontos que precisam ser observados quando se usa uma ferramenta de apoio ao desenvolvimento, na minha opinião, é a &lt;span style="font-weight: bold;"&gt;manutenção&lt;/span&gt;.  A manutenção é a correção de erros ou evolução da solução de software.&lt;br /&gt;&lt;br /&gt;O que ocorre quando usamos uma ferramenta de geração de código é a simples troca de um editor de texto, onde o desenvolvedor digita seu código, por um conjunto de menus e formulários, que uma vez preenchidos, darão origem a um conjunto de blocos de código. Em vez de o desenvolvedor se especializar na linguagem, se especializará na ferramenta - o que traz alguns riscos, como a dependência e a extrema necessidade de um contrato de suporte.&lt;br /&gt;&lt;br /&gt;Quando criamos um software, (muito) provavelmente teremos que entrar nas suas entranhas e mexer nele. Nem sempre conseguimos atender aos requisitos de negócio com os recursos da IDE, uma vez que precisamos das especificidades das linguagens para criar algoritmos muito específicos (e olha que as vezes temos dificuldades nisso). Como vou fazer isso em uma IDE 100% visual? Aí você pode dizer: "ok, vamos gerar o código e depois mexemos nele". Ótimo, mas daí surgem dois probleminhas:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Quando o código for mexido, o modelo do projeto será sincronizado? Como?&lt;/li&gt;&lt;li&gt;Como é o código gerado? O desenvolvedor conhece a estrutura do mesmo? O desenvolvedor terá que conhecer a linguagem e o padrão, e as vezes, ser um profissional mais qualificado do que um "desenvolvedor normal", que sabe desenvolver o mesmo software "na mão", pois terá que conhecer uma série de recursos e estruturas geradas pela IDE .&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Isso leva a outra questão: se o código for gerado, a linguagem terá que ser especificada - ou seja, deixou de ser independente de linguagem, pois a mesma terá que ser do conhecimento da equipe.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;Outra questão é o processo, que é o fluxo de atividades que, uma vez seguido, guiará o projeto até o produto completo.  A equipe de desenvolvimento terá que se adequar ao processo ditado pela IDE.&lt;br /&gt;&lt;br /&gt;Na minha opinião, a melhor forma de se desenvolver usando uma ferramenta CASE, é estudando e definindo os processos internos, selecionando a linguagem-alvo, e a estrutura de como será gerado, mantido, documentado e sincronizado o código entre o ambiente de desenvolvimento e a ferramenta. A profundidade do uso da ferramenta CASE deve também ser pesada - quanto mais fundo se for nela, mais detalhes de negócio serão descritos e gerados por ela, e isso pode demandar mais tempo do analista, que terá que fazer um fluxograma que pode ser resumido em algumas linhas de código pelo desenvolvedor.&lt;br /&gt;&lt;br /&gt;Muito mais do que focar nas atividades de especificação e codificação, a análise do contexto da empresa, envolvendo o perfil dos profissionais e o processo adotado, pode ser o fator de sucesso para a adoção de uma ferramenta como essa. E quem consegue fazer isso, pode criar sua própria ferramenta, customizada para sua realidade. Mas quem não pode, compra uma CASE, ou usa o notepad.&lt;br /&gt;&lt;br /&gt;Referência: http://www.softwell.com.br/web/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-7808412516516363260?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/7808412516516363260/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=7808412516516363260' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/7808412516516363260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/7808412516516363260'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/ferramentas-de-desenvolvimento-rpido-as.html' title='Ferramentas de desenvolvimento rápido... As Concorrentes'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-3151607574688657548</id><published>2008-03-12T10:33:00.000-07:00</published><updated>2008-03-12T10:57:49.905-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='patterns'/><title type='text'>Patterns</title><content type='html'>Pattern é definido por &lt;span style="font-style: italic;"&gt;Christopher Alexander &lt;/span&gt;como sendo &lt;span style="font-weight: bold;"&gt;a descrição da solução de um problema que ocorre frequentemente em nosso ambiente&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Então, podemos definir patterns apenas observando a repetição de problemas, abstraindo-os e sintetizando padrões de soluções. Embora isso soe meio teórico demais, é o que na prática fazemos, muitas vezes sem pensar. Depois de muito tempo resolvendo problemas similares, é natural que encontremos soluções mais interessantes, seja pela simplificação ou pela adaptação das mesmas prevendo problemas futuros. Assim compreendemos melhor, na prática, o que vem a ser efetivamente patterns.&lt;br /&gt;&lt;br /&gt;Agora, voltando à nossa realidade, cabe a nós identificar os problemas recorrentes e definir estratégias de solução. O mercado está cheio de patterns que atendem alguns casos, mas nem sempre existem soluções prontas.&lt;br /&gt;&lt;br /&gt;Um autor muito interessante é Martin Fowler, que além de trabalhar na área de processos de desenvolvimento, também entra muito nessa área de padrões de projetos de software.&lt;br /&gt;Alguns exemplos muito interessantes que ele traz são:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold; font-style: italic;"&gt;Money&lt;/span&gt;, que representa um valor monetário;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Value Object&lt;/span&gt;, usado para transitar objetos transientes entre camadas de uma aplicação (estilo DTO)&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;Special Case&lt;/span&gt;, que nada mais é do que uma exceção à regra, trabalhada a nível de objeto ao invés de atributo null&lt;/li&gt;&lt;li&gt;etc.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;O uso dos patterns está mais ligado a praticidade pretendida do que a necessidade de engolir o que o mercado (ou o meio acadêmico) diz que é bom. Se pensar no alto custo de se manter um software de grande porte, o interessante é a redução de retrabalho ou mesmo prever situações de manutenção, onde as intervenções sejam as mais rápidas possível. Outro ponto a se considerar é que a manutenção nem sempre será feito pelo mesmo profissional que desenvolveu o software - a documentação na medida certa aliada ao uso de padrões entendidos pelos profissionais envolvidos tanto no desenvolvimento quanto na manutenção são duas estratégias muito importantes em empresas de software.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-weight: bold;"&gt;Referências&lt;/span&gt;&lt;br /&gt;ALEXANDER, Christopher; ISHIKAWA, Sara; SILVERSTEIN, Murray; JACOBSON, Max; FIKSDAHL-KING, Ingrid, and ANGEL, Shlomo. &lt;span style="font-weight: bold;"&gt;A Pattern Language&lt;/span&gt;. Oxford University Press, New York, 1977.&lt;br /&gt;&lt;br /&gt;FOWLER, Martin; &lt;span style="font-weight: bold;"&gt;Patterns of Enterprise Application Architecture&lt;/span&gt;, June 2002&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-3151607574688657548?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/3151607574688657548/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=3151607574688657548' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/3151607574688657548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/3151607574688657548'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/patterns.html' title='Patterns'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-4881313304473647850</id><published>2008-03-12T09:28:00.000-07:00</published><updated>2008-03-12T09:31:21.452-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='orientação a objetos'/><title type='text'>Acessando diretamente Métodos e Constantes de Classes</title><content type='html'>Quando queremos usar um método de uma classe (ou melhor, de um objeto de classe), geralmente o fluxo normal é:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Instancia um objeto de classe;&lt;/li&gt;&lt;li&gt;Invoca o método;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;É uma questão de projeto, o uso ou não de métodos de classe. Os métodos de classe são aqueles que não acessam dados do objeto (não fazem referência ao $this). Isso é especialmente útil a economia de memória e para organização do código.&lt;br /&gt;&lt;br /&gt;Para usar o método de uma classe, basta usar o nome da classe, seguido de :: e o nome do método.&lt;br /&gt;Ex.:&lt;br /&gt;&lt;span style="font-family: courier new;font-size:85%;" &gt;// deve calcular o dígito verificador do parâmetro passado.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;font-size:85%;" &gt;Pessoa::calculaDVCPF('12345') &lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-4881313304473647850?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/4881313304473647850/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=4881313304473647850' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/4881313304473647850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/4881313304473647850'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/acessando-diretamente-mtodos-e.html' title='Acessando diretamente Métodos e Constantes de Classes'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-5636745758859778337</id><published>2008-03-11T20:07:00.000-07:00</published><updated>2008-03-12T05:45:08.314-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='orientação a objetos'/><title type='text'>Interface e "class_implements" -  recursos interessantes</title><content type='html'>Quando queremos fazer um projeto onde não sabemos ao certo que objetos receberemos como parâmetros, podemos 'forçar' a lógica para não permitir que objetos de outras classes que não as que esperamos sejam rejeitadas. Mas algumas vezes isso pode não ser muito produtivo, especialmente se o que esperamos possua comportamentos agregados de várias classes diferentes - como não temos (e nem queremos ter) os recursos de herança múltipla, lançamos mão de um recurso muito interessante: as interfaces.&lt;br /&gt;&lt;br /&gt;Meu primeiro contato com interface foi em Java, e vi que vale muito a pena, especialmente em projetos grandes e/ou quando na construção de frameworks e bibliotecas de suporte.&lt;br /&gt;Enfim, interfaces são como "esqueletos" de classes, com os métodos que devem ser implementados nas classes que as usam. Se eu tenho um método que recebe um objeto com dados de alguma fonte, e penso que pode haver algum erro nestes, posso criar uma interface 'erro_possivel', com o método 'imprimeErro'; Se eu forçar para que todos os objetos que passem para esta minha função implementem esta interface, então quando houver um erro posso ter a certeza de que ele tem este método implementado... mas peraí, como faço isso?&lt;br /&gt;&lt;br /&gt;Na criação da classe que será passada como parâmetro, uso o implements e o nome da interface; será exigido que você implemente os métodos declarados na interface na sua classe. Já no seu método, você terá que usar a função 'class_implements' passando como parâmetro o objeto, que será retornado um array com a lista de interfaces que este implementa - aí você verifica se nesta lista está contido o nome da interface esperada...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-5636745758859778337?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/5636745758859778337/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=5636745758859778337' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5636745758859778337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/5636745758859778337'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/interface-e-classimplements-recursos.html' title='Interface e &quot;class_implements&quot; -  recursos interessantes'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-8931255325475424504</id><published>2008-03-11T19:53:00.001-07:00</published><updated>2008-03-12T08:23:54.926-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='orientação a objetos'/><title type='text'>Carregar arquivos de classes automaticamente...</title><content type='html'>Como costume, separamos as classes em arquivos diferentes, e isso por um lado é bom, pois facilita a organização. Por outro lado, a proliferação de arquivos pode gerar dificuldade na carga das classes necessárias para alguns fins. Este problema ocorre especialmente quando se usa o esquema de instanciação de classes dinâmicas, ou seja, quando criamos objetos de classes especificadas em tempo de execução, como em esquemas de plugins.&lt;br /&gt;&lt;br /&gt;O PHP possui um recurso muito interesante, e pouco explorado, que é a carga automática de arquivos sob demanda. Na prática é a carga de um arquivo quando uma classe não-carregada é instanciada - isso na tentativa de carregar o arquivo que contém a definição da classe em questão. É claro que neste arquivo a dita-cuja não estiver presente, será emitido um erro.&lt;br /&gt;O recurso é o __autoload(). Atenção: lembre-se que os métodos que iniciam com dois underscores são chamadas de 'funções mágicas').&lt;br /&gt;&lt;br /&gt;A __autoload() (bem descrita no &lt;span style="font-size:85%;"&gt;http://br2.php.net/manual/pt_BR/language.oop5.autoload.php&lt;/span&gt;),  é definido pelo usuário e recebe como parâmetro o nome da classe que está sendo instanciada. Dentro desta função, você pode fazer o que for necessário para achar o arquivo. Com isso você tem a liberdade de procurar em vários diretórios o arquivo que bata com o padrão de nome definido.&lt;br /&gt;&lt;br /&gt;Três problemas que vejo no uso do __autoload() são:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Em primeiro lugar, o fato de não explicitar a inclusão do arquivo abre precedentes de risco de segurança, uma vez que alguém pode criar um arquivo no padrão em um diretório que será procurado pelo script antes de onde realmente reside o referido, e com isso comprometer a integridade do sistema.&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Mas isso é difícil de acontecer&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;O segundo motivo é a dificuldade de manter um código que usa uma classe que só-Deus-sabe onde está localizada.&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Para evitar isso, é necessário uma boa organização do código e da localização das classes.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Por fim, o terceiro e mais importante, na minha opinião, é que se for necessário o uso do __autoload() mais de uma vez no mesmo projeto, o interpretador emitirá um erro fatal - ou seja, ele não vai funcionar. Isso pode ocorrer especialmente quando se usa frameworks de apoio de terceiros, onde eles podem ter feito uso do __autoload().&lt;br /&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Para solucionar este problema, foi criada a função 'spl_autoload_register()', que funciona igual ao '__autoload()', só que permite o 'empilhamento' das funções que serão invocadas quando na instanciação de uma classe não-carregada.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;Veja maiores detalhes em &lt;span style="font-size:85%;"&gt;http://br2.php.net/manual/pt_BR/function.spl-autoload-register.php&lt;/span&gt; , e/ou o capítulo 7, seção 7.1 do livro '&lt;span style="font-style: italic;"&gt;PHP5 in Practice&lt;/span&gt;'&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-8931255325475424504?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/8931255325475424504/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=8931255325475424504' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8931255325475424504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/8931255325475424504'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/carregar-arquivos-de-classes.html' title='Carregar arquivos de classes automaticamente...'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-93641205317788930</id><published>2008-03-11T19:31:00.000-07:00</published><updated>2008-03-11T20:12:45.362-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='global'/><category scheme='http://www.blogger.com/atom/ns#' term='orientação a objetos'/><title type='text'>Globals... nunca mais!!!</title><content type='html'>Até pouco tempo atrás eu usava de vez em quando a famigerada palavra-chave 'global' do PHP, dentro das funções que precisavam acessar alguma variável externa... Isso em um primeiro momento parece não ter problemas e, pelo contrário, parece ainda simplificar muito a vida do desenvolvedor.&lt;br /&gt;&lt;br /&gt;Ledo engano...&lt;br /&gt;&lt;br /&gt;Em primeiro lugar, o uso de variáveis globais gera um sério problema: quando eu alterar seu conteúdo, quem será afetado? Quem alterou o conteúdo de tal variável? Estas são algumas perguntinhas que podem ocorrer a quem estiver mantendo um sistema em PHP.&lt;br /&gt;Além de gerar dificuldades de manutenção, o código fica poluído e confuso - quem for dar manutenção no sistema pode se perder.&lt;br /&gt;&lt;br /&gt;Ok, mas então como podemos dar uma solução para esse problema?&lt;br /&gt;Vou aqui citar dois casos típicos, que devem servir de base para a grande maioria das situações:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. A variável que está fora da minha função, está dentro do escopo do meu script.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Entendamos da seguinte forma: várias funções desta página acessam diretamente uma determinada variável, declarando-a como global.&lt;br /&gt;Se for possível, crie uma classe com esta (e outras) variáveis ditas globais, e junte com os métodos que as acessam. Se usar o PHP5, torne as variáveis private, e se possível, encapsule-as, criando seus getters e setters. Assim você mantém a integridade das variáveis garantindo que apenas os métodos desta classe podem alterar seus valores.&lt;br /&gt;Se não for usar a classe, pelo passe a variável como parâmetro na função - não esqueça de que se você deseja alterar seu conteúdo de dentro da função, então passe por referência ao invés de passar por valor (use o caractere '&amp;amp;').&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. A variável está fora do escopo da minha aplicação, mas dentro de um arquivo importado.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Este caso é mais complexo, pois pode ser que não se tenha acesso direto ao código onde está a tal variável global, e não se possa alterá-lo. Assim, a idéia da classe permanece, com a diferença de que um atributo interno seja na verdade, uma referência à dita-cuja. Faça o atributo normalmente na classe, e em seu setter passe a variável 'global' por referência - assim, de dentro da classe você estará acessando indiretamente a tal variável.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-93641205317788930?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/93641205317788930/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=93641205317788930' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/93641205317788930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/93641205317788930'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/globals-nunca-mais.html' title='Globals... nunca mais!!!'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-2837442816216916821</id><published>2008-03-11T19:27:00.001-07:00</published><updated>2008-03-11T19:27:51.687-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='array'/><title type='text'>Ordenando arrays com comparações definidas pelo usuário</title><content type='html'>Geralmente usamos as funções típicas de ordenação do PHP, como o sort(), usort() e ksort(). Isso é natural, considerando que na maioria dos casos estas funções atendem plenamente. Entretanto, quando temos um array mais complexo, onde sua ordenação exige mais do que estas funções fazem, precisamos de outra saída. Aqui entram as funções de ordenação "parametrizáveis". São elas: usort(), uasort() e uksort().&lt;br /&gt;&lt;br /&gt;Para a referência e exemplos de uso, a melhor fonte que encontrei foi o manual do PHP (http://br2.php.net/manual/pt_BR/function.usort.php).&lt;br /&gt;&lt;br /&gt;Note que a diferença fundamental do uasort() para o uksort() é que enquanto este classifica as chaves (claro que alterando junto seus valores), aquele apenas classifica os valores, deixando as chaves inalteradas.&lt;br /&gt;&lt;br /&gt;Um exemplo prático do uso destas funções é quando queremos classificar uma tabela sem usar os recursos do banco de dados, se a lógica de classificação for complexa, podemos pegar a tabela em um array multidimensional e usar as funções para gerar um array ordenado;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-2837442816216916821?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/2837442816216916821/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=2837442816216916821' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2837442816216916821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/2837442816216916821'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/ordenando-arrays-com-comparaes.html' title='Ordenando arrays com comparações definidas pelo usuário'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-153433167067168453</id><published>2008-03-11T05:31:00.000-07:00</published><updated>2008-03-11T05:54:35.843-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='desenvolvimento'/><category scheme='http://www.blogger.com/atom/ns#' term='gerência de projetos'/><category scheme='http://www.blogger.com/atom/ns#' term='processos'/><title type='text'>Desenvolvendo em camadas</title><content type='html'>Desde a faculdade ouvi falar nas tais 3-camadas e em como elas ajudariam no desenvolvimento de sistemas, sejam eles escritos em Java, Delphi, PHP, ou qualquer outra. Depois de quebrar a cabeça tentando entender, me foram apresentados os tais Design Patterns  do GoF , do Martin Fowler, e de tantos outros... Enfim, piorou tudo quando vi a lista de "camadas" adotadas no J2EE. Era tudo muito estranho - eu não conseguia ver aplicação naquilo tudo.&lt;br /&gt;&lt;br /&gt;Quando comecei efetivamente a trabalhar com projeto e implementação orientados a objetos, percebi que algumas coisas podiam ser bem aproveitadas. Debulhei uma série de artigos e projetos desenvolvidos em cima de frameworks orientados a objetos, e consegui assimilar  algumas coisas interessantes:&lt;br /&gt;&lt;br /&gt;As minhas principais motivações no uso de divisão em camadas são:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Aumento na manutenibilidade&lt;/span&gt; - se o código for bem projetado, as manutenções corretivas e evolutivas tendem a ser mais ágeis e menos confusas.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Especialização &lt;/span&gt;-  posso definir um especialista para fazer o trabalho em uma camada, aumentando a produtividade local (naquela camada)&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Diminuição da dependência entre as camadas&lt;/span&gt; - posso criar uma camada em PHP, a outra em Java e outra em qualquer SGBD.&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Desacoplamento &lt;/span&gt;- Quanto menos acoplados forem os componentes melhor, uma vez que as amarras entre estes podem dificultar as manutenções.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;É evidente que isso traz um contraponto, a saber:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;É exigido mais da equipe de projeto -  a análise e projeto são mais exigidas, e a formalização dos artefatos produzidos é maior. Na prática isso demanda um pouco mais de trabalho.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ferramental e processo - é necessário dar o devido suporte ao projeto, usando ferramentas de apoio; além disso, um processo é desejável, pois aumenta-se o volume de esforço acumulado, e é bom ter um passo-a-passo.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Comunicação - É um fator essencial: a comunicação entre todos os envolvidos dos projetos;&lt;/li&gt;&lt;li&gt;Gerência - diferente dos projetos individuais ad-hoc, projetos com a divisão de camadas geralmente exigem um certo grau de gerência para manter as partes coesas.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-153433167067168453?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/153433167067168453/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=153433167067168453' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/153433167067168453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/153433167067168453'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/desenvolvendo-em-camadas.html' title='Desenvolvendo em camadas'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4030446995309883641.post-6248903101066196611</id><published>2008-03-11T05:16:00.000-07:00</published><updated>2008-03-11T05:29:11.396-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='snipet'/><category scheme='http://www.blogger.com/atom/ns#' term='solução'/><category scheme='http://www.blogger.com/atom/ns#' term='trim'/><title type='text'>Removendo espaços do PHP</title><content type='html'>Lendo o primeiro capítulo do livro &lt;span style="font-weight: bold;"&gt;PHP 5 in Practice&lt;/span&gt;, de Elliot White III, vi uma seção interessante de ser postada.&lt;br /&gt;&lt;br /&gt;As vezes queremos eliminar espaços em branco das nossas strings, e frequentemente usamos a função &lt;span style="font-style: italic;"&gt;trim()&lt;/span&gt; . Só que as vezes queremos eliminar espaços &lt;span style="font-weight: bold;"&gt;dentro&lt;/span&gt; das strings, e quebramos a cabeça para fazer. Usando expressões regulares é fácil. Veja o exemplo a seguir:&lt;br /&gt;&lt;pre style="color: rgb(0, 0, 102);"&gt;&lt;?php&lt;br /&gt;$str = " This line  contains\tliberal \r\n use of   whitespace.\n\n";&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;// First remove the leading/trailing whitespace&lt;/span&gt;&lt;br /&gt;$str = trim($str);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;// Now remove any doubled-up whitespace&lt;/span&gt;&lt;br /&gt;$str = preg_replace('/\s(?=\s)/', '', $str);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;// Finally, replace any non-space whitespace, with a space&lt;/span&gt;&lt;br /&gt;$str = preg_replace('/[\n\r\t]/', ' ', $str);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 102, 102);"&gt;// Echo out: 'This line contains liberal use of whitespace.'&lt;/span&gt;&lt;br /&gt;echo "&lt;pre&gt;{$str}&lt;/pre&gt;";&lt;br /&gt;&lt;br /&gt;?&gt;&lt;/pre&gt;O exemplo acima funciona da seguinte forma:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Primeiro usa o trim() para limpar os espaços do início e do final da string. &lt;/li&gt;&lt;li&gt;Depois usa o preg_replace() para remover os espaços duplicados.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;O caracter de escape \s significa "qualquer espaço em branco".&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;A notação (?=) é usada para realizar pesquisa adiante. Na prática ele significa "qualquer espaço que é seguido por outro espaço". Isso remove os duplicados, deixando apenas um espaço em branco.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Finalmente, usamos outra expressão regular [\n\r\t] para encontrar as quebras de linha (\n), "retornos de carro" (\r) ou tabulações (\t), e substituímos tudo isso por um espaço em branco.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Extraído da seção 1.2.1 do livro  &lt;span style="font-weight: bold;"&gt;PHP 5 in Practice &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4030446995309883641-6248903101066196611?l=php-eduluz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-eduluz.blogspot.com/feeds/6248903101066196611/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4030446995309883641&amp;postID=6248903101066196611' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/6248903101066196611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4030446995309883641/posts/default/6248903101066196611'/><link rel='alternate' type='text/html' href='http://php-eduluz.blogspot.com/2008/03/removendo-espaos-do-php.html' title='Removendo espaços do PHP'/><author><name>Eduardo</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
