Как заменить не SGML символы в строке с помощью PHP? - PullRequest
6 голосов
/ 16 марта 2012

Я запрограммировал гостевую книгу, используя PHP4 и HTML 4.01 (с кодировкой ISO-8859-15, т.е. с латиницей-9).Данные сохраняются в MySQL-базе данных с набором символов (ISO-8859-1, т.е. latin-1).

Когда кто-то вводит символы из другого набора символов, кажется, что браузеры отправляют данные в кодированном виде (на самом деле я не проверял, где он кодируется, ...).

Во всяком случае, в некоторых случаях кажется, что символы не сохраняются закодированными в базе данных.Таким образом, валидатор возвращает сообщение об ошибке, когда я добавляю показ данных в документе HTML4.01:

не SGML символьный номер 146

Вы использовали недопустимый символ в своем тексте,HTML использует стандартный репертуар символов Консорциума UNICODE и оставляет неопределенными (среди прочего) 65 кодов символов (от 0 до 31 включительно и от 127 до 159 включительно), которые иногда используются для типографских кавычек и аналогичных в проприетарных наборах символов.Валидатор обнаружил один из этих неопределенных символов в вашем документе.Символ может появиться в вашем браузере в виде фигурной кавычки или символа товарного знака, или другого необычного символа;однако на другом компьютере он, скорее всего, будет выглядеть как совершенно другой символ или вообще ничего.

Лучше всего заменить символ ближайшим эквивалентным символом ASCII или использовать соответствующий объект персонажа.,Для получения дополнительной информации о кодировке символов в Интернете см. Превосходную справку Алана Флавелла о проблемах с набором символов HTML.

Эта ошибка также может быть вызвана форматированием символов, встроенных в документы некоторыми текстовыми процессорами.Если вы используете текстовый процессор для редактирования ваших документов HTML, обязательно используйте команду «Сохранить как ASCII» или аналогичную команду, чтобы сохранить документ без информации о форматировании.

Я сейчас использую PHP5.2.17и немного поиграл с htmlspecialchars, но ничего не получалось.Как я могу закодировать эти символы, чтобы больше не было ошибок проверки?

Ответы [ 2 ]

3 голосов
/ 16 марта 2012

Как в ISO-8859-1, так и в ISO-8859-15 номер 146 является управляющим символом MW (Ожидание сообщения) из диапазона C1 .

Ссылка SGMLISO 8859-1 (обратите внимание на расстояние между ISO и 8859-1, которое не является дефисом, как в наборах символов, которые вы используете).Он не допускает управляющих символов, но три (здесь: SGML в HTML ):

В наборе символов документа HTML допускаются только три управляющих символа: горизонтальная табуляция, возврат каретки,и перевод строки (кодовые позиции 9, 13 и 10).

Поэтому вы передали недопустимый символ.Не существует сущности SGML / HTML, для которой вы можете заменить ее.

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

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

МожетИмеет смысл изменить общую кодировку на UTF-8 для поддержки более широкого диапазона символов, но это действительно может .

Редактировать: Часть вышенесколько строгий взгляд.Мне пришло в голову, что ввод, который вы получаете, на самом деле не ISO-8859-1 (5), а что-то другое, например, кодовая страница Windows.Я бы сказал, что это Windows-1252 (cp1252) Википедия .По сравнению с диапазоном С1 ISO-8859-1 (128-159) он имеет несколько неконтролирующих символов.

На странице Википедии также отмечается, что большинство браузеров рассматривают ISO-8859-1 как Windows-1252 / CP1252./ CP-1252. PHP htmlentities() функция не может работать с этими символами, таблица перевода для HTML-сущностей не охватывает кодовые точки (PHP 5.3, не тестировалась по 5.4).Вам необходимо создать собственную таблицу перевода и использовать ее с strtr для замены символов, недоступных в ISO 8859-15 для windows-1252:

/*
 * mappings of Windows-1252 (cp1252)  128 (0x80) - 159 (0x9F) characters:
 * @link http://en.wikipedia.org/wiki/Windows-1252
 * @link http://www.w3.org/TR/html4/sgml/entities.html
 */
$cp1252HTML401Entities = array(
    "\x80" => '€',    # 128 -> euro sign, U+20AC NEW
    "\x82" => '‚',   # 130 -> single low-9 quotation mark, U+201A NEW
    "\x83" => 'ƒ',    # 131 -> latin small f with hook = function = florin, U+0192 ISOtech
    "\x84" => '„',   # 132 -> double low-9 quotation mark, U+201E NEW
    "\x85" => '…',  # 133 -> horizontal ellipsis = three dot leader, U+2026 ISOpub
    "\x86" => '†',  # 134 -> dagger, U+2020 ISOpub
    "\x87" => '‡',  # 135 -> double dagger, U+2021 ISOpub
    "\x88" => 'ˆ',    # 136 -> modifier letter circumflex accent, U+02C6 ISOpub
    "\x89" => '‰',  # 137 -> per mille sign, U+2030 ISOtech
    "\x8A" => 'Š',  # 138 -> latin capital letter S with caron, U+0160 ISOlat2
    "\x8B" => '‹',  # 139 -> single left-pointing angle quotation mark, U+2039 ISO proposed
    "\x8C" => 'Œ',   # 140 -> latin capital ligature OE, U+0152 ISOlat2
    "\x8E" => 'Ž',    # 142 -> U+017D
    "\x91" => '‘',   # 145 -> left single quotation mark, U+2018 ISOnum
    "\x92" => '’',   # 146 -> right single quotation mark, U+2019 ISOnum
    "\x93" => '“',   # 147 -> left double quotation mark, U+201C ISOnum
    "\x94" => '”',   # 148 -> right double quotation mark, U+201D ISOnum
    "\x95" => '•',    # 149 -> bullet = black small circle, U+2022 ISOpub
    "\x96" => '–',   # 150 -> en dash, U+2013 ISOpub
    "\x97" => '—',   # 151 -> em dash, U+2014 ISOpub
    "\x98" => '˜',   # 152 -> small tilde, U+02DC ISOdia
    "\x99" => '™',   # 153 -> trade mark sign, U+2122 ISOnum
    "\x9A" => 'š',  # 154 -> latin small letter s with caron, U+0161 ISOlat2
    "\x9B" => '›',  # 155 -> single right-pointing angle quotation mark, U+203A ISO proposed
    "\x9C" => 'œ',   # 156 -> latin small ligature oe, U+0153 ISOlat2
    "\x9E" => 'ž',    # 158 -> U+017E
    "\x9F" => 'Ÿ',    # 159 -> latin capital letter Y with diaeresis, U+0178 ISOlat2
);

$outputWithEntities = strtr($output, $cp1252HTML401Entities);

Если вы хотитечтобы быть еще более безопасным, вы можете сэкономить именованные объекты и просто выбрать числовые, которые также должны работать в очень старых браузерах:

$cp1252HTMLNumericEntities = array(
    "\x80" => '€',   # 128 -> euro sign, U+20AC NEW
    "\x82" => '‚',   # 130 -> single low-9 quotation mark, U+201A NEW
    "\x83" => 'ƒ',    # 131 -> latin small f with hook = function = florin, U+0192 ISOtech
    "\x84" => '„',   # 132 -> double low-9 quotation mark, U+201E NEW
    "\x85" => '…',   # 133 -> horizontal ellipsis = three dot leader, U+2026 ISOpub
    "\x86" => '†',   # 134 -> dagger, U+2020 ISOpub
    "\x87" => '‡',   # 135 -> double dagger, U+2021 ISOpub
    "\x88" => 'ˆ',    # 136 -> modifier letter circumflex accent, U+02C6 ISOpub
    "\x89" => '‰',   # 137 -> per mille sign, U+2030 ISOtech
    "\x8A" => 'Š',    # 138 -> latin capital letter S with caron, U+0160 ISOlat2
    "\x8B" => '‹',   # 139 -> single left-pointing angle quotation mark, U+2039 ISO proposed
    "\x8C" => 'Œ',    # 140 -> latin capital ligature OE, U+0152 ISOlat2
    "\x8E" => 'Ž',    # 142 -> U+017D
    "\x91" => '‘',   # 145 -> left single quotation mark, U+2018 ISOnum
    "\x92" => '’',   # 146 -> right single quotation mark, U+2019 ISOnum
    "\x93" => '“',   # 147 -> left double quotation mark, U+201C ISOnum
    "\x94" => '”',   # 148 -> right double quotation mark, U+201D ISOnum
    "\x95" => '•',   # 149 -> bullet = black small circle, U+2022 ISOpub
    "\x96" => '–',   # 150 -> en dash, U+2013 ISOpub
    "\x97" => '—',   # 151 -> em dash, U+2014 ISOpub
    "\x98" => '˜',    # 152 -> small tilde, U+02DC ISOdia
    "\x99" => '™',   # 153 -> trade mark sign, U+2122 ISOnum
    "\x9A" => 'š',    # 154 -> latin small letter s with caron, U+0161 ISOlat2
    "\x9B" => '›',   # 155 -> single right-pointing angle quotation mark, U+203A ISO proposed
    "\x9C" => 'œ',    # 156 -> latin small ligature oe, U+0153 ISOlat2
    "\x9E" => 'ž',    # 158 -> U+017E
    "\x9F" => 'Ÿ',    # 159 -> latin capital letter Y with diaeresis, U+0178 ISOlat2
);

Надеюсь, теперь это будет более полезным.Также смотрите страницу Википедии, на которой есть ссылки, для некоторых символов, которые в разных точках находятся в windows-1242 и ISO 8859-15 , но .Возможно, вам следует рассмотреть возможность использования UTF-8 на вашем сайте.

2 голосов
/ 16 марта 2012

Веб-страница с полем ввода текста должна иметь кодировку UTF-8, поскольку это единственный способ обеспечить правильную передачу всех введенных пользователем символов.То, как вы справляетесь с ними на стороне сервера (например, отклонение символов за пределами определенного диапазона), является другой проблемой.

Если вы используете другую кодировку и пользователь вводит символ, который не имеет представления в этой кодировке, этоявляется ошибкой, которую браузеры могут обрабатывать так, как им нравится.Современные браузеры делают что-то очень странное в принципе, хотя и полезно на практике: они представляют символы в виде ссылок на символы, например ’ для правильной одинарной кавычки (').В этом случае полученные данные такие же, как если бы пользователь фактически набрал символы ’ (но это настолько теоретически, что поставщики браузеров, по-видимому, игнорируют проблему).

Что происходит на стороне сервера в вашемСлучай неясен, но он может включать в себя много типов обработки.В любом случае, вы вообще не можете хранить ISO-8859-15 в кодировке ISO-8859-1 (ISO-8859-15 был разработан для замены некоторых символов в ISO-8859-1 другими символами).Неясно, что ваша программа делает с символьными ссылками типа ’.Было бы немного странным, хотя и вполне возможно, что программное обеспечение заменить их ссылками на символы, например ’ (которые основаны на использовании windows-1252 в качестве набора символов документа, вопреки правилам HTML; они технически не определены, а не запрещены)в HTML, но так широко поддерживается браузерами, что HTML5 превращает это в правило).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...