Подтвердить что ты не робот

Как избежать кавычек в значениях атрибутов HTML?

Я создаю строку для вставки в таблицу с помощью jQuery, создавая строку html, т.е.

var row = "";
row += "<tr>";
row += "<td>Name</td>";
row += "<td><input value='"+data.name+"'/></td>";
row += "</tr>";

data.name - строка, возвращаемая вызовом ajax, который может содержать любые символы. Если он содержит одну кавычку, ', он разбивает HTML, определяя конец значения атрибута.

Как я могу гарантировать правильность отображения строки в браузере?

4b9b3361

Ответ 1

Вам просто нужно поменять символы ' на эквивалентный код символа объекта HTML:

data.name.replace(/'/g, "&#39;");

В качестве альтернативы вы можете создать все это с помощью методов манипуляции JQuery DOM:

var row = $("<tr>").append("<td>Name</td><td></td>");
$("<input>", { value: data.name }).appendTo(row.children("td:eq(1)"));

Ответ 2

На самом деле вам может понадобиться одна из этих двух функций (это зависит от контекста использования). Эти функции обрабатывают все виды строковых кавычек, а также защищают от синтаксиса HTML/XML.

1. Функция quoteattr() для встраивания текста в HTML/XML:

Функция quoteattr() используется в контексте, где результат не будет оцениваться javascript, но должен интерпретироваться синтаксическим анализатором XML или HTML, и он должен абсолютно исключать нарушение синтаксиса атрибута элемента.

Символы новой строки сохраняются при создании содержимого текстовых элементов. Однако, если вы генерируете значение атрибута, это назначенное значение будет нормализовано DOM, как только оно будет установлено, поэтому все пробелы (SPACE, TAB, CR, LF) будут сжаты, удаляя начальные и конечные пробелы и сокращение всех средних последовательностей пробелов в одном ПРОСТРАНСТВЕ.

Но есть исключение: символ CR будет сохранен и не будет считаться пробелом, только, если он представлен с помощью числовой ссылки на символ! Результат будет действительным для всех атрибутов элемента, за исключением атрибутов типа NMTOKEN или ID или NMTOKENS: наличие ссылочного CR сделает присвоенное значение недействительным для этих атрибутов (например, id = "..." атрибут элементов HTML): это значение, являющееся недействительным, будет игнорироваться DOM. Но в других атрибутах (типа CDATA) все символы CR, представленные числовой символьной ссылкой, будут сохранены и не нормализованы. Обратите внимание, что этот прием не будет работать для сохранения других пробелов (SPACE, TAB, LF), даже если они представлены NCR, поскольку нормализация всех пробелов (за исключением NCR в CR) является обязательной в всех атрибуты.

Обратите внимание, что эта функция сама по себе не выполняет нормализацию пробелов в HTML/XML, поэтому она остается безопасной при создании содержимого текстового элемента (не передавайте второй параметр preserveCR для такого случая).

Поэтому, если вы передадите необязательный второй параметр (значение по умолчанию будет обрабатываться так, как если бы он был ложным), и если этот параметр оценивается как истина, новые строки будут сохранены с использованием этого NCR, когда вы захотите сгенерировать буквальное значение атрибута, и этот атрибут будет типа CDATA (например, атрибут title= "..."), а не типа ID, IDLIST, NMTOKEN или NMTOKENS (например, атрибут id = "...").

function quoteattr(s, preserveCR) {
    preserveCR = preserveCR ? '&#13;' : '\n';
    return ('' + s) /* Forces the conversion to string. */
        .replace(/&/g, '&amp;') /* This MUST be the 1st replacement. */
        .replace(/'/g, '&apos;') /* The 4 other predefined entities, required. */
        .replace(/"/g, '&quot;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        /*
        You may add other replacements here for HTML only 
        (but it not necessary).
        Or for XML, only if the named entities are defined in its DTD.
        */ 
        .replace(/\r\n/g, preserveCR) /* Must be before the next replacement. */
        .replace(/[\r\n]/g, preserveCR);
        ;
}

Предупреждение! Эта функция по-прежнему не проверяет исходную строку (которая в Javascript представляет собой неограниченный поток 16-битных кодовых единиц) на предмет ее действительности в файле, который должен быть допустимым источником простого текста и также как действительный источник для документа HTML/XML.

  • Он должен быть обновлен для обнаружения и отклонения (за исключением):
    • любые единицы кода, представляющие кодовые точки, назначенные не-символам (например,\uFFFE и \uFFFF): это требование Unicode только для допустимых простых текстов;
    • любые единицы суррогатного кода, которые неправильно спарены, чтобы сформировать действительную пару для кодированной точки в кодировке UTF-16: это требование Unicode для допустимых простых текстов;
    • любая действительная пара единиц суррогатного кода, представляющая действительную кодовую точку Unicode в дополнительных плоскостях, но назначенная не-символам (например, U + 10FFFE или U + 10FFFF): это требование Unicode только для действительных простых текстов;
    • большинство элементов управления C0 и C1 (в диапазонах \u0000..\u1F и\u007F..\u009F, за исключением элементов управления TAB и новой строки): это не требование Unicode, а дополнительное требование для допустимого HTML/XML.
  • Несмотря на это ограничение, приведенный выше код - это почти то, что вы захотите сделать. Как обычно. Современный движок javascript должен обеспечивать эту функцию изначально в системном объекте по умолчанию, но в большинстве случаев он не полностью обеспечивает строгую проверку обычного текста, а не проверку HTML/XML. Но объект документа HTML/XML, из которого будет вызываться ваш код Javascript, должен переопределить эту встроенную функцию.
  • Это ограничение обычно не является проблемой в большинстве случаев, поскольку исходная строка является результатом вычисления из исходных строк, поступающих из HTML/XML DOM.
  • Но это может потерпеть неудачу, если javascript извлекает подстроки и разбивает пары суррогатов, или если он генерирует текст из вычисляемых числовых источников (преобразование любого 16-битного значения кода в строку, содержащую эту единицу одного кода и добавление этих коротких строк или вставку эти короткие строки с помощью операций замены): если вы попытаетесь вставить закодированную строку в текстовый элемент HTML/XML DOM или в значение атрибута HTML/XML или имя элемента, DOM сам отклонит эту вставку и сгенерирует исключение; если ваш javascript вставляет результирующую строку в локальный двоичный файл или отправляет ее через двоичный сетевой сокет, исключение не будет выброшено для этого излучения. Такие строки в виде обычного текста также могут быть результатом чтения из двоичного файла (такого как файл изображения в формате PNG, GIF или JPEG) или из чтения вашего javascript из бинарно-безопасного сетевого сокета (такого, что поток ввода-вывода проходит 16- блоки битового кода, а не просто 8-битные блоки: большинство потоков двоичного ввода-вывода в любом случае основаны на байтах, и потокам текстового ввода-вывода необходимо указать кодировку для декодирования файлов в простой текст, чтобы недопустимые кодировки, найденные в текстовый поток вызовет исключение ввода-вывода в вашем скрипте).

Обратите внимание, что эта функция, как она реализована (если она дополнена для исправления ограничений, отмеченных в приведенном выше предупреждении), может также безопасно использоваться для цитирования также содержимого буквального текстового элемента в HTML/XML (чтобы избежать некоторые интерпретируемые элементы HTML/XML из исходного значения строки), а не только содержимое буквального значения атрибута! Так что его лучше назвать quoteml(); имя quoteattr() сохранилось только по традиции.

Это случай в вашем примере:

data.value = "It just a \"sample\" <test>.\n\tTry & see yourself!";
var row = '';
row += '<tr>';
row += '<td>Name</td>';
row += '<td><input value="' + quoteattr(data.value) + '" /></td>';
row += '</tr>';

Альтернатива quoteattr(), использующая только API DOM:

Альтернатива, если генерируемый вами HTML-код будет частью текущего HTML-документа, состоит в том, чтобы создавать каждый HTML-элемент индивидуально, используя методы документа DOM, так что вы можете устанавливать значения его атрибутов непосредственно через API DOM вместо вставка полного содержимого HTML с использованием свойства innerHTML одного элемента:

data.value = "It just a \"sample\" <test>.\n\tTry & see yourself!";
var row = document.createElement('tr');
var cell = document.createElement('td');
cell.innerText = 'Name';
row.appendChild(cell);
cell = document.createElement('td');
var input = document.createElement('input');
input.setAttribute('value', data.value);
cell.appendChild(input);
tr.appendChild(cell);
/*
The HTML code is generated automatically and is now accessible in the
row.innerHTML property, which you are not required to insert in the
current document.

But you can continue by appending tr into a 'tbody' element object, and then
insert this into a new 'table' element object, which ou can append or insert
as a child of a DOM object of your document.
*/

Обратите внимание, что эта альтернатива не пытается сохранить символы новой строки, присутствующие в data.value, потому что вы генерируете содержимое текстового элемента, а не значение атрибута. Если вы действительно хотите сгенерировать значение атрибута, сохраняя символы новой строки, используя &#13;, см. начало раздела 1 и код в quoteattr() выше.

2. Функция escape() для встраивания в буквенную строку javascript/JSON:

В других случаях вы будете использовать нижеприведенную функцию escape(), когда намереваетесь заключить в кавычки строку, которая будет частью сгенерированного фрагмента кода JavaScript, который вы также хотите сохранить (который может быть необязательно). также сначала должен быть проанализирован синтаксическим анализатором HTML/XML, в который может быть вставлен больший код javascript):

function escape(s) {
    return ('' + s) /* Forces the conversion to string. */
        .replace(/\\/g, '\\\\') /* This MUST be the 1st replacement. */
        .replace(/\t/g, '\\t') /* These 2 replacements protect whitespaces. */
        .replace(/\n/g, '\\n')
        .replace(/\u00A0/g, '\\u00A0') /* Useful but not absolutely necessary. */
        .replace(/&/g, '\\x26') /* These 5 replacements protect from HTML/XML. */
        .replace(/'/g, '\\x27')
        .replace(/"/g, '\\x22')
        .replace(/</g, '\\x3C')
        .replace(/>/g, '\\x3E')
        ;
}

Предупреждение! Этот исходный код не проверяет действительность закодированного документа как действительного простого текста. Однако он не должен никогда вызывать исключение (за исключением состояния нехватки памяти): исходные строки Javascript/JSON являются просто неограниченными потоками 16-битных кодовых единиц и не должны быть действительными в виде простого текста или не ограничено синтаксисом документа HTML/XML. Это означает, что код неполон, и его также следует заменить:

  • все остальные кодовые единицы, представляющие элементы управления C0 и C1 (за исключением TAB и LF, которые обрабатываются выше, но которые могут быть оставлены без изменений, без их замены) с использованием нотации \xNN;
  • все единицы кода, которые назначены не символам в Unicode, которые должны быть заменены с использованием нотации \uNNNN (например,\uFFFE или \uFFFF);
  • все единицы кода, используемые как суррогаты Юникода в диапазоне \uD800..\DFFF, например:
    • если они неправильно соединены в действительную пару UTF-16, представляющую действительную кодовую точку Unicode во всем диапазоне U + 0000..U + 10FFFF, эти единицы суррогатного кода должны быть заменены по отдельности с использованием записи \uDNNN;
    • в противном случае, если кодовая точка, которую представляет пара кодовых единиц, недопустима в простом тексте Unicode, поскольку кодовая точка назначена не символу, две кодовые точки должны быть заменены с использованием нотации \U00NNNNNN;
  • наконец, если кодовая точка, представленная единицей кода (или парой кодовых единиц, представляющих кодовую точку в дополнительной плоскости), независимо от того, назначена ли эта кодовая точка или зарезервирована/не назначена, также недействительна в исходных документах HTML/XML (см. их спецификацию), кодовая точка должна быть заменена с использованием нотации \uNNNN (если кодовая точка находится в BMP) или \u00NNNNNN (если кодовая точка находится в дополнительной плоскости);

Обратите внимание, что 5 последних замен не являются действительно необходимыми. Но если вы их не включите, вам иногда потребуется использовать "хак" совместимости <![CDATA[ ... ]]> в некоторых случаях, например, для дальнейшего включения сгенерированного JavaScript в HTML или XML (см. пример ниже, где этот "хак" используется в элементе HTML <script>...</script>.

Функция escape() имеет то преимущество, что она не вставляет любую ссылку на символ HTML/XML, результат сначала будет интерпретирован Javascript, и он будет позже сохранять во время выполнения точную длину строки, когда полученная строка будет быть оценены движком JavaScript. Это избавляет вас от необходимости управлять смешанным контекстом в коде вашего приложения (см. последний раздел о них и о связанных с этим вопросах безопасности). В частности, потому что, если вы используете quoteattr() в этом контексте, javascript, оцененный и выполненный позже, должен будет явно обрабатывать ссылки на символы, чтобы перекодировать их, что не подходит. Случаи использования включают в себя:

  1. когда замененная строка будет вставлена в сгенерированный обработчик событий javascript, окруженный каким-либо другим HTML-кодом, где фрагмент javascript будет содержать атрибуты, окруженные литеральными кавычками).
  2. когда замененная строка будет частью параметра settimeout(), который позже будет обработан eval() механизмом Javascript.

Пример 1 (генерируется только JavaScript, HTML-контент не генерируется):

var title = "It a \"title\"!";
var msg   = "Both strings contain \"quotes\" & 'apostrophes'...";
setTimeout(
    '__forceCloseDialog("myDialog", "' +
        escape(title) + '", "' +
        escape(msg) + '")',
    2000);

Пример 2 (создание корректного HTML):

var msg =
    "It just a \"sample\" <test>.\n\tTry & see yourself!";
/* This is similar to the above, but this JavaScript code will be reinserted below: */ 
var scriptCode =
    'alert("' +
    escape(msg) + /* important here!, because part of a JS string literal */
    '");';

/* First case (simple when inserting in a text element): */
document.write(
    '<script type="text/javascript">' +
    '\n//<![CDATA[\n' + /* (not really necessary but improves compatibility) */
    scriptCode +
    '\n//]]>\n' +       /* (not really necessary but improves compatibility) */
    '</script>');

/* Second case (more complex when inserting in an HTML attribute value): */
document.write(
    '<span onclick="' +
    quoteattr(scriptCode) + /* important here, because part of an HTML attribute */
    '">Click here !</span>');

Во втором примере вы видите, что обе функции кодирования одновременно используются для части сгенерированного текста, встроенного в литералы JavasSript (используя escape()), с сгенерированным кодом JavaScript ( содержащий сгенерированный строковый литерал), который сам снова внедряется и перекодируется с использованием quoteattr(), поскольку этот код JavaScript вставляется в атрибут HTML (во втором случае).

3. Общие соображения относительно безопасного кодирования текстов для встраивания в синтаксический контекст:

Итак, в итоге,

  • функция quotattr() должна использоваться при генерации константы литерала атрибута HTML/XML, где окружающие кавычки добавляются извне в конкатенации для получения полного кода HTML/XML.
  • функция escape() должна использоваться при генерации содержимого строкового константа JavaScript, где окружающие кавычки добавляются извне в конкатенации для получения полного кода HTML/XML.
  • При аккуратном использовании, и везде вы найдете содержимое переменной, которое можно безопасно вставить в другой контекст, и в соответствии только с этими правилами (с функциями, реализованными точно так же, как и выше, которые заботятся о "специальных символах", используемых в обоих контекстах) Вы можете смешивать как через множественное экранирование, так и преобразование все равно будет безопасным, и вам не потребуется дополнительный код для их декодирования в приложении с использованием этих литералов. не используйте эти функции.

Эти функции безопасны только в этих строгих контекстах (т.е. только значения атрибутов HTML/XML для quoteattr() и только строковые литералы Javascript для escape()).

Существуют другие контексты, использующие различные механизмы цитирования и экранирования (например, строковые литералы SQL или строковые литералы Visual Basic, литералы регулярных выражений, или текстовые поля файлов данных CSV, или значения заголовков MIME), для которых каждый потребуется их собственная отдельная экранирующая функция использовала только в следующих контекстах:

  • Никогда не предполагайте, что quoteattr() или escape() будут безопасны или не изменят семантику экранированной строки, прежде чем проверять сначала, что синтаксис (соответственно) значений атрибутов HTML/XML или литералов строки JavaScript будет изначально понят и поддержан в этих контекстах.
  • Например, синтаксис строковых литералов Javascript, сгенерированных escape(), также является подходящим и изначально поддерживается в двух других контекстах строковых литералов, используемых в исходном коде программирования Java, или текстовых значений в данных JSON.

Но обратное не всегда верно. Например:

  • Интерпретация закодированных экранированных литералов, изначально созданных для других контекстов, кроме строковых литералов Javascript (включая, например, строковые литералы в исходном коде PHP), не всегда безопасна для непосредственного использования в качестве литералов Javascript. через системную функцию javascript eval() для декодирования тех сгенерированных строковых литералов, которые не были экранированы с использованием escape(), потому что эти другие строковые литералы могут содержать другие специальные символы, сгенерированные специально для этих других начальных контекстов, которые будут неправильно интерпретироваться Javascript, это может включать дополнительные побеги, такие как "\Uxxxxxxxx" или "\e", или "${var}" и "$$", или включение дополнительных операторов конкатенации, таких как ' + ", которые изменяют стиль цитирования, или из "прозрачных" разделителей, таких как "<!--" и "-->" или "<[DATA[" и "]]>" (которые могут быть найдены и безопасны в другом только сложном контексте, поддерживающем несколько синтаксисов экранирования: см. ниже последний абзац этого раздела о смешанных контекстах).
  • То же самое будет применяться к интерпретации/декодированию закодированных экранированных литералов, которые изначально были созданы для других контекстов, в которых значения атрибутов HTML/XML в документах создаются с использованием их стандартного текстового представления (например, при попытке интерпретировать строковые литералы, которые были созданы для встраивания в нестандартное представление в двоичном формате документов HTML/XML!)
  • Это также будет применяться к интерпретации/декодированию с помощью функции javascript eval() строковых литералов, которые были сгенерированы только для безопасного включения в литералы атрибутов HTML/XML с использованием quotteattr(), что не будет безопасным, поскольку контексты были неправильно смешаны.
  • Это также будет применяться к интерпретации/декодированию с помощью синтаксического анализатора текстовых документов HTML/XML с литералами значений атрибутов, которые были сгенерированы только для безопасного включения в строковый литерал Javascript с использованием escape(), что не будет безопасным, потому что контексты также были неправильно смешаны.

4. Безопасное декодирование значения встроенных синтаксических литералов:

Если вы хотите декодировать или интерпретировать строковые литералы в контекстах, в которых декодированные результирующие строковые значения будут использоваться взаимозаменяемо и нечетко, без изменения в другом контексте, так называемых смешанных контекстах (включая, например, присвоение имен идентификаторам в HTML/XML с помощью строковых литералов на начальном этапе) с надежной кодировкой quotteattr(), присвоение имен программным переменным для Javascript из строк, изначально безопасно закодированных с помощью escape() и т.д.), вам необходимо подготовить и использовать новую функцию экранирования (которая также проверит правильность строкового значения перед его кодированием, отклонением или усечением/упрощением/фильтрацией), а также новой функцией декодирования (которая также тщательно избегает интерпретации допустимых, но небезопасных последовательностей, только принятых внутренне, но неприемлемых для небезопасных внешних источников), что также означает, что для декодирования источников данных JSON необходимо абсолютно исключить такую функцию декодирования, как eval() в javascript, для чего вам потребуется использовать более безопасный собственный JSON-декодер; ve JSON-декодер не будет интерпретировать допустимые последовательности Javascript, такие как включение разделителей в кавычках в буквальное выражение, операторы или последовательности, такие как "{$var}"), для обеспечения безопасности такого отображения!

Эти последние соображения о декодировании литералов в смешанных контекстах, которые были надежно закодированы только с помощью любого синтаксиса для передачи данных, чтобы быть безопасным только в более ограниченном единственном контексте, абсолютно необходимы для безопасности вашего приложения или веб-службы. Никогда не смешивайте эти контексты между местом кодирования и местом декодирования, если эти места не принадлежат одной и той же области безопасности (но даже в этом случае использование смешанных контекстов всегда очень опасно, это очень трудно точно отслеживать в своем коде.

По этой причине я рекомендую вам никогда не использовать и не предполагать смешанные контексты в любом месте вашего приложения: вместо этого напишите безопасную функцию кодирования и декодирования для единственного точного контекста, который имеет точные правила длины и допустимости для значений декодированной строки, и правила точной длины и допустимости строковых литералов в кодированной строке. Запретите эти смешанные контексты: для каждого изменения контекста используйте другую подходящую пару функций кодирования/декодирования (какая функция используется в этой паре зависит от того, какой контекст встроен в другой контекст; и от пары сопоставления функции также специфичны для каждой пары контекстов).

Это означает, что:

  • Чтобы безопасно декодировать литерал значения атрибута HTML/XML, который был изначально закодирован с помощью quoteattr(), вы должны '' 'не' '' предполагать, что он был закодирован с использованием других именованных объектов, значение которых будет зависеть от определенного DTD, определяющего его. Вы должны вместо этого инициализировать анализатор HTML/XML для поддержки только нескольких именованных символьных сущностей по умолчанию, сгенерированных quoteattr(), и, необязательно, числовых символьных сущностей (которые также безопасны в таком контексте: функция quoteattr() генерирует только несколько из них, но может генерировать больше этих числовых ссылок на символы, но не должно генерировать другие именованные объекты символов, которые не предопределены в DTD по умолчанию). Все другие именованные объекты должны быть отклонены вашим анализатором как недопустимые в исходном строковом литерале для декодирования. В качестве альтернативы вы получите более высокую производительность, определив функцию unquoteattr (которая будет отклонять любое присутствие буквенных кавычек в исходной строке, а также неподдерживаемых именованных сущностей).
  • Чтобы безопасно декодировать строковый литерал Javascript (или строковый литерал JSON), который был изначально закодирован с помощью escape(), вы должны использовать безопасную функцию JavaScript unescape(), но не небезопасно Функция Javascript eval()!

Ниже приведены примеры этих двух связанных функций безопасного декодирования.

5. Функция unquoteattr() для анализа текста, встроенного в текстовые элементы HTML/XML или литералы значений атрибутов:

function unquoteattr(s) {
    /*
    Note: this can be implemented more efficiently by a loop searching for
    ampersands, from start to end of ssource string, and parsing the
    character(s) found immediately after after the ampersand.
    */
    s = ('' + s); /* Forces the conversion to string type. */
    /*
    You may optionally start by detecting CDATA sections (like
    '<![CDATA[' ... ']]>'), whose contents must not be reparsed by the
    following replacements, but separated, filtered out of the CDATA
    delimiters, and then concatenated into an output buffer.
    The following replacements are only for sections of source text
    found *outside* such CDATA sections, that will be concatenated
    in the output buffer only after all the following replacements and
    security checkings.

    This will require a loop starting here.

    The following code is only for the alternate sections that are
    not within the detected CDATA sections.
    */
    /* Decode by reversing the initial order of replacements. */
    s = s
        .replace(/\r\n/g, '\n') /* To do before the next replacement. */ 
        .replace(/[\r\n]/, '\n')
        .replace(/&#13;&#10;/g, '\n') /* These 3 replacements keep whitespaces. */
        .replace(/&#1[03];/g, '\n')
        .replace(/&#9;/g, '\t')
        .replace(/&gt;/g, '>') /* The 4 other predefined entities required. */
        .replace(/&lt;/g, '<')
        .replace(/&quot;/g, '"')
        .replace(/&apos;/g, "'")
        ;
    /*
    You may add other replacements here for predefined HTML entities only 
    (but it not necessary). Or for XML, only if the named entities are
    defined in *your* assumed DTD.
    But you can add these replacements only if these entities will *not* 
    be replaced by a string value containing *any* ampersand character.
    Do not decode the '&amp;' sequence here !

    If you choose to support more numeric character entities, their
    decoded numeric value *must* be assigned characters or unassigned
    Unicode code points, but *not* surrogates or assigned non-characters,
    and *not* most C0 and C1 controls (except a few ones that are valid
    in HTML/XML text elements and attribute values: TAB, LF, CR, and
    NL='\x85').

    If you find valid Unicode code points that are invalid characters
    for XML/HTML, this function *must* reject the source string as
    invalid and throw an exception.

    In addition, the four possible representations of newlines (CR, LF,
    CR+LF, or NL) *must* be decoded only as if they were '\n' (U+000A).

    See the XML/HTML reference specifications !
    */
    /* Required check for security! */
    var found = /&[^;]*;?/.match(s);
    if (found.length >0 && found[0] != '&amp;')
        throw 'unsafe entity found in the attribute literal content';
     /* This MUST be the last replacement. */
    s = s.replace(/&amp;/g, '&');
    /*
    The loop needed to support CDATA sections will end here.
    This is where you'll concatenate the replaced sections (CDATA or
    not), if you have splitted the source string to detect and support
    these CDATA sections.

    Note that all backslashes found in CDATA sections do NOT have the
    semantic of escapes, and are *safe*.

    On the opposite, CDATA sections not properly terminated by a
    matching ']]>' section terminator are *unsafe*, and must be rejected
    before reaching this final point.
    */
    return s;
}

Обратите внимание, что эта функция не анализирует окружающие кавычки, которые используются окружить значения атрибута HTML. Эта функция может фактически декодировать любой текстовый элемент HTML/XML, возможно, содержащий буквенные кавычки, которые являются безопасными. Это ваша ответственность за анализ HTML-кода для извлечения строк в кавычках, используемых в атрибутах HTML/XML, и для удаления соответствующих разделителей кавычек перед вызовом функции unquoteattr().

6. Функция unescape() для анализа текстового содержимого, встроенного в литералы Javascript/JSON:

function unescape(s) {
    /*
    Note: this can be implemented more efficiently by a loop searching for
    backslashes, from start to end of source string, and parsing and
    dispatching the character found immediately after the backslash, if it
    must be followed by additional characters such as an octal or
    hexadecimal 7-bit ASCII-only encoded character, or an hexadecimal Unicode
    encoded valid code point, or a valid pair of hexadecimal UTF-16-encoded
    code units representing a single Unicode code point.

    8-bit encoded code units for non-ASCII characters should not be used, but
    if they are, they should be decoded into a 16-bit code units keeping their
    numeric value, i.e. like the numeric value of an equivalent Unicode
    code point (which means ISO 8859-1, not Windows 1252, including C1 controls).

    Note that Javascript or JSON does NOT require code units to be paired when
    they encode surrogates; and Javascript/JSON will also accept any Unicode
    code point in the valid range representable as UTF-16 pairs, including
    NULL, all controls, and code units assigned to non-characters.
    This means that all code points in \U00000000..\U0010FFFF are valid,
    as well as all 16-bit code units in \u0000..\uFFFF, in any order.
    It up to your application to restrict these valid ranges if needed.
    */
    s = ('' + s) /* Forces the conversion to string. */
    /* Decode by reversing the initial order of replacements */
        .replace(/\\x3E/g, '>')
        .replace(/\\x3C/g, '<')
        .replace(/\\x22/g, '"')
        .replace(/\\x27/g, "'")
        .replace(/\\x26/g, '&') /* These 5 replacements protect from HTML/XML. */
        .replace(/\\u00A0/g, '\u00A0') /* Useful but not absolutely necessary. */
        .replace(/\\n/g, '\n')
        .replace(/\\t/g, '\t') /* These 2 replacements protect whitespaces. */
        ;
    /*
    You may optionally add here support for other numerical or symbolic
    character escapes.
    But you can add these replacements only if these entities will *not* 
    be replaced by a string value containing *any* backslash character.
    Do not decode to any doubled backslashes here !
    */
    /* Required check for security! */
    var found = /\\[^\\])?/.match(s);
    if (found.length > 0 && found[0] != '\\\\')
        throw 'Unsafe or unsupported escape found in the literal string content';
    /* This MUST be the last replacement. */
    return s.replace(/\\\\/g, '\\');
}

Обратите внимание, что эта функция не анализирует окружающие кавычки, которые используются окружать Javascript или JSON строки буквально. Это ваша ответственность разбирать исходный код Javascript или JSON для извлечения строковых литералов в кавычках и для удаления этих соответствующих разделителей кавычек перед вызовом функции unescape().

Ответ 3

" = &quot; or &#34;

' = &#39;

Примеры:

<div attr="Tim &quot;The Toolman&quot; Taylor"
<div attr='Tim "The Toolman" Taylor'
<div attr="Tim 'The Toolman' Taylor"
<div attr='Tim &#39;The Toolman&#39; Taylor'

В строках JavaScript вы используете \, чтобы избежать символа кавычки:

var s = "Tim \"The Toolman\" Taylor";
var s = 'Tim \'The Toolman\' Taylor';

Итак, укажите ваши значения атрибутов с помощью "и используйте такую ​​функцию:

function escapeAttrNodeValue(value) {
    return value.replace(/(&)|(")|(\u00A0)/g, function(match, amp, quote) {
        if (amp) return "&amp;";
        if (quote) return "&quot;";
        return "&nbsp;";
    });
}

Ответ 4

Мой ответ частично основан на Andy E, и я по-прежнему рекомендую читать то, что написал verdy_p, но здесь он

$("<a>", { href: 'very<script>\'b"ad' }).text('click me')[0].outerHTML

Отказ от ответственности: это ответ не на точный вопрос, а просто "как избежать атрибута"

Ответ 5

Данные ответы кажутся довольно сложными, поэтому для моего случая использования я попробовал встроенный encodeURIComponent и decodeURIComponent и обнаружил, что они работали хорошо, а за комментарии этого не избежать ', но для этого вы можете использовать escape() и unescape() в unescape() методах вместо.

Ответ 6

Я думаю, вы могли бы сделать:

var row = "";
row += "<tr>";
row += "<td>Name</td>";
row += "<td><input value=\""+data.name+"\"/></td>";
row += "</tr>";

Если вас беспокоит в data.name, который является существующей одинарной цитатой.

В лучшем случае вы можете создать элемент INPUT, а затем setValue(data.name) для него.

Ответ 7

Используя Lodash:

const serialised = _.escape("Here a string that could break HTML");

// Add it into data-attr in HTML
<a data-value-serialised=" + serialised + " onclick="callback()">link</a>
// and then at JS where this value will be read:
function callback(e) {  
    $(e.currentTarget).data('valueSerialised'); // with a bit of help from jQuery

    const originalString = _.unescape(serialised); // can be used as part of a payload or whatever.
}