Codificador e decodificador de entidades HTML
Faça escape de texto para que seja seguro dentro de HTML, ou decodifique entidades nomeadas e numéricas de volta aos caracteres que representam.
A saída aparecerá aqui
O que esta ferramenta faz
O HTML não tem como distinguir um sinal de menor que você queria como texto de um que abre uma etiqueta. A linguagem resolve isso com entidades: sequências de escape curtas que representam um caractere sem serem lidas como marcação. Esta ferramenta converte nos dois sentidos — texto simples para a sua forma com escape, e HTML com escape de volta para os caracteres que representa.
Ambos os sentidos rodam inteiramente no seu navegador. Aqui isso importa mais do que na maioria das ferramentas, porque o texto que se cola num decodificador de entidades costuma ser uma página recolhida por um scraper, o email de um cliente ou uma coluna de banco de dados que alguém está tentando perceber.
Os cinco caracteres que importam
Existem milhares de entidades, mas bastam poucas para tornar o texto seguro. A codificação aqui substitui exatamente cinco caracteres e deixa legível tudo o resto:
- O e comercial passa a & — este primeiro, ou cada substituição seguinte seria relida como uma entidade.
- O sinal de menor passa a < — o caractere capaz de abrir uma etiqueta.
- O sinal de maior passa a > — menos perigoso sozinho, com escape por simetria e para sobreviver a analisadores descuidados.
- As aspas duplas passam a " — necessárias dentro de valores de atributo escritos com aspas duplas.
- O apóstrofo passa a ' — necessário dentro de valores de atributo escritos com aspas simples.
Este último é escrito numericamente de propósito. Existe um nome, ', mas vem do XML e o HTML 4 nunca o definiu, por isso analisadores antigos deixam-no passar como texto literal e o escape falha em silêncio. A forma numérica sempre funcionou em todo lugar, e é por isso que as bibliotecas de escape sérias a emitem.
Nomeadas, decimais e hexadecimais
Qualquer caractere pode ser escrito de três maneiras, e a decodificação aceita todas. O travessão é um bom exemplo:
named — a forma legível, mas só para caracteres que têm nome decimal — o ponto de código na base 10 hex — o mesmo ponto de código na base 16, a notação das tabelas Unicode
Ao decodificar, esta ferramenta reconhece 255 nomes: todos os que o HTML 4 define, mais três que ele não define — ', que vem do XML, e Zcaron e zcaron, os dois caracteres do Windows-1252 que o HTML 4 deixou sem nome. Juntos, eles cobrem as letras do Latin-1, o alfabeto grego, as setas, os símbolos matemáticos e a pontuação tipográfica, praticamente tudo o que aparece em texto real. O HTML 5 define cerca de 2100 nomes no total, e os demais são quase todos símbolos matemáticos pouco frequentes; carregar essa tabela acrescentaria dezenas de kilobytes a cada carregamento de página em troca de nomes que a maioria dos documentos nunca usa. Um nome fora do conjunto é comunicado em vez de descartado, portanto o custo é um aviso, nunca uma resposta errada.
A codificação segue o caminho inverso e mantém-se deliberadamente simples: nomes para os cinco caracteres acima, números decimais para todo o resto. Nada se transforma em … nem em ’ quando o próprio caractere é perfeitamente válido num documento UTF-8.
Fazer escape não é uma regra mas quatro
É tentador tratar o escape de entidades como a resposta à injeção, e dentro do conteúdo de um elemento é mesmo. Mas o HTML são na verdade quatro linguagens encaixadas umas nas outras, cada uma com as suas regras. O escape de entidades está certo nos dois primeiros destes lugares e é inútil nos restantes:
- Conteúdo de elemento — texto entre etiquetas. O escape de entidades é exatamente o indicado.
- Valores de atributo entre aspas. O escape de entidades serve, desde que o atributo esteja mesmo entre aspas; sem elas, um espaço no valor termina o atributo e o escape não lhe traz nada.
- Dentro de um bloco script. Aplicam-se as regras de escape de cadeias de JavaScript, não as entidades — o navegador não decodifica entidades aí, por isso uma aspa com escape chega como os caracteres literais ".
- Atributos de URL como href e src. O escape de entidades não trava um URL javascript:, porque o perigo está no esquema e não em qualquer caractere que uma entidade fosse substituir.
A regra prática: faça escape no ponto onde o texto é inserido num documento, com as regras do contexto exato em que aterra — e não uma só vez, cedo, na esperança de que sirva em todo lugar mais à frente.
Por que às vezes se vê &amp;
Esta é de longe a razão mais comum para recorrer a um decodificador de entidades. O texto sofreu escape e depois sofreu escape outra vez — normalmente uma pelo código da aplicação e outra por um motor de modelos ou framework que já faz escape da sua saída:
original Fish & Chips escaped Fish & Chips escaped x2 Fish &amp; Chips
A segunda linha aparece na página como o original. A terceira aparece como a segunda, ou seja, o visitante vê a entidade em vez do caractere. A decodificação remove exatamente uma camada, por isso uma única passagem diz a você em que caso está. Se a saída ainda contiver entidades, havia mais do que uma camada. A correção quase nunca é remover entidades na altura de mostrar: é encontrar e eliminar o passo de escape duplicado, porque a mesma falha está corrompendo em silêncio os dados armazenados.
O não-ASCII e a opção para isso
Uma página servida em UTF-8 não precisa de entidades para letras acentuadas, hebraico, árabe, chinês ou emoji. Esses caracteres são válidos tal como estão, e deixá-los legíveis mantém o código-fonte legível e o arquivo menor. É o padrão aqui.
A opção existe porque alguns destinos ainda insistem em ASCII puro: modelos de e-mail antigos, sistemas que estragam bytes acima de 127, ou uma coluna de banco de dados cuja codificação ninguém quer mudar. Ativá-la escreve um caractere desses como referência decimal sempre que essa referência for lida de volta como esse mesmo caractere — é passa a é, א passa a א. Onde nenhuma referência faria isso de forma confiável, o caractere fica exatamente como está em vez de ser trocado por uma que significa outra coisa: os números de 128 a 159, que o HTML ou lê como os caracteres do Windows-1252 descritos abaixo ou sinaliza como erro, nunca como os caracteres de controle que eles nomeiam, e uma metade solta de um par que sobrou de um texto que já chegou quebrado, à qual nenhuma referência dá nome.
Os emoji merecem uma nota. Um emoji é escrito como uma única referência para todo o seu ponto de código, por exemplo 🙂, nunca como duas metades. Se já usou a ferramenta de escape JSON, isto é o oposto do que acontece lá, onde o formato exige expressamente dividir um emoji em dois escapes \u. O mesmo caractere, duas respostas corretas, porque os dois formatos definem o escape sobre unidades diferentes.
Quando uma referência não pode ser decodificada
Aqui a decodificação nunca falha e nunca apaga nada. Uma referência que não se consegue resolver fica exatamente como foi encontrada e é listada acima da saída com a sua linha e a sua coluna. São comunicadas três coisas:
- Um nome desconhecido, como &nbps; — quase sempre uma gralha de . É o aviso sobre o qual vale a pena agir: significa que falta um espaço no seu conteúdo e ninguém reparou.
- Um número que não é um caractere, como � ou um valor acima do intervalo Unicode. Não há nada para o decodificar, por isso fica como texto.
- Um número entre 128 e 159. Ver abaixo.
Um e comercial isolado não é comunicado de forma alguma. Em HTML, R&D e Q&A são texto comum, e tratar cada e comercial perdido como um erro enterraria os avisos importantes sob o ruído da prosa.
O intervalo de 128 a 159 é uma verdadeira esquisitice. Esses números designam caracteres de controle invisíveis que ninguém alguma vez quer escrever; aparecem porque o documento foi redigido em Windows-1252, onde os mesmos números são aspas curvas, travessões e o símbolo do euro. Os navegadores leem-nos discretamente como Windows-1252 exatamente por isso, e esta ferramenta faz o mesmo para que o resultado corresponda ao que uma página mostraria de fato — mas o diz nos avisos, porque uma substituição silenciosa que não pediu é pior do que uma barulhenta.
Perguntas frequentes
- Fazer escape destes cinco caracteres basta para travar o XSS?
- No conteúdo de um elemento e em valores de atributo entre aspas, sim: é precisamente para isso que serve. Não basta dentro de um bloco script ou style, num atributo sem aspas, nem num atributo de URL como href, cada um dos quais precisa das suas próprias regras. O escape é uma propriedade do lugar onde o texto aterra, não do texto.
- Por que o apóstrofo é codificado como ' e não como '?
- Porque ' é uma entidade XML que o HTML 4 nunca definiu. Os analisadores anteriores ao HTML 5 deixam-na como texto literal, por isso um apóstrofo que julgava protegido não está. A forma numérica funciona em qualquer analisador, e por isso é a opção segura.
- A minha página mostra &amp; em vez de um e comercial. O que aconteceu?
- O texto sofreu escape duas vezes. Decodifique-o aqui: uma passagem transforma &amp; em &, confirmando a camada a mais. Corrija o processo em vez do texto — normalmente o seu código faz escape de uma saída que o motor de modelos já estava protegendo.
- Preciso de codificar hebraico, árabe ou emoji?
- Não numa página moderna servida em UTF-8; são válidos tal como estão. Ative a opção não-ASCII apenas quando algo mais à frente exigir ASCII puro, como um modelo de e-mail antigo. Cada emoji é então escrito como uma única referência numérica.
- Por que a ferramenta avisa sobre “ se o decodificou bem?
- Porque 147 designa um caractere de controle invisível, não a aspa que vê. Os documentos que o usam foram escritos em Windows-1252, onde 147 é uma aspa curva: os navegadores leem-no assim, e esta ferramenta também. O aviso diz a você que houve uma substituição, para que possa corrigir a codificação de origem se estiver ao seu alcance.
- O meu texto é enviado para um servidor?
- Não. A codificação e a decodificação rodam inteiramente no seu navegador; nada do que colar sai do seu dispositivo.
Ferramentas relacionadas
- Gerador de Data URI
Transforme um arquivo ou texto num data: URI e leia um de volta.
- Base64
Codifica e decodifica Base64 — suporte completo a UTF-8.
- Codificador / decodificador de URL
Codificação percentual de um valor ou de um URL inteiro, e ao contrário.
- Escape / unescape de strings JSON
Faça escape de texto para uma string JSON, ou leia uma com escape.