2015-08-05 33 views
15

Użytkownik wprowadza wiadomości czatu, które są renderowane bezpośrednio na stronę przy użyciu szablonów wąsów. Oczywiście, kod HTML powinien zostać zmieniony, aby zapobiec iniekcji HTML, ale znowu linki powinny być renderowane jako <a href='...'>.Ucieczka generowanych przez użytkownika wiadomości czatowych, ale renderowanie łączy

Istnieją różne podejścia Próbowałem użyć {{{ ... }}}, aby zwrócić niezwyciężoną zawartość HTML, co oznacza, że ​​link zostanie wyrenderowany i muszę dbać o ucieczkę HTML. Czy istnieje bezpieczny sposób robienia tego bez polegania na niedopieczonym rozwiązaniu, które sam sobie piszę?

jQuery.text() byłby świetny, ale myślę, że będzie ponownie renderować <a> jako tekst.

Co jeszcze mogę tu zrobić?

+1

Co sądzisz na temat korzystania z różnego rodzaju znaczników dla linków w czacie, takich jak BBCode lub Markdown? Tak to zwykle działa na różnych forach dyskusyjnych, a także tutaj. – JacobMiki

+1

@JacobMiki Ale nie chodzi o ustalenie ogólnej składni przecen, ale tylko o renderowanie linków. Facebook Chat też tego nie potrzebuje. – Mahoni

Odpowiedz

10

Jeśli nie chcesz pisać własnego rozwiązania do przechodzenia lub parsowania, istnieje wtyczka jQuery do obsługi linków o nazwie Linkify. Można po prostu uciec od wiadomości, a następnie przeanalizować je po stronie klienta.

Przykład jak to działa:

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

tylko pomysł: można zbudować własną funkcję ucieczce

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

można wywołać funkcję przez

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

nie testowałem tego. To rozwiązanie wymaga jQuery. Powyższy kod jest oparty na tym rozwiązaniu: https://stackoverflow.com/a/27764431/1479486

0

spróbuj wkładając najpierw w .text(), a następnie użyć wyrażenia regularnego do renderowania związek z .html(). Tutaj można zobaczyć przykład waniliowy:

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

Dla bardziej acurate regexp widać here

+1

[tutaj] (https://mathiasbynens.be/demo/url-regex) możesz zobaczyć więcej alternatyw dla regexp –

0

Jeśli kończy się zejście ROUTE REGEX następujący filtr i regex był najbardziej agresywny i znalezionych dla zbierając wszystkie rodzaje adresów URL, które będą próbować wpisać Twoi użytkownicy.

Herezje regexr się bawić z nim: 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>'; 
       } 
      } 
     }; 
    } 

})();