it-swarm.com.de

Unescape HTML Entities in Javascript?

Ich habe einen Javascript-Code, der mit einem XML-RPC-Backend kommuniziert .. Die XML-RPC gibt Zeichenfolgen des Formulars zurück:

<img src='myimage.jpg'>

Wenn ich jedoch die Zeichenfolgen in HTML stelle, werden sie wörtlich gerendert. Ich sehe kein Bild, ich sehe die Zeichenfolge buchstäblich:

<img src='myimage.jpg'>

Ich vermute, dass der HTML-Code über den XML-RPC-Kanal entkommen ist.

Wie kann ich die Zeichenfolge in Javascript aufheben? Ich habe die Techniken auf dieser Seite erfolglos ausprobiert: http://paulschreiber.com/blog/2008/09/20/javascript-how-to-unescape-html-entities/

Wie kann das Problem auf andere Weise diagnostiziert werden?

118
Joseph Turian

Ich verwende die folgende Methode:

function htmlDecode(input){
  var e = document.createElement('div');
  e.innerHTML = input;
  // handle case of empty input
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}

htmlDecode("&lt;img src='myimage.jpg'&gt;"); 
// returns "<img src='myimage.jpg'>"

Grundsätzlich erstelle ich ein DOM-Element programmgesteuert, weise den codierten HTML-Code seiner innerHTML zu und rufe den nodeValue aus dem Textknoten ab, der mit der innerHTML-Einfügung erstellt wurde. Da es nur ein Element erstellt, es aber niemals hinzufügt, wird kein Website-HTML-Code geändert.

Es funktioniert cross-browser (einschließlich älterer Browser) und akzeptiert alle HTML Character Entities .

BEARBEITEN: Die alte Version dieses Codes funktionierte auf IE nicht mit leeren Eingaben, wie gezeigt hier auf jsFiddle (Ansicht im IE). Die obige Version funktioniert mit allen Eingängen.

UPDATE: Anscheinend funktioniert das nicht mit großer Zeichenfolge und es wird auch eine Sicherheitsanfälligkeit eingeführt, siehe Kommentare.

155
CMS

Die meisten Antworten, die hier gegeben werden, haben einen großen Nachteil: Wenn die Zeichenfolge, die Sie konvertieren möchten, nicht als vertrauenswürdig eingestuft wird, erhalten Sie am Ende eine Cross-Site Scripting (XSS) -Lücke . Beachten Sie für die Funktion in der akzeptierten Antwort Folgendes:

htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");

Die Zeichenfolge enthält hier ein nicht umschriebenes HTML-Tag, sodass die htmlDecode-Funktion nicht dekodiert, sondern den in der Zeichenfolge angegebenen JavaScript-Code ausführt.

Dies kann durch die Verwendung von DOMParser vermieden werden, das in allen modernen Browsern unterstützt wird :

function htmlDecode(input)
{
  var doc = new DOMParser().parseFromString(input, "text/html");
  return doc.documentElement.textContent;
}

// This returns "<img src='myimage.jpg'>"
htmlDecode("&lt;img src='myimage.jpg'&gt;");

// This returns ""
htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");

Diese Funktion führt garantiert keinen JavaScript-Code als Nebeneffekt aus. Alle HTML-Tags werden ignoriert, nur Textinhalt wird zurückgegeben.

Hinweis zur Kompatibilität: Das Analysieren von HTML mit DOMParser erfordert mindestens Chrome 30, Firefox 12, Opera 17, Internet Explorer 10, Safari 7.1 oder Microsoft Edge. Alle Browser ohne Support sind also weit über ihre EOL hinaus und ab 2017 können nur noch ältere Versionen von Internet Explorer und Safari (in der Regel noch unzählig genug) gesehen werden.

235
Wladimir Palant

Wenn Sie jQuery verwenden:

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

Andernfalls verwenden Sie Strictly Software's Encoder Object , das über eine hervorragende htmlDecode()-Funktion verfügt.

39
Chris Fulstow

Der Trick besteht darin, die Stärke des Browsers zu verwenden, um die speziellen HTML-Zeichen zu decodieren, der Browser darf jedoch die Ergebnisse nicht so ausführen, als wäre er HTML. Diese Funktion verwendet einen regulären Ausdruck, um codierte HTML-Zeichen (ein Zeichen) zu identifizieren und zu ersetzen zu einer Zeit.

function unescapeHtml(html) {
    var el = document.createElement('div');
    return html.replace(/\&[#0-9a-z]+;/gi, function (enc) {
        el.innerHTML = enc;
        return el.innerText
    });
}
6
Ben White

Die Antwort von CMS funktioniert einwandfrei, es sei denn, der HTML-Code, den Sie dekomprimieren möchten, ist sehr lang und länger als 65536 Zeichen. In Chrome wird der innere HTML-Code dann in viele untergeordnete Knoten aufgeteilt, von denen jeder höchstens 65536 lang ist, und Sie müssen diese verketten. Diese Funktion funktioniert auch für sehr lange Zeichenfolgen:

function unencodeHtmlContent(escapedHtml) {
  var elem = document.createElement('div');
  elem.innerHTML = escapedHtml;
  var result = '';
  // Chrome splits innerHTML into many child nodes, each one at most 65536.
  // Whereas FF creates just one single huge child node.
  for (var i = 0; i < elem.childNodes.length; ++i) {
    result = result + elem.childNodes[i].nodeValue;
  }
  return result;
}

In dieser Antwort zu innerHTML max Länge finden Sie weitere Informationen: https://stackoverflow.com/a/27545633/694469

5
KajMagnus

Chris Antwort ist schön und elegant, aber es schlägt fehl, wenn der Wert undefined ist. Nur eine einfache Verbesserung macht es solide:

function htmlDecode(value) {
   return (typeof value === 'undefined') ? '' : $('<div/>').html(value).text();
}
4
nerijus

Keine direkte Antwort auf Ihre Frage, aber wäre es nicht besser für Ihren RPC, eine Struktur (sei es XML oder JSON oder was auch immer) mit diesen Bilddaten (in Ihrem Beispiel URLs) in dieser Struktur zurückzugeben? 

Dann könnten Sie es einfach in Ihrem Javascript analysieren und den <img> mit Javascript selbst erstellen.

Die Struktur, die Sie von RPC erhalten, könnte folgendermaßen aussehen:

{"img" : ["myimage.jpg", "myimage2.jpg"]}

Ich denke, es ist besser so, da das Einfügen eines Codes aus externen Quellen in Ihre Seite nicht sehr sicher aussieht. Stellen Sie sich vor, wie jemand Ihr XML-RPC-Skript entführt und dort etwas eingefügt hat, was Sie nicht möchten (sogar etwas Javascript ...). 

3
kender

Gern geschehen ... nur ein Bote ... das volle Verdienst geht an ourcodeworld.com, Link unten.

window.htmlentities = {
        /**
         * Converts a string to its html characters completely.
         *
         * @param {String} str String with unescaped HTML characters
         **/
        encode : function(str) {
            var buf = [];

            for (var i=str.length-1;i>=0;i--) {
                buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
            }

            return buf.join('');
        },
        /**
         * Converts an html characterSet into its original character.
         *
         * @param {String} str htmlSet entities
         **/
        decode : function(str) {
            return str.replace(/&#(\d+);/g, function(match, dec) {
                return String.fromCharCode(dec);
            });
        }
    };

Volle Gutschrift: https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript

2
indospace.io

Das ist ein besseres:

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

benutzen:

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

von: HTML Entity Decode

1

Alle anderen Antworten hier haben Probleme.

Die document.createElement ('div') -Methoden (einschließlich der Methoden, die jQuery verwenden) führen alle an sie übergebenen Javascript aus (ein Sicherheitsrisiko), und die DOMParser.parseFromString () - Methode trimmt Whitespace. Hier ist eine reine Javascript-Lösung, die kein Problem hat:

function htmlDecode(html) {
    var textarea = document.createElement("textarea");
    html= html.replace(/\r/g, String.fromCharCode(0xe000)); // Replace "\r" with reserved unicode character.
    textarea.innerHTML = html;
    var result = textarea.value;
    return result.replace(new RegExp(String.fromCharCode(0xe000), 'g'), '\r');
}

TextArea wird speziell verwendet, um die Ausführung von js-Code zu vermeiden. Es passiert diese:

htmlDecode('&lt;&amp;&nbsp;&gt;'); // returns "<& >" with non-breaking space.
htmlDecode('  '); // returns "  "
htmlDecode('<img src="dummy" onerror="alert(\'xss\')">'); // Does not execute alert()
htmlDecode('\r\n') // returns "\r\n", doesn't lose the \r like other solutions.
0
Dwayne

Ich verwende dies in meinem Projekt: Inspiriert von anderen Antworten aber mit einem zusätzlichen sicheren Parameter kann es nützlich sein, wenn Sie mit dekorierten Zeichen umgehen

var decodeEntities=(function(){

    var el=document.createElement('div');
    return function(str, safeEscape){

        if(str && typeof str === 'string'){

            str=str.replace(/\</g, '&lt;');

            el.innerHTML=str;
            if(el.innerText){

                str=el.innerText;
                el.innerText='';
            }
            else if(el.textContent){

                str=el.textContent;
                el.textContent='';
            }

            if(safeEscape)
                str=str.replace(/\</g, '&lt;');
        }
        return str;
    }
})();

Und es ist verwendbar wie:

var label='safe <b> character &eacute;ntity</b>';
var safehtml='<div title="'+decodeEntities(label)+'">'+decodeEntities(label, true)+'</div>';
0
tmx976