Qual é exatamente o problema com eval()?

Para iniciar este post, é preciso deixar algo claro: diferente da minha postura com os polêmicos ponto-e-vírgula, em que sei que sou “promíscuo e relaxado”, eu sou muito reticente quanto ao uso de eval() em javascript. O principal motivo é que eval() me cheira a gambiarra. Mas tenho muita dificuldade em dizer porquê. Na verdade, acho mesmo que é só uma questão de elegância.

Já li muita coisa sobre o assunto, mas nenhum argumento me convenceu. Os dois principais argumentos são performance e segurança. Em minha opinião nem um dos dois argumentos procede.

Performance

Em primeiro lugar, é preciso dizer que o argumento de que JSON tem pior performance raramente é verdade. Há alguns anos, código executado via eval não poderia ser cacheado ou pré-otimizado. Isso não é mais verdade hoje em dia. A V8 (Chrome), a Nitro (Safari) e a SpiderMonkey (Firefox) já trabalham com caching do código passado a eval em diversas circunstâncias. Além disso, pense nas situações em que eval seria útil. Não consigo imaginar uma em que performance seja um problema. Por exemplo, uso eval como um fallback para navegadores que não tem suporte nativo a JSON. Sinceramente, depois de um delay de dois segundos esperando por uma requisição Ajax, não faz absolutamente nenhuma diferença se interpretar esse retorno vai levar dez milissegundos a mais.

Alguém pode dizer que seria melhor nessa situação usar uma biblioteca JSON com validações, como a do Douglas Crockford. Mas isso acrescentaria 17Kb de código em troca de absolutamente nada. Alguém pode então argumentar que o que se ganha usando uma biblioteca dessas não é exatamente nada, mas pelo menos um validador do código antes da execução. Respondo a isso no final.

Segurança

O segundo argumento mais usado contra o uso de eval() é segurança. O fato de executar uma string, gerada dinamicamente, e não código escrito diretamente por você, pode dar calafrios. Puxa, mas não dá para ter a menor ideia do que será executado! Um agressor não poderia usar isso para executar código arbitrário? Isso não abre as portas para ataques XSS ou man-in-the-middle?

Aqui também, ninguém nunca conseguiu me demonstrar um único caso em que isso fosse uma preocupação real. Imagine o caso de uso que citei acima, por exemplo, de fazer parsing de dados JSON vindos via Ajax. Embora o código que vá passar por eval() não esteja no seu javascript, ele efetivamente foi escrito por você, no servidor. Se alguém consegue acesso a sua aplicação server afim de enviar dados maliciosos para suas requisições Ajax, por que ele se daria ao trabalho de fazer isso se ele poderia simplesmente gerar Javascript malicioso ou HTML malicioso? Se alguém teve esse nível de acesso a seu servidor, XSS é a menor de suas preocupações.

Outra variação do argumento da segurança diz que se você usa eval() a partir de uma entrada de dados do usuário, isso sim poderia abrir as portas para a execução de código malicioso. É preciso lembrar aqui que código javascript roda no client. Assim, o fato de eu poder digitar um script malicioso num campo de formulário, por exemplo, não significa nada exceto o fato de que posso “invadir minha própria máquina”.

Claro, se você recebe os dados gerados por esse eval() no servidor sem validá-los, isso pode causar problemas. Mas, nesse caso, o problema não está no eval() mas em sua validação porca no servidor. Se não houvesse eval() no código, a mesma coisa poderia ser feita na Firebug ou no console do Chrome.

Há ainda a preocupação com buscar dados de um servidor externo e executá-los, o que faria com que seu site possa executar código malicioso. Bom, se você inclui javascript em sua página gerado pelo Google Analytics, e pelo Twitter, Facebook, AddThis e outros geradores de widgets, porque não confiaria em executar código dessas mesmas fontes via eval()? Qual é exatamente a diferença?

Em suma, se as fontes de dados para o eval() não são confiáveis, não use-as de jeito nenhum. O problema não está no eval().

Qualidade de código

Um último argumento, menos usado mas em minha opinião mais relevante, tem a ver com a qualidade de código. O principal motivo que me faz evitar o uso de eval() é o fato de, se houver algum erro no código avaliado, será bem mais difícil debugar. O navegador vai acusar o número da linha do eval(). Esse é um forte argumento, mas não para todas as situações. Geralmente eu gero JSON no servidor com uma biblioteca ou módulo bastante confiáveis, tanto em PHP quanto em Python. Quais são sinceramente as chances de meu software falhar porque há um problema na biblioteca padrão de JSON do PHP?

Por isso, eu não costumo trocar um simples eval() pelo uso de uma biblioteca de JSON, por exemplo.

Fazendo errado

Não importa quão útil e boa seja uma ferramenta, sempre há uma infinidade de maneiras erradas de usá-la. Vi esses dias código assim:

eval('document.'+obj).className='selected'

Esse código é muito ruim, demonstrando um desconhecimento básico dos recursos da linguagem. Pode facilmente ser substituído por isso:

document[obj].className='selected'

Entenda que este artigo questionando os argumentos comuns contra o uso de eval() não é uma defesa de seu uso, principalmente de seu uso indiscrimado.

Seu argumento

Perdi alguma coisa? Há algo mais que precise ser dito? Por favor, fique à vontade para deixar seus comentários.

 

 

 

Pequena dica de Python: __missing__

A partir do Python 2.5, ao estender dicionários, você pode dar a suas classes um método __missing_, que será executado toda vez que você tentar acessar um índice inexistente. Veja:

class Counter(dict):
    def __missing__(self, key):
        self[key]=0
        return self[key]

Veja funcionando:

>>> votos=['john','paul','john','john','ringo',
...        'george','paul','ringo','ringo','john',
...        'paul','john','george','paul','paul',
...        'john','paul','john','ringo','paul']
>>> c=Counter()
>>> for v in votos:
...     c[v]+=1
... 
>>> c
{'ringo': 4, 'paul': 7, 'john': 7, 'george': 2}

Site recomendado: Marco Gomes

Além de escalar paredes, construir sites em uma madrugada e ser o Eike Batista da internet, Marco Gomes também escreve em seu blog. E escreve bem. Conteúdo inteligente e interessante para quem gosta de internet.

Além disso, deve ter o dedo dele no blog da boo-box, um excelente exemplo de como um blog de uma empresa pode ser interessante e relevante.

Não, este post não é patrocinado 😉

Alta Performance com WordPress

O que vai acontecer com seu site WordPress se ele receber muitas visitas? Aprenda neste Workshop as técnicas e segredos para manter seu site no ar, mesmo sob intenso tráfego.

Site bom é site rápido

A Amazon fez um trabalho de redução do tempo de carregamento em suas páginas e descobriu que cada décimo de segundo que suas páginas demoram a carregar representa 1% a menos de vendas. Ninguém gosta de sites que demoram a carregar.

Pensando nisso, preparamos este Workshop sobre otimização de performance em websites, focado especialmente em sites WordPress. Veja o programa

Novo local

Redesenhamos os Workshops da Visie. Serão eventos de menor porte, num lugar mais adequado a cursos de tecnologia, e também mais baratos. E esperamos que sejam mais frequentes. O lugar escolhido foi o MyJobSpace, que merece um post a parte.

E o primeiro Workshop que faremos neste novo formato é sobre um tema que acho apaixonante: performance. O Workshop Alta Performance com WordPress vai mostrar a você tudo o que você pode fazer, no servidor, PHP, em seu tema, plugins, HTML, Javascript, CSS e imagens para ter um site muito rápido.

Como temos apenas 34 vagas, é bom você não vacilar. Inscreva-se.

Extraindo o áudio MP3 de um vídeo com ffmpeg

Gosto bastante de alguns videopodcasts, como o Roda e Avisa e o Man in the Arena. Mas o tempo que tenho para ouví-los é quando estou dirigindo. Nesse momento, o fato de serem em vídeo não significam nada. Tê-los em MP3 é muito mais prático para mim, que assim consigo ouví-los no som do carro.

Para baixar os vídeos tenho usado o Easy YouTube Video Downloader. Meu próximo projeto pessoal é automatizar isso de alguma maneira, quem sabe com Miro.

Depois, para extrair apenas o áudio, em MP3, faço:

ffmpeg -i entrada_video.mp4 -vn saida_audio.mp3

Simples e rápido. E fácil de automatizar.

Lendo os logs do nginx com pipes e PHP

Um amigo me perguntou hoje sobre soluções NoSQL. Na conversa que se seguiu, descobri o que ele precisava fazer: precisa publicar um servidor cujas URLs vão simplesmente fazer um redirect para outro site, mas devem guardar as informações do redirect para enviar para o Clicky. É claro que os dados devem ser enviados ao Clicky o mais rápido possível, para que as estatísticas sejam atualizadas e o cliente do meu amigo possa acompanhar as estatísticas em tempo real. Mas o mais importante é que o redirect seja feito rapidamente, e que o serviço aguente tráfego massivo.

Meu amigo pensava em usar nginx com PHP e uma solução de NoSQL. Eu expliquei a ele que era uma ideia mais complicada do que precisava. O ideal, nessa situação, é dividir os problemas. O nginx poderia sozinho cuidar dos redirects, sem PHP, com uma performance impressionante. E ele poderia em seguida fazer algo que lesse o log do próprio nginx e enviasse os dados dados ao Clicky.

Meu amigo programa bem em PHP, então vamos fazer oq ue pudermos nessa linguagem. Veja um exemplo simples de como isso funcionaria: podemos criar um shell script simples que vai simplesmente executar um tail -f no log do nginx e redirecionar a saída para um script PHP.

O comando tail -f é muito interessante. Deixe uma janela de terminal aberta em seu Linux com:

tail -f /var/log/syslog

Você vai ver que o tail, com -f, imprime o final do arquivo mas não sai. Ele fica monitorando o arquivo e quando novas linhas são acrescentadas, ele as envia para a saída padrão (nesse caso, a tela.)

Então nosso shell script, chamado monitor.sh, terá o seguinte conteúdo (troque o caminho do arquivo de log pelo caminho onde ele fica em seu sistema):

tail -f /var/log/nginx/access.log | php monitor.php

Isso vai manter o script rodando, enviando cada nova linha no log para o monitor.php. Cada vez que o nginx processa uma requisição ele envia nova linha para esse arquivo. O monitor.php pode ter algo assim:

<?
$stdin = fopen('php://stdin', 'r');

while($l=trim(fgets($stdin))){
  // Aqui $l contém uma linha do log do nginx.
  // Faça o que quiser com isso. Como exemplo
  // vou só tratar os dados e imprimir.
  $l=split(';',preg_replace('/( |\t)+/',';',$l));
  $l[3]=substr($l[3],1);
  $l[5]=substr($l[5],1);
  if($l[5]=='GET' or $l[5]=='POST')
    echo "$l[0] $l[3] $l[5] $l[6]\n";
}

Por fim, falta deixar isso rodando. O jeito mais simples é deixar uma sessão de screen aberta com o comando. Basta rodar o comando screen, executar o monitor.sh no shell que vai se abrir e sair com CTRL+D. Claro que há jeitos melhores de deixar isso rodando. O ideal é transformar esse script num daemon. Mas a solução com screen é suficiente para iniciar no assunto.

JABÁ: para entender melhor os detalhes e aprender mais truques como esse, vá ao Workshop de Linux para Desenvolvedores.

HTTP API WordPress

Você está desenvolvendo um plugin ou tema para WordPress e precisa fazer uma conexão HTTP? Não use fopen, curl, file_get_contents, etc. Use a HTTP API do WordPress.

A HTTP API é simples de usar, muito bem implementada e tem excelente performance.  E se um dia você precisar hospedar seu site num servidor debaixo de um proxy, não vai precisar reescrever seu código. Ao configurar o proxy no wp-config.php, tudo vai funcionar.

Veja um exemplo do uso da HTTP API:

$content=wp_remote_retrieve_body(
           wp_remote_get('http://visie.com.br/'));

Por que sua estratégia de mobile começa com iOS?

Saiu a notícia hoje: Android ultrapassará Windows e será sistema mais usado do mundo, diz IDC.

Agora veja o gráfico:

Sistemas operacionais mobile navegando na web no Brasil de Fev/2011 a Fev/2012

Apesar disso, continuo recebendo das agências sites para construir que não tem versão mobile ou, quando tem, foi desenhada e deve ser construída para iPhone e iPad.

Cena comum numa reunião entre cliente e agência: todo mundo, de ambos os lados, coloca seu celular sobre a mesa. São todos iPhone. Logo, acho que até inconscientemente, eles deduzem que iPhone é o que importa. Alô pessoal! Vocês estão falando com 8,7% do público! Com um investimento semelhante, mas um pouquinho mais de planejamento, poderiam falar com praticamente todo mundo que está navegando no celular.

Configurando o locale no Ubuntu

É um problema comum ao configurar um novo servidor com Ubuntu, descobrir que não há um locale válido configurado, ou descobrir que o locale padrão não é o que você desejava. Os sintomas comuns de um sistema sem um locale válido são as seguintes mensagens:

locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory

Ou essa outra, bem mais assustadora:

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
   LANGUAGE = (unset),
   LC_ALL = (unset),
   LC_CTYPE = "pt_BR.UTF-8",
   LANG = "en_US.UTF-8"
   are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

Os sintomas de um locale diferente do que você gostaria são mensagens em algum idioma estranho.

Como corrigir? Vou postar aqui, porque esse arquivo fica num local muito inusitado, em minha opinião. Não está em /etc. Edite, como root, o arquivo:

/var/lib/locales/supported.d/local

E coloque os locales que você quer que o sistema suporte. A maioria dos usuários brasileiros vai se dar bem com esse conteúdo:

pt_BR ISO-8859-1
pt_BR.UTF-8 UTF-8

No meu caso, como faço questão de trabalhar exclusivamente com Unicode, eu deixo esse arquivo assim:

pt_BR.UTF-8 UTF-8

Em seguida rode:

sudo dpkg-reconfigure locales

Isso deve resolver o problema.

HTML5 é mais que canvas

Acesse o HTML5 Please. Clique em use e dê uma olhada na lista. Agora clique em use with caution e confira a lista. Viu quanta coisa?

Por que a maioria dos exemplos de site em HTML5 brasileiros, dois anos depois de começarmos a usar esse treco, ainda são um mark-up levemente vitaminado e canvas?

Onde estão nossas aplicações offline? Web sockets? Drag-and-drop? Geolocation? Micro-data? Device orientation? Novos campos de formulário? SVG? History API?

Mas não tem demanda…

Você pode se desculpar por estar usando os mesmos velhos recursos de sempre, dizendo que os clientes da agência ou produtora onde você trabalha não querem os recursos novos, que seu chefe não quer saber dessas coisas, que tem trabalho pra caramba pra simplesmente recortar os layouts que recebe e não quer arrumar sarna pra se coçar…

Você vai mesmo querer passar o resto da vida recortando layouts? O mundo vai mudar, e você vai ser extinto, dinossauro. Se não tem demanda, crie a demanda. Comece a desenvolver projetos pessoais com o que você acha que seus clientes deveriam estar usando. Em seguida, mostre para todo mundo. Você vai ver se a demanda não aparece.

Todo mundo tem celular conectado. Todos os navegadores (até o IE) estão se esforçando para funcionar direito. É um momento mágico. É uma oportunidade que você não quer deixar passar. Um pouquinho de esforço aí, galera.

Site Recomendado: Miguel Cavalcanti

O Miguel parou de blogar, o último post dele tem mais de seis meses. Ele tem publicado exclusivamente o videopodcast Man in the Arena.

O que é excelente. É claro que se o Miguel tivesse tempo para escrever um novo bom post por dia e ainda manter o Man in the Arena funcionando, todos adoraríamos. Mas isso me parece, claramente, pedir demais.

O Man in the Arena é um dos podcasts mais inteligentes e relevantes que eu conheço para quem se interessa por empreendedorismo. Eles estão trabalhando agora na temporada 2012, mas se você não conhecia, por favor, assista desde o primeiro. Vai achar inspirador.

Assalto

Na última quinta-feira, indo para casa, fui assaltado. Havia deixado o Peka e o Hugo em casa, e estávamos eu a Dani no carro. Levaram meu computador, um Mac que eu estava usando para desenvolver um projeto, meu iPad e meu celular. Da Dani levaram computador, celular, documentos e dinheiro.

Passado o susto, fui na quinta à noite mesmo comprar um computador para repor o que haviam levado. É minha ferramenta de trabalho, não posso ficar sem. Comprei um Vaio VPCSB25FB, instalei Xubuntu 11.10, a passei a sexta-feira e o domingo colocando as coisas no lugar nele e num Mac Mini que eu já tinha e vou usar no lugar do que levaram.

Algumas lições:

  1. Criptografe sua pasta pessoal: dormi mais tranquilo sabendo que a minha estava criptografada.
  2. Cloud rulez: meus contatos, agenda e e-mails estão no Google. No dia seguinte, mesmo sem meu celular, consegui conferir meus compromissos e ligar para quem eu precisei. Meus projetos estão todos no Git e os arquivos pessoais todos no Dropbox. Perdi no total uns quatro dias de trabalho, a maior parte desse tempo reconfigurando as coisas.
  3. Tenha seguro: eu não tinha seguro das minhas coisas. Quando procurei, me pareceu muito caro. Quando levaram minhas coisas, comecei a achar o seguro barato.
  4. Tenha backup: tenho uma conta Pro 100 no Dropbox. Custa 20 dólares por mês. É barato.

É isso. Passou o susto. Vamos trabalhar bastante agora, pra pagar as coisas novas.

Update: excelente post do Maudy Pedrão: Instale o PREY no Ubuntu e não perca de vista o seu notebook.