Pergunta

Eu estou usando JavaScript para puxar um valor a partir de um campo oculto e exibi-lo em uma caixa de texto. O valor no campo oculto é codificada.

Por exemplo,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

fica puxado para dentro

<input type='text' value='chalk &amp; cheese' />

via alguns jQuery para obter o valor do campo oculto (é neste ponto que eu perder a codificação):

$('#hiddenId').attr('value')

O problema é que quando eu li chalk &amp; cheese do campo oculto, JavaScript parece perder a codificação. Eu não quero que o valor a ser chalk & cheese. Eu quero o amp; literal a ser mantida.

Existe uma biblioteca JavaScript ou um método jQuery que vai HTML-codificar uma string?

Foi útil?

Solução

EDIT: Esta resposta foi publicado um tempo atrás, e a função htmlDecode introduziu uma vulnerabilidade de XSS. Foi modificado mudando o elemento temporário a partir de um div para um textarea reduzindo a possibilidade de XSS. Mas hoje em dia, gostaria de encorajá-lo a usar a API DOMParser como sugerido na outra anwswer .


Eu uso essas funções:

function htmlEncode(value){
  // Create a in-memory element, set its inner text (which is automatically encoded)
  // Then grab the encoded contents back out. The element never exists on the DOM.
  return $('<textarea/>').text(value).html();
}

function htmlDecode(value){
  return $('<textarea/>').html(value).text();
}

Basicamente um elemento div é criado na memória, mas nunca é anexado ao documento.

Sobre a função htmlEncode eu definir o innerText do elemento, e recuperar o innerHTML codificado; sobre a função htmlDecode eu definir o valor innerHTML do elemento eo innerText é recuperada.

Verifique um exemplo de execução aqui .

Outras dicas

O truque jQuery não aspas codificar e no IE que irá retirar o seu espaço em branco.

Com base no fuga templatetag em Django, que eu acho que é muito utilizada / já testado, eu fiz essa função que faz o que é necessário.

É sem dúvida mais simples (e possivelmente mais rápido) do que qualquer das soluções alternativas para a questão-stripping espaços em branco - e ele codifica aspas, o que é essencial se você estiver indo para usar o resultado dentro de um valor de atributo, por exemplo

function htmlEscape(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

Atualização 2013/06/17:
Na busca para o mais rápido escapar eu descobri essa implementação de um método replaceAll:
http://dumpsite.com/forum/index.php?topic=4 .msg29 # Msg29
(Também referenciado aqui: método mais rápido para substituir todas as instâncias de um personagem em um string)
Alguns resultados de desempenho aqui:
http://jsperf.com/htmlencoderegex/25

Ela dá corda resultado idêntico às cadeias builtin replace acima. Eu ficaria muito feliz se alguém poderia explicar porque é mais rápido!?

Atualização 2015/03/04:
Eu notei que AngularJS estão usando exatamente o método acima:
https://github.com/angular /angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Eles adicionar um par de refinamentos - eles parecem ser lidar com um obscurecer questão Unicode , bem como a conversão de todos os caracteres não alfanuméricos para entidades. Eu estava sob a impressão de que este não era necessário, desde que você tem um conjunto de caracteres UTF8 especificado para o documento.

Vou notar que (4 anos mais tarde) Django ainda não fazer qualquer uma dessas coisas, então eu não tenho certeza de como eles são importantes:
https://github.com/django/django/ blob / 1.8b1 / django / utils / html.py # L44

Atualização 2016/04/06:
Você também pode querer escapar para a frente-slash /. Isso não é necessário para a codificação HTML correto, no entanto, é recomendado pela OWASP como uma medida de segurança anti-XSS. (graças a @JNF para sugerir este nos comentários)

        .replace(/\//g, '&#x2F;');

Aqui está uma versão não-jQuery que é consideravelmente mais rápido do que a versão .html() jQuery ea versão .replace(). Isso preserva todos os espaços, mas como a versão jQuery, não lida com aspas.

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

Speed: http://jsperf.com/htmlencoderegex/17

teste de velocidade

Demonstração: jsFiddle

Output:

saída

Script:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>

Eu sei que este é um velho, mas eu queria postar uma variação o aceite resposta que irá trabalhar em IE sem remover linhas:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
} 

Sublinhado fornece _.escape() e _.unescape() métodos que fazem isso.

> _.unescape( "chalk &amp; cheese" );
  "chalk & cheese"

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"

Boa resposta. Observe que, se o valor para codificar é undefined ou null com jQuery 1.4.2 que você pode obter erros, tais como:

jQuery("<div/>").text(value).html is not a function

ou

Uncaught TypeError: Object has no method 'html'

A solução é modificar a função para verificar se há um valor real:

function htmlEncode(value){ 
    if (value) {
        return jQuery('<div/>').text(value).html(); 
    } else {
        return '';
    }
}

Para aqueles que preferem javascript simples, aqui é o método que eu tenho usado com sucesso:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

FWIW, a codificação não está sendo perdido. A codificação é utilizado pelo analisador de marcação (navegador) durante o carregamento da página. Uma vez que a fonte é lido e analisado eo navegador tem o DOM carregado na memória, a codificação foi analisado em que ela representa. Então, no momento em que o seu JS é executar para ler qualquer coisa na memória, o caractere que fica é o que a codificação representados.

I pode estar operando estritamente em semântica aqui, mas eu queria que você entendesse o propósito de codificação. A palavra "perdido" faz parecer que algo não está funcionando como deveria.

Prototype tem built-in do classe string . Então, se você estiver usando / plano para usar Prototype, ele faz algo como:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"

Faster sem Jquery. Você pode codificar cada personagem em sua string:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

Ou apenas como alvo os principais personagens que se preocupar (e, inebreaks, <,>, "e ') como:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>

Aqui está uma solução simples javascript. Estende-se objeto String com um método "HTMLEncode" que pode ser usado em um objeto sem parâmetro ou com um parâmetro.

String.prototype.HTMLEncode = function(str) {
  var result = "";
  var str = (arguments.length===1) ? str : this;
  for(var i=0; i<str.length; i++) {
     var chrcode = str.charCodeAt(i);
     result+=(chrcode>128) ? "&#"+chrcode+";" : str.substr(i,1)
   }
   return result;
}
// TEST
console.log("stetaewteaw æø".HTMLEncode());
console.log("stetaewteaw æø".HTMLEncode("æåøåæå"))

Eu fiz um "método HTMLEncode para javascript" essência .

Com base sanitize do angular ... (ES6 módulo de sintaxe)

// ref: https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js
const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
const NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;

const decodeElem = document.createElement('pre');


/**
 * Decodes html encoded text, so that the actual string may
 * be used.
 * @param value
 * @returns {string} decoded text
 */
export function decode(value) {
  if (!value) return '';
  decodeElem.innerHTML = value.replace(/</g, '&lt;');
  return decodeElem.textContent;
}


/**
 * Encodes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} encoded text
 */
export function encode(value) {
  if (value === null || value === undefined) return '';
  return String(value).
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, value => {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, value => {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}

export default {encode,decode};

afaik não há qualquer frente HTML Encode / Decode métodos em javascript.

No entanto, o que você pode fazer, é usar JS para criar um elemento arbitrário, defini-lo é texto interno, em seguida, lê-lo usando innerHTML.

dizer, com jQuery isso deve funcionar:

var helper = $('chalk & cheese').hide().appendTo('body');
var htmled = helper.html();
helper.remove();

ou algo nesse sentido

Você não deve ter para escapar valores / codificar, a fim de shuttle-los de um campo de entrada para outro.

<form>
 <input id="button" type="button" value="Click me">
 <input type="hidden" id="hiddenId" name="hiddenId" value="I like cheese">
 <input type="text" id="output" name="output">
</form>
<script>
    $(document).ready(function(e) {
        $('#button').click(function(e) {
            $('#output').val($('#hiddenId').val());
        });
    });
</script>

JS não vai inserindo HTML puro ou qualquer coisa; ele apenas diz o DOM para definir a propriedade value (ou atributo; não tenho certeza). De qualquer maneira, o DOM lida com quaisquer problemas de codificação para você. A menos que você está fazendo algo estranho como o uso de document.write ou eval, HTML-codificação será efetivamente transparente.

Se você está falando sobre a geração de uma nova caixa de texto para armazenar o resultado ... é ainda tão fácil. Basta passar a parte estática do HTML para jQuery, em seguida, definir o resto das propriedades / atributos no objeto que retorna a você.

$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());

Eu tive um problema semelhante e resolvê-lo usando o encodeURIComponent função de JavaScript ( documentação )

Por exemplo, no seu caso, se você usar:

<input id='hiddenId' type='hidden' value='chalk & cheese' />

e

encodeURIComponent($('#hiddenId').attr('value'))

Você receberá chalk%20%26%20cheese. espaços até mesmo são mantidos.

No meu caso, eu tive que codifica uma barra invertida e este código funciona perfeitamente

encodeURIComponent('name/surname')

e eu tenho name%2Fsurname

A minha função puro-JS:

/**
 * HTML entities encode
 *
 * @param {string} str Input text
 * @return {string} Filtered text
 */
function htmlencode (str){

  var div = document.createElement('div');
  div.appendChild(document.createTextNode(str));
  return div.innerHTML;
}

JavaScript HTML Entities Encode & Decode

Se você quiser usar jQuery. Eu encontrei esta:

http://www.jquerysdk.com/api/jQuery.htmlspecialchars

(parte do jquery.string plug-in oferecido pelo jQuery SDK)

O problema com Prototype eu acredito é que ela se estende objetos base em JavaScript e será incompatível com qualquer jQuery você pode ter usado. Claro, se você já está usando o protótipo e não jQuery, não vai ser um problema.

EDIT: Também não é este, que é um porto de utilitários de cordas de protótipo para jQuery:

http://stilldesigning.com/dotstring/

var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.push(echar);
            entityKeys.push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

Esta é a partir do código fonte ExtJS.

<script>
String.prototype.htmlEncode = function () {
    return String(this)
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');

}

var aString = '<script>alert("I hack your site")</script>';
console.log(aString.htmlEncode());
</script>

saída: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

.htmlEncode () estarão acessíveis em todas as cordas, uma vez definido.

HtmlEncodes o valor dado

  var htmlEncodeContainer = $('<div />');
  function htmlEncode(value) {
    if (value) {
      return htmlEncodeContainer.text(value).html();
    } else {
      return '';
    }
  }

Eu tive alguns problemas com a barra invertida na minha corda usuário Domain \.

Eu adicionei isso para os outros escapes de Anentropic resposta

.replace(/\\/g, '&#92;')

O que eu encontrei aqui: Como escapar barra invertida em JavaScript?

Aqui está um pouco que emula a função Server.HTMLEncode da ASP da Microsoft, escrito em JavaScript puro:

function htmlEncode(s) {
  var ntable = {
    "&": "amp",
    "<": "lt",
    ">": "gt",
    "\"": "quot"
  };
  s = s.replace(/[&<>"]/g, function(ch) {
    return "&" + ntable[ch] + ";";
  })
  s = s.replace(/[^ -\x7e]/g, function(ch) {
    return "&#" + ch.charCodeAt(0).toString() + ";";
  });
  return s;
}

O resultado não apóstrofos codificar, mas codifica as outras especialidades HTML e qualquer caractere fora do intervalo 0x20-0x7e.

Escolher o que escapeHTML() está fazendo nos prototype.js

Adicionando este script ajuda a escapeHTML:

String.prototype.escapeHTML = function() { 
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
}

Agora você pode chamar o método escapeHTML em cordas em seu script, como:

var escapedString = "<h1>this is HTML</h1>".escapeHTML();
// gives: "&lt;h1&gt;this is HTML&lt;/h1&gt;"

Hope isso ajuda quem procura uma solução simples sem ter que incluir os prototype.js inteiras

Usando algumas das outras respostas aqui eu fiz uma versão que substitui todos os caracteres pertinentes em um único passe, independentemente do número de caracteres codificados distintas (apenas uma chamada para replace()) assim será mais rápido para cordas maiores.

Não contar com a API DOM de existir ou de outras bibliotecas.

window.encodeHTML = (function() {
    function escapeRegex(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    }
    var encodings = {
        '&'  : '&amp;',
        '"'  : '&quot;',
        '\'' : '&#39;',
        '<'  : '&lt;',
        '>'  : '&gt;',
        '\\' : '&#x2F;'
    };
    function encode(what) { return encodings[what]; };
    var specialChars = new RegExp('[' +
        escapeRegex(Object.keys(encodings).join('')) +
    ']', 'g');

    return function(text) { return text.replace(specialChars, encode); };
})();

Tendo correu que uma vez, agora você pode chamar

encodeHTML('<>&"\'')

Para obter &lt;&gt;&amp;&quot;&#39;

function encodeHTML(str) {
    return document.createElement("a").appendChild( 
        document.createTextNode(str)).parentNode.innerHTML;
};

function decodeHTML(str) {
    var element = document.createElement("a"); 
    element.innerHTML = str;
    return element.textContent;
};
var str = "<"
var enc = encodeHTML(str);
var dec = decodeHTML(enc);
console.log("str: " + str, "\nenc: " + enc, "\ndec: " + dec);

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top