345 votes

Comment décoder les entités HTML à l'aide de jQuery ?

Comment utiliser jQuery pour décoder les entités HTML dans une chaîne de caractères ?

0 votes

Le choix prématuré de la technologie (jQuery) invite à répondre à des questions de sécurité. Il serait peut-être préférable de fermer cette question en tant que doublon de stackoverflow.com/questions/1912501/ .

448voto

tom Points 3246

Note de sécurité : l'utilisation de cette réponse (conservée dans sa forme originale ci-dessous) peut introduire une Vulnérabilité XSS dans votre application. Vous ne devez pas utiliser cette réponse. Lire la réponse de lucascaro pour une explication des vulnérabilités dans cette réponse, et utiliser l'approche de cette réponse ou La réponse de Mark Amery à la place.

En fait, essayez

var encodedStr = "This is fun & stuff";
var decoded = $("<div/>").html(encodedStr).text();
console.log(decoded);

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div/>

178 votes

Faites no faire ça avec des entrées non fiables. De nombreux navigateurs chargent les images et déclenchent les événements associés même si le nœud n'est pas attaché au DOM. Essayez d'exécuter $("<div/>").html('<img src="http://www.google.com/images/logos/ps_logo2.png" onload=alert(1337)>') . Dans Firefox ou Safari, l'alerte est déclenchée.

0 votes

@Mike, que recommandez-vous à la place ? Votre réponse de .replace() n'est pas bonne si vous ne savez pas ce que vous remplacez...

7 votes

@ekkis, vous devez enlever les balises avant d'essayer de décoder les entités. str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/g, "") ou quelque chose de similaire.

227voto

lucascaro Points 317

Sans aucun 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 le réponse acceptée mais peut être utilisé en toute sécurité avec des entrées utilisateur non fiables.


Questions de sécurité dans des approches similaires

Comme noté par Mike Samuel en faisant cela avec un <div> au lieu d'un <textarea> avec une entrée utilisateur non fiable est une vulnérabilité XSS, même si la <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)">')

Cependant, cette attaque n'est pas possible contre un <textarea> parce qu'il n'y a pas d'éléments HTML dont le contenu est autorisé dans un fichier de type <textarea> . Par conséquent, toutes les balises HTML encore présentes dans la chaîne "encodée" seront automatiquement codées en entités 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)">'))

Avertissement : Faire cela en utilisant la méthode de jQuery .html() y .val() au lieu d'utiliser les méthodes .innerHTML y .value est également peu sûr* pour certaines versions de jQuery, même en utilisant un textarea . En effet, les anciennes versions de jQuery seraient évaluer délibérément et explicitement les scripts. contenue dans la chaîne de caractères passée à .html() . Ainsi, un 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 à <a href="https://stackoverflow.com/users/2377920/eru-penkman">Eru Penkman </a>pour avoir détecté cette vulnérabilité.

6 votes

Il peut être judicieux de détruire le textarea après avoir extrait sa valeur : decodedString = textArea.value; textArea.remove(); return decodedString;

2 votes

Ou seulement si la version de javascript supporte effectivement remove() : if ('remove' in Element.prototype) textArea.remove();

6 votes

@Werner Dès que la fonction est sortie, il n'y aura plus de variables contenant une référence à celle-ci, elle sera donc automatiquement supprimée par la fonction éboueur .

80voto

Alan Hamlett Points 1041

Comme l'a dit Mike Samuel, n'utilisez pas jQuery.html().text() pour décoder les entités html car ce n'est pas sûr.

Au lieu de cela, utilisez un modèle de rendu comme Mustache.js o decodeEntities du commentaire de @VyvIT.

Underscore.js La bibliothèque utility-belt est livrée avec escape y unescape mais elles ne sont pas sûres pour les entrées utilisateur :

_.escape(string)

_.unescape(string)

2 votes

Cela mérite en fait beaucoup plus de votes positifs ! C'est la solution que je préfère. Ils ont inclus unescape dans les docs maintenant, btw.

0 votes

Merci, j'ai mis à jour ma réponse avec un lien direct vers les nouvelles docs.

5 votes

_.unescape("&#39;") donne juste "'" au lieu d'un guillemet simple. Y a-t-il quelque chose qui m'échappe ou le trait de soulignement ne s'échappe pas vers les codes d'entité HTML comme indiqué sur la page : w3schools.com/tags/ref_entities.asp

28voto

Canavar Points 29161

Je pense que vous confondez les méthodes texte et HTML. Regardez cet exemple, si vous utilisez le HTML interne d'un élément comme texte, vous obtiendrez des balises HTML décodées (deuxième bouton). Mais si vous les utilisez en tant que HTML, vous obtiendrez la vue formatée en HTML (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 HTML contenu.

Le deuxième bouton écrit : voici un contenu <B>HTML</B>.

Au fait, vous pouvez voir un plug-in que j'ai trouvé en Plugin jQuery - Décodage et encodage HTML qui encode et décode les chaînes HTML.

26voto

Rondo Points 462

La question est limitée par "avec jQuery" mais cela pourrait aider certains de savoir que le code jQuery donné dans la meilleure réponse ici fait ce qui suit en dessous... cela fonctionne avec ou sans jQuery :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X