Benutzer geben Chat-Nachrichten ein, die mithilfe von Moustache-Vorlagen direkt auf die Seite gerendert werden. Natürlich sollte HTML maskiert werden, um eine HTML-Injection zu verhindern, aber andererseits sollten Links als <a href='...'> gerendert werden.

Es gibt verschiedene Ansätze, mit denen ich versucht habe, {{{ ... }}} zu verwenden, um den nicht entkoppelten HTML-Inhalt zurückzugeben. Dies bedeutet, dass der Link gerendert wird und ich mich darum kümmern muss, dass HTML selbst entweicht. Gibt es eine sichere Möglichkeit, dies zu tun, ohne sich auf eine halbherzige Lösung zu verlassen, die ich selbst schreibe?

jQuery.text() wäre großartig, aber ich denke, es wird das <a> wieder als Text rendern.

Was kann ich hier noch tun?

15
Mahoni 5 Aug. 2015 im 13:11

4 Antworten

Beste Antwort

Wenn Sie keine eigene Escape- oder Parsing-Lösung schreiben möchten, gibt es ein jQuery-Plugin für die Verarbeitung von Links mit dem Namen Linkify. Sie können Nachrichten einfach maskieren und dann clientseitig analysieren.

Beispiel, wie es funktioniert:

var text = "<div>Test<br>Test<br>Test http://stackoverflow.com</div>";
$('div').text(text);

// Before: &lt;div&gt;Test&lt;br&gt;Test&lt;br&gt;Test http://stackoverflow.com&lt;/div&gt;

$('div').linkify();

// After: lt;div&gt;Test&lt;br&gt;Test&lt;br&gt;Test <a href="http://stackoverflow.com" class="linkified" target="_blank">http://stackoverflow.com</a>&lt;/div&gt;
10
JacobMiki 10 Aug. 2015 im 10:32

Wenn Sie am Ende die Regex-Route gehen, war der folgende Filter und Regex der aggressivste, den ich gefunden habe, um alle Arten von URLs aufzunehmen, die Ihre Benutzer versuchen werden, einzugeben.

Hier ist ein Regexr, um damit herumzuspielen: http://regexr.com/3bjk9

(function () {
    'use strict';

    angular
        .module('core.filters')
        .filter('urlToA', urlToA);

    // --------------------

    function urlToA () {
        return function (string, noClick) {
            var urlPattern = /((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi; // jshint ignore:line

            return string ? string.replace(urlPattern, replace) : string;

            function replace (url) {
                var httpUrl = url.indexOf('http') === -1 ? 'http://' + url : url;

                if (noClick) {
                    return '<a>' + url + '</a>';
                } else {
                    return '<a href="' + httpUrl + '">' + url + '</a>';
                }
            }
        };
    }

})();
0
Deminetix 17 Aug. 2015 im 07:30

Versuchen Sie, zuerst in .text () einzufügen, und verwenden Sie dann regexp, um den Link mit .html () zu rendern. Hier sehen Sie ein Vanille-Beispiel:

var a="see formula a<b>c in http://test.com or https://x.com?p=3";

var hold=document.createElement('div');
hold.textContent=a;

hold.innerHTML=hold.innerHTML.replace(
    /(https?:\/\/[-$A-Za-z0-9%_?&.~+\/=]+)/g,
    '<a href="$1">$1</a>'
);

window.addEventListener('load',function(){
    document.body.appendChild(hold);
});

Für einen genaueren regulären Ausdruck sehen Sie hier

0
Community 23 Mai 2017 im 12:14

Nur eine Idee: Sie könnten Ihre eigene Fluchtfunktion erstellen

escape : function () {
    return function(val, render) {
        var $s = $(val);
        var $elements = $s.find("*").not("a"); //add other white-listed elements seperated by comma 
        for (var i = $elements.length - 1; i >= 0; i--) {
            var e = $elements[i];
            $(e).replaceWith(e.innerHTML);
        }
        return $s.html();
    }
}

Sie können die Funktion über aufrufen

{{#escape}}{{{YOUR_TEXT}}}{{/escape}}

Ich habe das nicht getestet. Diese Lösung benötigt jQuery. Der obige Code basiert auf dieser Lösung: https://stackoverflow.com/a/27764431/1479486

0
Community 23 Mai 2017 im 12:22