Как избежать кавычек в значениях атрибутов HTML?
Я строю строку для вставки в таблицу с помощью jQuery путем создания строки HTML, т.е.
var row = "";
row += "<tr>";
row += "<td>Name</td>";
row += "<td><input value='"+data.name+"'/></td>";
row += "</tr>";
data.name
это строка, возвращаемая из вызова ajax, которая может содержать любые символы. Если он содержит одну цитату, '
, он сломает HTML, определив конец значения атрибута.
Как я могу убедиться, что строка отображается правильно в браузере?
6 ответов
Вам просто нужно поменять любой '
символы с эквивалентным кодом символа сущности HTML:
data.name.replace(/'/g, "'");
В качестве альтернативы, вы можете создать все это, используя методы манипулирования DOM в jQuery:
var row = $("<tr>").append("<td>Name</td><td></td>");
$("<input>", { value: data.name }).appendTo(row.children("td:eq(1)"));
На самом деле вам может понадобиться одна из этих двух функций (это зависит от контекста использования). Эти функции обрабатывают все виды строковых кавычек, а также защищают от синтаксиса 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 ? ' ' : '\n';
return ('' + s) /* Forces the conversion to string. */
.replace(/&/g, '&') /* This MUST be the 1st replacement. */
.replace(/'/g, ''') /* The 4 other predefined entities, required. */
.replace(/"/g, '"')
.replace(/</g, '<')
.replace(/>/g, '>')
/*
You may add other replacements here for HTML only
(but it's 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's 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()
, используя только DOM API:
Альтернатива, если генерируемый вами HTML-код будет частью текущего HTML-документа, состоит в том, чтобы создавать каждый HTML-элемент индивидуально, используя методы документа DOM, так что вы можете устанавливать значения его атрибутов непосредственно через API DOM, а не вставка полного содержимого HTML с использованием свойства innerHTML одного элемента:
data.value = "It's 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, потому что вы генерируете содержимое текстового элемента, а не значение атрибута здесь. Если вы действительно хотите сгенерировать значение атрибута, сохраняя символы новой строки, используя
см. начало раздела 1 и код внутри quoteattr()
выше.
2. The 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;
- все единицы кода, которые назначены не символам в Юникоде, которые должны быть заменены с использованием нотации \uNNNN (например, \uFFFE или \uFFFF);
- все единицы кода, используемые как суррогаты Unicode в диапазоне \uD800..\DFFF, например:
- если они неправильно соединены в действительную пару UTF-16, представляющую действительную кодовую точку Unicode во всем диапазоне U+0000..U+10FFFF, эти единицы суррогатного кода должны быть заменены индивидуально с использованием записи \uDNNN;
- иначе, если, если кодовая точка, которую представляет пара кодовых единиц, недопустима в простом тексте Unicode, потому что кодовая точка назначена не символу, две кодовые точки должны быть заменены с использованием нотации \U00NNNNNN;
- наконец, если кодовая точка, представленная единицей кода (или парой кодовых единиц, представляющих кодовую точку в дополнительной плоскости), независимо от того, назначена ли эта кодовая точка или зарезервирована / не назначена, также недействительна в исходных документах HTML/XML (см. их спецификацию), кодовая точка должна быть заменена с использованием нотации \uNNNN (если кодовая точка находится в BMP) или \u00NNNNNN (если кодовая точка находится в дополнительной плоскости);
Обратите внимание, что 5 последних замен не являются действительно необходимыми. Но если вы их не включите, вам иногда придется использовать <![CDATA[ ... ]]>
совместимость "взломать" в некоторых случаях, например, дальнейшее включение сгенерированного JavaScript в HTML или XML (см. пример ниже, где этот "взлом" используется в <script>...</script>
Элемент HTML).
escape()
Преимущество функции заключается в том, что она не вставляет никакую ссылку на символ HTML/XML, результат будет сначала интерпретирован Javascript, и он будет позже сохранять во время выполнения точную длину строки, когда результирующая строка будет оценена механизмом javascript. Это избавляет вас от необходимости управлять смешанным контекстом в коде вашего приложения (см. Последний раздел о них и о связанных с этим вопросах безопасности). Особенно потому, что если вы используете quoteattr()
в этом контексте javascript, оцененный и выполненный позже, должен будет явно обрабатывать ссылки на символы, чтобы перекодировать их, что не подходит. Случаи использования включают в себя:
- когда замененная строка будет вставлена в сгенерированный обработчик событий javascript, окруженный каким-либо другим HTML-кодом, где фрагмент javascript будет содержать атрибуты, окруженные литеральными кавычками).
- когда замененная строка будет частью параметра settimeout(), который позднее будет обработан eval() механизмом Javascript.
Пример 1 (генерируется только JavaScript, HTML-контент не генерируется):
var title = "It's a \"title\"!";
var msg = "Both strings contain \"quotes\" & 'apostrophes'...";
setTimeout(
'__forceCloseDialog("myDialog", "' +
escape(title) + '", "' +
escape(msg) + '")',
2000);
Пример 2 (создание корректного HTML):
var msg =
"It's 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[
" а также "]]>
msgstr " (это может быть найдено и безопасно в другом только сложном контексте, поддерживающем множественные экранирующие синтаксисы: см. ниже последний абзац этого раздела о смешанных контекстах). - То же самое будет применяться к интерпретации / декодированию закодированных экранированных литералов, которые были изначально созданы для других контекстов, в которых значения атрибутов HTML/XML в документах создаются с использованием их стандартного текстового представления (например, при попытке интерпретировать строковые литералы, которые были созданы для встраивания в нестандартное представление в двоичном формате документов HTML/XML!)
- Это также относится к интерпретации / декодированию с помощью функции javascript.
eval()
строковых литералов, которые были безопасно созданы только для включения в литералы атрибутов HTML/XML с использованиемquotteattr()
, что не будет безопасным, потому что контексты были неправильно смешаны. - Это также будет применяться к интерпретации / декодированию с помощью синтаксического анализатора текстовых документов HTML/XML литералов значений атрибутов, которые были безопасно созданы только для включения в строковый литерал Javascript с использованием
escape()
, что не будет безопасным, потому что контексты также были неправильно смешаны.
4. Безопасное декодирование значения встроенных синтаксических литералов:
Если вы хотите декодировать или интерпретировать строковые литералы в контекстах, в которых декодированные результирующие строковые значения будут использоваться взаимозаменяемо и нечетко, без изменения в другом контексте, так называемых смешанных контекстах (включая, например, присвоение имен идентификаторам в HTML/XML с помощью строковых литералов изначально неправильно кодируется quotteattr()
; называя некоторые программные переменные для Javascript из строк, изначально безопасно закодированных escape()
; и так далее...), вам нужно будет подготовить и использовать новую функцию экранирования (которая также проверит правильность строкового значения перед его кодированием, или отклонит его, или усечет / упростит / отфильтрует его), а также в качестве новой функции декодирования (которая также будет тщательно избегать интерпретации действительных, но небезопасных последовательностей, только принятых внутренне, но не приемлемых для небезопасных внешних источников, что также означает, что функция декодирования, такая как eval()
в javascript необходимо абсолютно избегать декодирования источников данных JSON, для чего вам потребуется использовать более безопасный собственный JSON-декодер; нативный JSON-декодер не будет интерпретировать допустимые последовательности Javascript, такие как включение разделителей в кавычках в буквальное выражение, операторы или последовательности типа " {$var}
"), чтобы обеспечить безопасность такого отображения!
Эти последние соображения относительно декодирования литералов в смешанных контекстах, которые были надежно закодированы только с помощью любого синтаксиса для безопасной передачи данных только в более ограничивающем отдельном контексте, абсолютно необходимы для безопасности вашего приложения или веб-службы. Никогда не смешивайте эти контексты между местом кодирования и местом декодирования, если эти места не принадлежат одной и той же области безопасности (но даже в этом случае использование смешанных контекстов всегда очень опасно, очень трудно точно отследить в вашем коде.
По этой причине я рекомендую вам никогда не использовать и не предполагать смешанные контексты где-либо в вашем приложении: вместо этого напишите безопасную функцию кодирования и декодирования для единственного точного контекста, который имеет точные правила длины и допустимости для значений декодированной строки, а также точные правила длины и действительности для закодированные строковые строковые литералы. Запретите эти смешанные контексты: для каждого изменения контекста используйте другую совпадающую пару функций кодирования / декодирования (какая функция используется в этой паре зависит от того, какой контекст встроен в другой контекст; и пара совпадающих функций также специфична для каждого пара контекстов).
Это означает, что:
- Для безопасного декодирования литерала значения атрибута HTML/XML, который был изначально закодирован
quoteattr()
Вы должны '''не' '' предполагать, что он был закодирован с использованием других именованных объектов, значение которых будет зависеть от определенного DTD, определяющего его. Вместо этого вы должны инициализировать анализатор HTML/XML для поддержки только нескольких именованных символьных сущностей по умолчанию, созданныхquoteattr()
и, необязательно, числовые символьные объекты (которые также безопасны в таком контексте:quoteattr()
функция генерирует только несколько из них, но может генерировать больше этих числовых ссылок на символы, но не должна генерировать другие именованные символьные объекты, которые не определены в DTD по умолчанию). Все остальные именованные сущности должны быть отклонены вашим синтаксическим анализатором как недопустимые в исходном строковом литерале для декодирования. В качестве альтернативы вы получите лучшую производительность, определивunquoteattr
функция (которая будет отклонять любое присутствие буквальных кавычек в исходной строке, а также неподдерживаемых именованных сущностей). - Для безопасного декодирования строкового литерала Javascript (или строкового литерала JSON), который был изначально закодирован
escape()
, вы должны использовать безопасный JavaScriptunescape()
функция, но не небезопасный Javascripteval()
функция!
Ниже приведены примеры этих двух связанных функций безопасного декодирования.
5. The 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(/ /g, '\n') /* These 3 replacements keep whitespaces. */
.replace(/[03];/g, '\n')
.replace(/	/g, '\t')
.replace(/>/g, '>') /* The 4 other predefined entities required. */
.replace(/</g, '<')
.replace(/"/g, '"')
.replace(/'/g, "'")
;
/*
You may add other replacements here for predefined HTML entities only
(but it's 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 '&' 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] != '&')
throw 'unsafe entity found in the attribute literal content';
/* This MUST be the last replacement. */
s = s.replace(/&/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. The 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's 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()
функция.
" = " or "
' = '
Примеры:
<div attr="Tim "The Toolman" Taylor"
<div attr='Tim "The Toolman" Taylor'
<div attr="Tim 'The Toolman' Taylor"
<div attr='Tim 'The Toolman' 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 "&";
if (quote) return """;
return " ";
});
}
Мой ответ частично основан на Энди Э, и я все еще рекомендую прочитать то, что написал verdy_p, но здесь это
$("<a>", { href: 'very<script>\'b"ad' }).text('click me')[0].outerHTML
Отказ от ответственности: это ответ не на точный вопрос, а просто как избежать атрибута
Используя Lodash:
const serialised = _.escape("Here's 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.
}
Я думаю, что вы могли бы сделать:
var row = "";
row += "<tr>";
row += "<td>Name</td>";
row += "<td><input value=\""+data.name+"\"/></td>";
row += "</tr>";
Если вы беспокоитесь о data.name
которая является существующей одинарной кавычкой.
В лучшем случае вы могли бы создать INPUT
элемент тогда setValue(data.name)
для этого.
Приведенные ответы кажутся довольно сложными, поэтому для моего случая использования я попробовал встроенный encodeURIComponent
а также decodeURIComponent
и обнаружили, что они работали хорошо.