web-dev-qa-db-fra.com

Comment décoder des entités HTML avec jQuery?

Comment utiliser jQuery pour décoder des entités HTML dans une chaîne?

314
EddyR

Note de sécurité: l'utilisation de cette réponse (conservée dans sa forme d'origine ci-dessous) peut introduire un vulnérabilité XSS dans votre application. Vous ne devriez pas utiliser cette réponse. Lisez réponse de lucascaro pour une explication des vulnérabilités de cette réponse et utilisez l'approche tirée de cette réponse ou de réponse de Mark Amery .

En fait, essayez 

var decoded = $("<div/>").html(encodedStr).text();
426
tom

Sans jQuery:

function decodeEntities(encodedString) {
  var textArea = document.createElement('textarea');
  textArea.innerHTML = encodedString;
  return textArea.value;
}

console.log(decodeEntities('1 &amp; 2')); // '1 & 2'

Cela fonctionne de la même manière que réponse acceptée , mais son utilisation est sûre avec une entrée utilisateur non fiable.


Problèmes de sécurité dans des approches similaires

Comme noté par Mike Samuel _, le faire avec un <div> au lieu d'un <textarea> avec une entrée utilisateur non fiable est une vulnérabilité XSS, même si le <div> n'est jamais ajouté au DOM:

function decodeEntities(encodedString) {
  var div = document.createElement('div');
  div.innerHTML = encodedString;
  return div.textContent;
}

// Shows an alert
decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">')

Toutefois, cette attaque n'est pas possible contre un <textarea> car aucun élément HTML n'est autorisé dans le contenu d'un <textarea> . En conséquence, toutes les balises HTML encore présentes dans la chaîne "codée" seront automatiquement codées par entité par le navigateur.

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

// Safe, and returns the correct answer
console.log(decodeEntities('<img src="nonexistent_image" onerror="alert(1337)">'))

Warning: utilisez les méthodes .html() et .val() de jQuery au lieu d'utiliser .innerHTML et .value est également non sécurisé * pour certaines versions de jQuery, même en utilisant textarea. En effet, les anciennes versions de jQuery auraient évaluent délibérément et explicitement les scripts contenues dans la chaîne transmise à .html(). Par conséquent, le code comme celui-ci affiche une alerte dans jQuery 1.8:

//<!-- CDATA
// Shows alert
$("<textarea>")
.html("<script>alert(1337);</script>")
.text();

//-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>

* Merci à Eru Penkman d'avoir attrapé cette vulnérabilité.

187
lucascaro

Comme Mike Samuel l'a dit, n'utilisez pas jQuery.html (). Text () pour décoder les entités HTML car il est dangereux.

Au lieu de cela, utilisez un rendu de modèle tel que Mustache.js ou decodeEntities from @ VyvIT.

Underscore.js utility-belt La bibliothèque est fournie avec les méthodes escape et unescape, mais elles ne sont pas sécurisées pour les entrées utilisateur:

_.escape (string)

_.unescape (chaîne de caractères)

77
Alan Hamlett

Je pense que vous confondez le texte et les méthodes HTML. Regardez cet exemple, si vous utilisez le code HTML interne d'un élément comme texte, vous obtiendrez des balises HTML décodées (second bouton). Mais si vous les utilisez en HTML, vous aurez la vue HTML formatée (premier bouton).

<div id="myDiv">
    here is a <b>HTML</b> content.
</div>
<br />
<input value="Write as HTML" type="button" onclick="javascript:$('#resultDiv').html($('#myDiv').html());" />
&nbsp;&nbsp;
<input value="Write as Text" type="button" onclick="javascript:$('#resultDiv').text($('#myDiv').html());" />
<br /><br />
<div id="resultDiv">
    Results here !
</div>

Le premier bouton écrit: voici un contenu HTML

Le second bouton écrit: voici un contenu <B> HTML </ B>. 

A propos, vous pouvez voir un plug-in que j'ai trouvé dans plugin jQuery - HTML décoder et encoder qui encode et décode les chaînes HTML.

28
Canavar

La question est limitée par 'avec jQuery', mais il peut être utile de savoir que le code jQuery donné dans la meilleure réponse ci-dessous fait ce qui suit ci-dessous ... cela fonctionne avec ou sans jQuery:

function decodeEntities(input) {
  var y = document.createElement('textarea');
  y.innerHTML = input;
  return y.value;
}
26
Rondo

encoder:

$("<textarea/>").html('<a>').html();      // return '&lt;a&gt'

décoder:

$("<textarea/>").html('&lt;a&gt').val()   // return '<a>'
16
user4064396

Vous pouvez utiliser la bibliothèque he _, disponible à partir de https://github.com/mathiasbynens/he

Exemple:

console.log(he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro "));
// Logs "Jörg & Jürgen rocked to & fro"

J'ai contesté l'auteur de la bibliothèque sur la question de savoir s'il y avait une quelconque raison d'utiliser cette bibliothèque dans le code côté client en faveur du hack <textarea> fourni dans autres réponses ici et ailleurs. Il a fourni quelques justifications possibles:

  • Si vous utilisez le fichier node.js, l'utilisation d'une bibliothèque pour le codage/décodage HTML constitue une solution unique qui fonctionne à la fois côté client et côté serveur.

  • Les algorithmes de décodage d'entités de certains navigateurs présentent des bogues ou ne prennent pas en charge certaines références de caractère name . Par exemple, Internet Explorer décodera et restituera correctement les espaces insécables (&nbsp;), mais les signalera sous forme d'espaces ordinaires au lieu d'espaces insécables via la propriété innerText d'un élément DOM, rompant ainsi le hack <textarea> (bien que de manière mineure). En outre, IE 8 et 9 simplement ne prend pas en charge les nouvelles références de caractères nommés ajoutées dans HTML 5. L'auteur de he organise également un test de prise en charge des références de caractères nommés à http://mathias.html5.org/tests/html/named-character-references/ . Dans IE 8, il rapporte plus de mille erreurs.

    Si vous souhaitez vous isoler des bogues de navigateur liés au décodage d'entités et/ou pouvoir gérer l'ensemble des références de caractères nommés, vous ne pouvez pas vous échapper avec le hack <textarea>; vous aurez besoin d'une bibliothèque comme il.

  • Il a simplement l'impression de faire les choses de cette façon, c'est moins hacky.

15
Mark Amery

Utilisation

myString = myString.replace( /\&amp;/g, '&' );

Il est plus facile de le faire côté serveur car, apparemment, JavaScript ne possède pas de bibliothèque native pour la gestion des entités, et je n’en ai trouvé aucune en tête des résultats de recherche pour les divers cadres qui étendent JavaScript. 

Recherchez "entités HTML JavaScript" et vous trouverez peut-être quelques bibliothèques à cette fin, mais elles seront probablement toutes construites autour de la logique ci-dessus - remplacer, entité par entité.

4
Dara

Vous devez créer une fonction personnalisée pour les entités html:

function htmlEntities(str) {
return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g,'&gt;').replace(/"/g, '&quot;');
}
1
Ali

Il me suffisait d'avoir un caractère HTML (⇓) comme valeur pour un bouton HTML. Le code HTML semble bon depuis le début dans le navigateur:

<input type="button" value="Embed & Share  &dArr;" id="share_button" />

J'ajoutais maintenant une bascule qui devrait également afficher le caractère. C'est ma solution

$("#share_button").toggle(
    function(){
        $("#share").slideDown();
        $(this).attr("value", "Embed & Share " + $("<div>").html("&uArr;").text());
    }

Ceci affiche à nouveau dans le bouton. J'espère que cela pourrait aider quelqu'un.

0
philipp

Alternativement, il y a aussi une bibliothèque pour cela.

ici, https://cdnjs.com/libraries/he

npm install he                 //using node.js

<script src="js/he.js"></script>  //or from your javascript directory

L'utilisation est comme suit ... 

//to encode text 
he.encode('© Ande & Nonso® Company LImited 2018');  

//to decode the 
he.decode('&copy; Ande &amp; Nonso&reg; Company Limited 2018');

à votre santé.

0
Andaeiii

Voici encore un problème: La chaîne échappée ne semble pas lisible lorsqu'elle est affectée à la valeur d'entrée

var string = _.escape("<img src=fake onerror=alert('boo!')>");
$('input').val(string);

Exemple: https://jsfiddle.net/kjpdwmqa/3/

0
Lauris Kuznecovs

Étendre une classe de chaîne:

String::decode = ->
  $('<textarea />').html(this).text()

et utiliser comme méthode:

"&lt;img src='myimage.jpg'&gt;".decode()
0
Sergio Belevskij

Essaye ça :

var htmlEntities = "&lt;script&gt;alert('hello');&lt;/script&gt;";
var htmlDecode =$.parseHTML(htmlEntities)[0]['wholeText'];
console.log(htmlDecode);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

parseHTML est une fonction de la bibliothèque Jquery qui retournera un tableau contenant des détails sur la chaîne donnée.

dans certains cas, la chaîne est grande, la fonction séparera donc le contenu en plusieurs index.

et pour obtenir toutes les données d'index, vous devez accéder à n'importe quel index, puis accéder à l'index appelé "wholeText".

J'ai choisi l'index 0 car cela fonctionnera dans tous les cas (petite chaîne ou grande chaîne).

0
Fawaz Al Romy

Pour les utilisateurs d'ExtJS, si vous avez déjà la chaîne codée, par exemple lorsque la valeur renvoyée d'une fonction de bibliothèque est le contenu innerHTML, considérez cette fonction ExtJS:

Ext.util.Format.htmlDecode(innerHtmlContent)
0
Ilan

Supposons que vous ayez en dessous de String.

Nos cabines Deluxe sont chaleureuses et confortables. confortable

var str = $("p").text(); // get the text from <p> tag
$('p').html(str).text();  // Now,decode html entities in your variable i.e 

str et assigner à 

étiquette.

c'est tout.

0
Anirudh Sood