Kodowanie HTML utracone podczas odczytu atrybutu z pola wejściowego

Używam JavaScript, aby wyciągnąć wartość z ukrytego pola i wyświetlić ją w polu tekstowym. Wartość w ukrytym polu jest zakodowana.

Na przykład,

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

Zostaje wciągnięta do

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

Przez jQuery, aby uzyskać wartość z ukrytego pola (w tym momencie tracę kodowanie):

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

Problem polega na tym, że gdy czytam chalk &amp; cheese z ukrytego pola, JavaScript zdaje się tracić kodowanie. Aby uciec " i ', chcę aby kodowanie / align = "left" /

Czy istnieje biblioteka JavaScript lub metoda jQuery, która koduje łańcuch znaków w HTML?

Author: nothingisnecessary, 2009-08-03

22 answers

Używam tych funkcji:

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

Zasadniczo element div jest tworzony w pamięci, ale nigdy nie jest dołączany do dokumentu.

W funkcji htmlEncode ustawiam innerText elementu i pobieram zakodowane innerHTML; w funkcji htmlDecode ustawiam innerHTML wartość elementu i pobierany jest innerText.

Sprawdź działający przykład tutaj .

 1036
Author: CMS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-17 16:19:50

Sztuczka jQuery nie koduje cudzysłowów i w IE usuwa białe znaki.

Bazując na templatetagu escape w Django, który chyba jest już mocno używany/testowany, stworzyłem tę funkcję, która robi to, co jest potrzebne.

Jest prawdopodobnie prostszy (i być może szybszy) niż obejście problemu usuwania białych znaków - i koduje znaki cudzysłowu, co jest niezbędne, jeśli masz zamiar użyć wyniku wewnątrz wartości atrybutu przykład.

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

Aktualizacja 2013-06-17:
W poszukiwaniu najszybszej ucieczki znalazłem tę implementację metody replaceAll:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(również tutaj: najszybsza Metoda zastąpienia wszystkich wystąpień znaku w łańcuchu )
Niektóre wyniki wydajności tutaj:
http://jsperf.com/htmlencoderegex/25

Daje identyczny ciąg wynikowy do wbudowanych replace łańcuchów powyżej. Byłbym bardzo szczęśliwy, gdyby ktoś mógł wyjaśnić, dlaczego jest szybciej!?

Aktualizacja 2015-03-04:
Właśnie zauważyłem, że AngularJS używają dokładnie tej metody above:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Dodają kilka udoskonaleń - wydają się obsługiwać niejasny problem z Unicode, a także konwertować wszystkie Nie alfanumeryczne znaki na encje. Miałem wrażenie, że ten ostatni jest nie jest to konieczne, o ile dla dokumentu podano kod UTF8.

Zauważę, że (4 lata później) Django nadal nie robi żadnej z tych rzeczy, więc nie jestem pewien, jak ważne są one:
https://github.com/django/django/blob/1.8b1/django/utils/html.py#L44

Aktualizacja 2016-04-06:
Możesz również chcieć uciec przed forward-slash /. Nie jest to wymagane do poprawnego kodowania HTML, jednak jest to zalecane przez OWASP jako środek bezpieczeństwa anty-XSS. (dzięki @JNF za zasugerowanie tego w komentarzach)

        .replace(/\//g, '&#x2F;');
 532
Author: Anentropic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:59

Oto wersja nie-jQuery, która jest znacznie szybsza zarówno od wersji jQuery .html(), jak i wersji .replace(). Zachowuje wszystkie białe znaki, ale podobnie jak wersja jQuery, nie obsługuje cudzysłowów.

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

Prędkość: http://jsperf.com/htmlencoderegex/17

test prędkości

Demo: jsFiddle

Wyjście:

wyjście

Scenariusz:

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>
 76
Author: ThinkingStiff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-11 21:06:34

Wiem, że to stara, ale chciałem zamieścić odmianę zaakceptowanej odpowiedzi , która będzie działać w IE bez usuwania linii:

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
Author: boca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:59

Underscore zapewnia _.escape() oraz _.unescape() metody, które to robią.

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

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"
 28
Author: TJ VanToll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-10 15:04:59

Dobra odpowiedź. Zauważ, że jeśli wartość do zakodowania to undefined lub null w jQuery 1.4.2 mogą wystąpić błędy takie jak:

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

Lub

Uncaught TypeError: Object has no method 'html'

Rozwiązaniem jest zmodyfikowanie funkcji, aby sprawdzić rzeczywistą wartość:

function htmlEncode(value){ 
    if (value) {
        return jQuery('<div/>').text(value).html(); 
    } else {
        return '';
    }
}
 12
Author: leepowers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-02 22:40:13

Dla tych, którzy preferują zwykły javascript, oto metoda, której z powodzeniem użyłem:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}
 9
Author: backtestbroker.com,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-12 21:13:14

Prototype {[3] } ma wbudowaną klasę String . Więc jeśli używasz/planujesz użyć Prototype, robi to coś w stylu:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"
 5
Author: Sinan Taifour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-02 21:17:14

FWIW, kodowanie nie jest tracone. Kodowanie jest używane przez parser znaczników (przeglądarkę) podczas ładowania strony. Gdy źródło zostanie odczytane i przeanalizowane, a przeglądarka załaduje DOM do pamięci, kodowanie zostanie przetworzone na to, co reprezentuje. Więc do czasu, gdy twój JS jest wykonywany, aby odczytać cokolwiek w pamięci, znak, który otrzymuje, jest tym, co reprezentuje kodowanie.

Może i zajmuję się semantyką, ale chciałem, żebyś zrozumiał cel kodowania. Słowo "zagubiony" brzmi, jakby coś nie działało tak, jak powinno.

 5
Author: JAAulde,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-24 12:13:28

Szybciej bez Jquery. Możesz zakodować każdy znak w łańcuchu:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}
W przeciwieństwie do innych gier, w których nie można grać, nie można grać na gitarze.]}

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
Author: Dave Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-26 14:16:45

Oto proste rozwiązanie javascript. Rozszerza obiekt String za pomocą metody "HTMLEncode", która może być użyta na obiekcie bez parametru lub z parametrem.

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

Zrobiłemgist "metoda HTMLEncode dla javascript".

 4
Author: Netsi1964,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-12 06:33:47

Nie powinno być konieczności kodowania wartości w celu przeniesienia ich z jednego pola wejściowego do drugiego.

<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 nie wstawia surowego HTML ' a ani niczego innego; po prostu mówi domowi, aby ustawił właściwość value (lub atrybut; nie jest pewien). Tak czy inaczej, DOM zajmuje się wszystkimi problemami z kodowaniem. Jeśli nie robisz czegoś dziwnego, jak użycie document.write lub eval, kodowanie HTML będzie skutecznie przezroczyste.

Jeśli mówisz o wygenerowaniu nowego pola tekstowego, aby trzymać result...it " s nadal tak łatwo. Wystarczy przekazać statyczną część HTML do jQuery, a następnie ustawić resztę właściwości / atrybutów obiektu, który do ciebie zwraca.

$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());
 2
Author: cHao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-17 16:09:32

Miałem podobny problem i rozwiązałem go za pomocą funkcji encodeURIComponent z JavaScript (documentation )

Na przykład, w Twoim przypadku, jeśli używasz:

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

I

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

Dostaniesz chalk%20%26%20cheese. Utrzymywane są nawet przestrzenie.

W moim przypadku musiałem zakodować jeden Ukośnik i ten kod działa idealnie

encodeURIComponent('name/surname')

I mam name%2Fsurname

 2
Author: Dmyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-05 23:00:30

Na podstawie dezynfekcji kątowej ... (składnia modułu 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};
 2
Author: Tracker1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-19 23:01:12

Afaik nie ma żadnych prostych metod kodowania/dekodowania HTML w javascript.

Możesz jednak użyć JS do utworzenia dowolnego elementu, ustawić jego wewnętrzny tekst, a następnie odczytać go za pomocą innerHTML.

Powiedzmy, że z jQuery powinno działać:

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

Albo coś w tym stylu

 1
Author: Ken Egozi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-17 11:20:19

Jeśli chcesz użyć jQuery. Znalazłem to:

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

(część jquery.wtyczka typu string oferowana przez jQuery SDK)

Problem z Prototype moim zdaniem polega na tym, że rozszerza obiekty bazowe w JavaScript i będzie niezgodny z dowolnym jQuery, którego możesz użyć. Oczywiście, jeśli używasz już Prototype, a nie jQuery, nie będzie to problemem.

EDIT: jest też to, czyli port prototypów string utilities for jQuery:

Http://stilldesigning.com/dotstring/

 1
Author: Sam Saint-Pettersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-25 20:35:11
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
    };
})();

To jest z kodu źródłowego ExtJS.

 1
Author: WaiKit Kung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-02 10:42:02
<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>

Wyświetli: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

.htmlEncode() będzie dostępne dla wszystkich ciągów znaków po zdefiniowaniu.

 1
Author: Stuart Eske,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-03 14:11:39

HtmlEncodes the given value

  var htmlEncodeContainer = $('<div />');
  function htmlEncode(value) {
    if (value) {
      return htmlEncodeContainer.text(value).html();
    } else {
      return '';
    }
  }
 1
Author: Sky Yip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-20 03:04:53

Napotkałem pewne problemy z ukośnikiem wstecznym w ciągu mojej domeny\użytkownika.

Dodałem to do innych odpowiedzi Anentropic

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

Które znalazłem tutaj: Jak uniknąć ukośnika w JavaScript?

 1
Author: spacebread,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:42

Oto mały fragment, który emuluje funkcję Server.HTMLEncode z ASP Microsoftu, napisaną w czystym JavaScript:

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

Wynik nie koduje apostrofów, ale koduje inne znaki HTML i dowolne znaki spoza zakresu 0x20 - 0x7E.

 1
Author: ReWrite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 17:40:21

Wybieranie co escapeHTML() robi w prototypie.js

Dodanie tego skryptu pomaga w ucieczce:

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

Teraz możesz wywołać metodę escapeHTML na ciągach znaków w Twoim skrypcie, jak:

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

Mam nadzieję, że pomoże każdemu, kto szuka prostego rozwiązania bez konieczności dołączania całego prototypu.js

 0
Author: new_user,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-22 13:20:10