Question

I & # 8217; J'utilise JavaScript pour extraire une valeur d'un champ caché et l'afficher dans une zone de texte. La valeur dans le champ caché est codée.

Par exemple,

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

se laisse entraîner dans

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

via un certain jQuery pour obtenir la valeur du champ caché (& # 8217; c’est à ce stade que je perds le codage):

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

Le problème est que, lorsque je lis chalk &amp; cheese dans le champ caché, JavaScript semble perdre l'encodage. Je ne veux pas que la valeur soit chalk & cheese. Je veux que le littéral amp; soit conservé.

Existe-t-il une bibliothèque JavaScript ou une méthode jQuery qui encodera une chaîne au format HTML?

Était-ce utile?

La solution

EDIT: Cette réponse a été publiée il y a longtemps et la fonction htmlDecode a introduit une vulnérabilité XSS. Il a été modifié en changeant l'élément temporaire d'un div à un textarea réduisant les chances XSS. Mais de nos jours, je vous encourage à utiliser l'API DOMParser comme suggéré dans les autres réponses .

J'utilise ces fonctions:

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();
}

En principe, un élément div est créé en mémoire, mais il n'est jamais ajouté au document.

Sur la htmlEncode fonction, je règle le innerText de l'élément et récupère le code innerHTML; sur la <=> fonction, je définis la <=> valeur de l'élément et <=> est récupéré.

Consultez un exemple en cours ici .

Autres conseils

L’astuce de jQuery ne code pas les guillemets et élimine l’espace blanc dans IE.

Sur la base de la balise escape de Django, que je suppose déjà très utilisée / testée, j'ai créé cette fonction, qui fait le nécessaire.

C’est sans doute plus simple (et peut-être plus rapide) que l’une quelconque des solutions de contournement pour le problème de suppression d’espaces - et elle encode les guillemets, ce qui est essentiel si vous voulez utiliser le résultat dans une valeur d’attribut, par exemple.

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, '&');
}

Mise à jour 2013-06-17:
Dans la recherche de la fuite la plus rapide, j'ai trouvé cette implémentation d'une méthode replaceAll:
http://dumpsite.com/forum/index.php?topic=4 .msg29 # msg29
(également référencé ici: Méthode la plus rapide pour remplacer toutes les occurrences d'un caractère dans une chaîne )

Quelques résultats de performance ici:
http://jsperf.com/htmlencoderegex/25

Il donne une chaîne de résultats identique aux chaînes replace intégrées ci-dessus. Je serais très heureux si quelqu'un pouvait expliquer pourquoi c'est plus rapide!?

Mise à jour 2015-03-04:
Je viens de remarquer que AngularJS utilise exactement la méthode ci-dessus:
https://github.com/angular /angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Ils ajoutent quelques améliorations - ils semblent gérer un problème obscur Unicode ainsi que la conversion de tous les caractères non alphanumériques en entités. J'avais l'impression que ce dernier n'était pas nécessaire tant que vous avez spécifié un jeu de caractères UTF8 pour votre document.

Je noterai que (4 ans plus tard) Django ne fait toujours aucune de ces choses, alors je ne suis pas sûr de leur importance:
https://github.com/django/django/ blob / 1.8b1 / django / utils / html.py # L44

Mise à jour du 2016-04-06:
Vous pouvez également souhaiter échapper au slash avant /. Ce n'est pas nécessaire pour un encodage HTML correct, mais c'est OWASP en tant que mesure de sécurité anti-XSS. (merci à @JNF d’avoir suggéré cela dans les commentaires)

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

Voici une version non-jQuery considérablement plus rapide que la version jQuery .html() et la version .replace(). Cela préserve tous les espaces, mais comme la version jQuery, il ne gère pas les guillemets.

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

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

  

test de vitesse

Démo:  jsFiddle

Sortie:

sortie

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>

Je sais qu'il s'agit d'un ancien message, mais je souhaitais publier une variante de réponse acceptée , qui fonctionnera dans IE sans supprimer les lignes:

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();
} 

Underscore fournit _.escape() et _.unescape() méthodes.

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

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

Bonne réponse. Notez que si la valeur à coder est undefined ou null avec jQuery 1.4.2, des erreurs telles que:

risquent de se produire.

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

OU

Uncaught TypeError: Object has no method 'html'

La solution consiste à modifier la fonction pour rechercher une valeur réelle:

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

Pour ceux qui préfèrent le javascript, voici la méthode que j'ai utilisée avec succès:

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

FWIW, l'encodage n'est pas perdu. L'encodage est utilisé par l'analyseur de balises (navigateur) lors du chargement de la page. Une fois que la source est lue et analysée et que le DOM a chargé le DOM dans la mémoire, le codage a été analysé dans ce qu’il représente. Donc, au moment où votre JS est exécuté pour lire quelque chose en mémoire, le caractère obtenu correspond à ce que représente le codage.

Je travaille peut-être strictement sur la sémantique, mais je voulais que vous compreniez le but de l’encodage. Le mot & Quot; perdu & Quot; donne l'impression que quelque chose ne fonctionne pas comme il se doit.

Le prototype est intégré au Classe de chaîne . Donc, si vous utilisez / prévoyez d’utiliser Prototype, le résultat sera le suivant:

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

Plus rapide sans Jquery. Vous pouvez encoder chaque caractère de votre chaîne:

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

Ou ciblez simplement les personnages principaux dont vous souhaitez vous soucier (& amp ;, inebreaks, < ;, > ;, & "; et ') comme:

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>

Voici une solution javascript simple. Il étend l'objet String avec une méthode & Quot; HTMLEncode & Quot; qui peut être utilisé sur un objet sans paramètre, ou avec un paramètre.

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("æåøåæå"))

J'ai créé une gist " méthode HTMLEncode pour javascript " .

Basé sur angular's sanitize ... (syntaxe de module es6)

// 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};

Pour autant qu'il n'existe aucune méthode simple d'encodage / décodage HTML en javascript.

Toutefois, vous pouvez utiliser JS pour créer un élément arbitraire, définir son texte interne, puis le lire à l'aide de innerHTML.

Par exemple, avec jQuery cela devrait marcher:

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

ou quelque chose du genre

Vous ne devriez pas avoir à échapper / encoder des valeurs pour les faire passer d'un champ d'entrée à un autre.

<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 ne va pas insérer du code HTML brut ou quoi que ce soit; il indique simplement au DOM de définir la propriété value (ou l'attribut; pas sûr). Dans les deux cas, le DOM gère les problèmes d’encodage pour vous. À moins que vous ne fassiez quelque chose de bizarre comme utiliser document.write ou eval, le codage HTML sera efficacement transparent.

Si vous parlez de générer une nouvelle zone de texte pour conserver le résultat ... c'est toujours aussi facile. Passez simplement la partie statique du code HTML à jQuery, puis définissez le reste des propriétés / attributs sur l'objet qu'il vous renvoie.

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

J'ai eu un problème similaire et je l'ai résolu à l'aide de la fonction encodeURIComponent à partir de JavaScript ( documentation )

Par exemple, dans votre cas, si vous utilisez:

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

et

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

vous obtiendrez chalk%20%26%20cheese. Même les espaces sont conservés.

Dans mon cas, je devais encoder une barre oblique inverse et ce code fonctionnait parfaitement

encodeURIComponent('name/surname')

et je suis name%2Fsurname

Ma fonction pure-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;
}
  

entités HTML JavaScript Encode & amp; Décoder

Si vous souhaitez utiliser jQuery. J'ai trouvé ceci:

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

(partie du plug-in jquery.string proposé par le kit de développement logiciel jQuery)

Le problème avec Prototype, je crois, est qu’il étend les objets de base en JavaScript et sera incompatible avec tout jQuery que vous avez utilisé. Bien sûr, si vous utilisez déjà Prototype et pas jQuery, ce ne sera pas un problème.

EDIT: il y a aussi ceci, qui est un port des utilitaires de chaîne de Prototype pour 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
    };
})();

Ceci provient du code source 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>

affichera: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

.htmlEncode () sera accessible sur toutes les chaînes une fois définies.

HtmlEncodes la valeur donnée

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

J'ai rencontré des problèmes de barre oblique inversée dans la chaîne Domaine \ Utilisateur.

J'ai ajouté cela aux autres échappatoires de la réponse d'Anentropic

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

Ce que j'ai trouvé ici: Comment échapper à la barre oblique inverse en JavaScript?

Voici un petit peu qui émule la Server.HTMLEncode fonction de l’ASP de Microsoft, écrite en JavaScript pur:

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;
}

Le résultat ne code pas , mais code les autres spéciaux HTML et tout caractère en dehors de la plage 0x20-0x7e.

Choisir ce que escapeHTML() fait dans le prototype.js

L'ajout de ce script vous permet d'échapper à HTML:

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

maintenant, vous pouvez appeler la méthode escapeHTML sur les chaînes de votre script, par exemple:

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

J'espère que cela aidera toute personne à la recherche d'une solution simple sans avoir à inclure l'intégralité du prototype.js

En utilisant certaines des autres réponses ici, j’ai créé une version qui remplace tous les caractères pertinents en un seul passage, quel que soit le nombre de caractères codés distincts (un seul appel à replace()), donc ce sera plus rapide pour les grandes chaînes.

Cela ne dépend pas de l'API DOM pour exister ni des autres bibliothèques.

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); };
})();

Après avoir couru cette fois, vous pouvez appeler

encodeHTML('<>&"\'')

Pour obtenir &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);

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top