Substituindo acentos por Entidades HTML no Rails

Hoje (na verdade ontem) passei por um problema até que bastante comum: fui notificado que um dos relatórios que desenvolvi, e que chega via anexo de e-mail ao seu destinatário, estava com problemas de codificação: ao invés de acentos, estavam aparecendo os famosos “caracteres estranhos”.

Fui surpreendido pela afirmação, pois testei de todas as maneiras e procurei me certificar que o arquivo ia chegar em seu destino utilizando a codificação UTF-8, que deveria suportar todos os acentos. Meu chefe, que reportou o problema, ainda complementou, “se eu mudo a codificação do IE para ISO-8859-1, os acentos aparecem corretamente”. Muito estranho.

Ao investigar por mais detalhes, acabei perguntando pelo cliente de e-mail… Outlook foi a resposta. Abri a VM do Windows, configurei o Outlook, e tentei abrir o e-mail com o relatório… Realmente, de alguma maneira, o Outlook “converteu” o arquivo de UTF-8 para ISO-8859-1, porém, não removeu nenhum dos marcadores de codificação do arquivo (como a tag <meta>). Porque ele resolveu converter meu arquivo, é um mistério.

A sugestão que recebi, para resolver o problema, foi emitir o relatório já em ISO-8859-1… Mas não quis me entregar, me recuso a mudar a codificação que a minha ferramenta está utilizando apenas para cobrir o caso Outlook… E se daqui a pouco algum Outlook em outra língua resolve converter pra ainda outra codificação, e estraga tudo de novo?

Minha solução: codificar todos os acentos do formulário como entidades HTML. Assim, “Fábio” vira “F&acute;bio” e todos ficam felizes, o HTML do relatório vira um ANSI puro e quero só ver o Outlook conseguir estragar ele.

Ruby torna a gente extremamente preguiçoso… Uma vez que decidi por esta abordagem, fui atrás de uma biblioteca que fizesse a codificação para mim. Encontrei o HTMLEntities. Instalei a gema, testei, rodou legal. E agora, vou percorrer os templates adicionando coder.encode() em cada chamada? Peraí, estamos no Ruby, deve ter uma maneira mais preguiçosa de fazer.

E tinha mesmo. Pesquisei um pouco, e encontrei a explicação de como funciona a proteção contra XSS do Rails. Com isso, descobri a função que o Rails utiliza para codificar automaticamente qualquer conteúdo que não esteja marcado como html_safe. A implementação padrão codifica apenas o <, > e &. A idéia é substituí-la pela minha própria função, utilizando o HTMLEntities. Como?

Criei um initializer, em config/initializers/htmlentities.rb, com o conteúdo abaixo, e pronto! Tudo funcionando como tem que ser.

module ERB::Util
  @@htmle = HTMLEntities.new
  def self.html_escape(s)
    s = s.to_s
    if s.html_safe?
      s
    else
      @@htmle.encode(s, :named)
    end
  end

  def self.h(s)
    self.html_escape(s)
  end
end

É, amigo, quero ver fazer isso em ASP.NET sem magia negra!

3 comentários em “Substituindo acentos por Entidades HTML no Rails

  1. Ops, errei o post. hehehe
    Em .NET não seria assim?

    Server.HtmlEncode("<a href='#' rel="nofollow">Você não viu que há água no balcão?</a>")

    com resultado…

    &lt;a href='#'&gt;Você não viu que há água no balcão?&lt;/a&gt;

  2. Seria, para um caso… Agora imagina encher uma página de Server.HtmlEncode pra todo lado… Não serve, né?

    O legal da solução que eu montei é que não precisei mudar uma linha de código sequer no controller, nem no model, nem na view… Simplesmente aproveitei o suporte que o Rails já tem de proteção a XSS (ele já converte todo caracter < e > que venha da camada de negócio ou do model em &lt; e &gt;) e estendi para também converter á em &aacute;.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s