wake-up-neo.com

HTML-Codierung verloren, wenn Attribut aus Eingabefeld gelesen wird

Ich verwende JavaScript, um einen Wert aus einem ausgeblendeten Feld abzurufen und in einem Textfeld anzuzeigen. Der Wert im ausgeblendeten Feld ist codiert.

Zum Beispiel,

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

wird hineingezogen

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

über einige jQuery, um den Wert aus dem ausgeblendeten Feld zu erhalten (an diesem Punkt verliere ich die Kodierung):

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

Das Problem ist, dass, wenn ich chalk &amp; cheese aus dem verborgenen Feld lese, die Kodierung anscheinend verloren geht. Um " und ' zu umgehen, möchte ich, dass die Kodierung erhalten bleibt.

Gibt es eine JavaScript-Bibliothek oder eine jQuery-Methode, die eine Zeichenfolge mit HTML kodiert?

708
AJM

Ich benutze diese Funktionen:

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

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

Grundsätzlich wird ein div-Element im Speicher erstellt, aber niemals an das Dokument angehängt.

Bei der Funktion htmlEncode stelle ich die Variable innerText des Elements ein und rufe die kodierte Variable innerHTML ab. Bei der htmlDecode-Funktion habe ich den innerHTML-Wert des Elements eingestellt und die innerText wird abgerufen.

Überprüfen Sie ein laufendes Beispiel hier .

1050
CMS

Der jQuery-Trick codiert keine Anführungszeichen und in IE wird der Whitespace entfernt.

Basierend auf dem escape -Templatetag in Django, von dem ich denke, dass er bereits stark genutzt/getestet wird, habe ich diese Funktion erstellt, die das tut, was benötigt wird.

Es ist wahrscheinlich einfacher (und möglicherweise auch schneller) als alle Abhilfemaßnahmen für das Problem mit Leerzeichenstrennung - und es codiert Anführungszeichen. Dies ist wichtig, wenn Sie das Ergebnis beispielsweise in einem Attributwert verwenden möchten.

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

Update 2013-06-17:
Bei der Suche nach dem schnellsten Escapeing habe ich diese Implementierung einer replaceAll-Methode gefunden:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(wird auch hier referenziert: schnellste Methode zum Ersetzen aller Instanzen eines Zeichens in einer Zeichenfolge )
Einige Leistungsergebnisse hier:
http://jsperf.com/htmlencoderegex/25

Sie gibt den eingebauten replace-Ketten oben eine identische Ergebniszeichenfolge. Ich würde mich sehr freuen, wenn jemand erklären könnte, warum es schneller geht !?

Update 2015-03-04:
Ich habe gerade bemerkt, dass AngularJS genau die oben genannte Methode verwendet:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Sie fügen ein paar Verfeinerungen hinzu - sie scheinen ein obskures Unicode-Problem zu handhaben und alle nicht-alphanumerischen Zeichen in Entitäten zu konvertieren. Ich hatte den Eindruck, dass letzteres nicht notwendig war, solange Sie einen UTF8-Zeichensatz für Ihr Dokument festgelegt haben.

Ich werde anmerken, dass Django (4 Jahre später) noch immer keine dieser Dinge tut, daher bin ich mir nicht sicher, wie wichtig sie sind:
https://github.com/Django/django/blob/1.8b1/Django/utils/html.py#L44

Update 06.04.2016:
Möglicherweise möchten Sie auch den Schrägstrich / umgehen. Dies ist für die korrekte HTML-Codierung nicht erforderlich. Es handelt sich jedoch um empfohlen von OWASP als Anti-XSS-Sicherheitsmaßnahme. (Danke an @JNF für den Vorschlag in Kommentaren)

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

Hier ist eine Nicht-jQuery-Version, die erheblich schneller ist als die Version jQuery .html() und die Version .replace(). Dadurch werden alle Leerzeichen beibehalten, aber wie bei der jQuery-Version werden keine Anführungszeichen verarbeitet.

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

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

speed test

Demo:  jsFiddle

Ausgabe:

output

Skript:

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>
79
ThinkingStiff

Ich weiß, dass dies eine alte ist, aber ich wollte eine Variation von der akzeptierten Antwort posten, die in IE funktioniert, ohne Zeilen zu entfernen:

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

Underscore bietet _.escape() und _.unescape() Methoden, die dies tun.

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

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

Gute Antwort. Beachten Sie, dass bei einem zu codierenden Wert von undefined oder null mit jQuery 1.4.2 möglicherweise Fehler auftreten, z.

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

OR

Uncaught TypeError: Object has no method 'html'

Die Lösung besteht darin, die Funktion zu ändern, um nach einem tatsächlichen Wert zu suchen:

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

Für diejenigen, die einfaches Javascript bevorzugen, ist hier die Methode, die ich erfolgreich verwendet habe:

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

Prototyp hat die eingebaute String-Klasse . Wenn Sie also Prototype verwenden/planen, wird Folgendes verwendet:

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

FWIW, die Kodierung geht nicht verloren. Die Kodierung wird vom Markup-Parser (Browser) während des Ladens der Seite verwendet. Sobald die Quelle gelesen und analysiert wurde und der Browser das DOM in den Speicher geladen hat, wurde die Kodierung in das, was sie darstellt, analysiert. Wenn Ihr JS ausgeführt wird, um etwas im Speicher zu lesen, ist das Zeichen, das er erhält, das, was die Codierung darstellt.

Ich beschäftige mich hier vielleicht streng mit Semantik, aber ich wollte, dass Sie den Zweck der Kodierung verstehen. Das Wort "verloren" klingt so, als würde etwas nicht so funktionieren, wie es sollte.

5
JAAulde

Schneller ohne Jquery. Sie können jedes Zeichen in Ihrer Zeichenfolge kodieren:

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

Oder zielen Sie einfach auf die Hauptfiguren, um sich über (&, Inbreaks, <,>, "und ') Sorgen zu machen, beispielsweise

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>

5
Dave Brown

Hier ist eine einfache Javascript-Lösung. Es erweitert das String-Objekt um eine Methode "HTMLEncode", die für ein Objekt ohne Parameter oder mit einem Parameter verwendet werden kann.

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

Ich habe eine Gist "HTMLEncode-Methode für Javascript" gemacht.

4
Netsi1964

Basierend auf Anglees sanitize ... (es6-Modulsyntax)

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

Meine pure-JS-Funktion:

/**
 * 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-Entitäten kodieren und dekodieren

2
Nick Tsai

afaik gibt es keine einfachen HTML Encode/Decode-Methoden in Javascript.

Sie können jedoch mithilfe von JS ein beliebiges Element erstellen, den inneren Text festlegen und dann mit innerHTML lesen. 

mit jQuery sollte dies funktionieren:

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

oder etwas in diese Richtung

2
Ken Egozi

Sie sollten keine Werte zwischenspeichern/kodieren müssen, um sie von einem Eingabefeld in ein anderes zu verschieben.

<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 fügt kein rohes HTML oder irgendetwas ein; es teilt dem DOM lediglich mit, die value-Eigenschaft (oder das Attribut; nicht sicher) festzulegen. In beiden Fällen behandelt das DOM alle Codierungsprobleme für Sie. Wenn Sie nichts Ungewöhnliches wie document.write oder eval verwenden, ist die HTML-Codierung effektiv transparent.

Wenn Sie davon sprechen, ein neues Textfeld zu erstellen, um das Ergebnis zu speichern, ist es immer noch so einfach. Übergeben Sie einfach den statischen Teil des HTML-Codes an jQuery, und legen Sie dann den Rest der Eigenschaften/Attribute für das Objekt fest, das er Ihnen zurückgibt.

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

Ich hatte ein ähnliches Problem und löse es mit der Funktion encodeURIComponent von JavaScript ( documentation )

Zum Beispiel in Ihrem Fall, wenn Sie verwenden:

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

und

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

sie erhalten chalk%20%26%20cheese. Sogar Räume werden beibehalten.

In meinem Fall musste ich einen Backslash codieren, und dieser Code funktioniert einwandfrei

encodeURIComponent('name/surname')

und ich habe name%2Fsurname

2
Dmyan

Ich habe Probleme mit dem Backslash in meiner Domain\User-Zeichenfolge.

Ich habe dies zu den anderen Fluchten aus der Antwort von Anentropic hinzugefügt

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

Was ich hier gefunden habe: Wie entgeht man Backslash in JavaScript?

1
spacebread
<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>

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

.htmlEncode () ist für alle definierten Zeichenketten verfügbar.

1
Stuart Eske

HtmlEncode für den angegebenen Wert

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

Hier ein bisschen, dass die Server.HTMLEncode-Funktion aus ASP von Microsoft emuliert wird, die in reinem JavaScript geschrieben ist:

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

Das Ergebnis nicht codiert Apostrophe, sondern codiert die anderen HTML-Specials und alle Zeichen außerhalb des Bereichs 0x20-0x7e.

1
ReWrite

Wenn Sie jQuery verwenden möchten. Ich habe das gefunden:

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

(Teil des Plugins jquery.string, das von jQuery SDK angeboten wird)

Ich glaube, das Problem mit Prototype besteht darin, dass es Basisobjekte in JavaScript erweitert und mit allen verwendeten jQuery-Dateien nicht kompatibel ist. Wenn Sie bereits Prototype und nicht jQuery verwenden, ist dies natürlich kein Problem.

EDIT: Außerdem gibt es hier eine Portierung der String-Dienstprogramme von Prototype für jQuery:

http://stilldesigning.com/dotstring/

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

Dies ist aus dem ExtJS-Quellcode.

1
WaiKit Kung

Mit einigen der anderen Antworten hier habe ich eine Version erstellt, die alle relevanten Zeichen in einem Durchgang ersetzt, unabhängig von der Anzahl der verschiedenen codierten Zeichen (nur ein Aufruf von replace()). Bei größeren Zeichenfolgen wird dies schneller.

Es ist nicht abhängig von der DOM-API oder anderen Bibliotheken.

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

Nachdem Sie das einmal ausgeführt haben, können Sie jetzt anrufen

encodeHTML('<>&"\'')

&lt;&gt;&amp;&quot;&#39; bekommen

0
Hashbrown

Auswählen, was escapeHTML() in prototype.js macht

Das Hinzufügen dieses Skripts hilft Ihnen, HTML zu umgehen:

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

sie können jetzt die escapeHTML-Methode für Zeichenfolgen in Ihrem Skript aufrufen, z.

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

Ich hoffe, es hilft jedem, der nach einer einfachen Lösung sucht, ohne den gesamten prototype.js verwenden zu müssen

0
new_user
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);
0
Israel