Как очистить пользовательский ввод для правильного кодирования содержимого перед его сохранением? - PullRequest
12 голосов
/ 15 апреля 2009

У меня есть приложение, в котором пользователи вводят текст в формы.

Данные сохраняются в базе данных MySQL (сопоставление: utf8_general_ci) и затем выводятся в формате XML (кодировка: UTF-8).

Проблема заключается в том, что люди склонны вырезать и вставлять свою информацию из других источников, например, документов Microsoft Word или PDF-файлов.

В этом вводимом тексте часто содержатся символы, неправильные для выходной кодировки, например «умные кавычки», которые приходят из документа в кодировке Windows-1252

Это вызывает проблемы, очевидно, при преобразовании или иной работе с XML, поскольку символы недопустимы.

Итак, как санировать ввод?

Ранее я использовал несколько довольно грубых методов, таких как скрипт "de-moronize" , который состоит из длинного списка операций поиска и замены.

Это все еще лучший способ сделать это? Есть ли другой путь?

Могу ли я просто установить атрибут accept-charset в форме, и браузер сделает это за меня?

Если да, то какие браузеры это сделают, и есть ли вероятность проблем?

Кроме того, почему моя база данных принимает эти символы, которые являются зарезервированными / управляющими символами в UTF-8?

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

ТИА

Ответы [ 3 ]

9 голосов
/ 15 апреля 2009

В этом вводимом тексте часто содержатся символы, неправильные для выходной кодировки, например «умные кавычки», полученные из документа в кодировке Windows-1252

«Умные кавычки» (байты 147 и 148 в cp1252) - это абсолютно допустимые символы Юникода, U + 201C и U + 201D. Ваше приложение должно быть способно обрабатывать их без проблем; если нет, вы делаете что-то не так, и, скорее всего, все символы, не входящие в ASCII, потерпят неудачу.

Независимо от того, были ли символы получены от того, кто их печатал или кто-то вставлял их из Word, браузер должен отправлять символы в кодировке UTF-8 в ваше приложение, которое должно хранить те же байты UTF-8 в базе данных.

Если браузер не отправляет в UTF-8, скорее всего, вы не можете установить кодировку HTML-страницы, содержащей форму. Это можно сделать с помощью:

Content-Type: text/html;charset=utf-8

HTTP-заголовок и / или:

<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />

элемент в .

Могу ли я просто установить атрибут accept-charset в форме и сделать так, чтобы браузер сделал это для меня?

Нет, accept-charset в принципе бесполезен благодаря IE, который неправильно интерпретирует его как «попробуйте использовать этот набор символов, если тот, что на странице не может кодировать нужные нам символы», вместо «всегда использовать этот набор символов». Это означает, что если вы используете accept-charset, вы можете получить сразу несколько кодировок, без возможности выяснить, что есть что. Nice!

почему моя база данных принимает эти символы, которые являются зарезервированными / управляющими символами в UTF-8?

В MySQL UTF-8 - это просто сопоставление, используемое для сравнения и упорядочения. Он по-прежнему хранит данные в байтах и ​​не заботится о том, что они не являются действительными последовательностями UTF-8.

В любом случае, хорошая идея декодировать и проверять входящие последовательности UTF-8 в вашем приложении, потому что «короткие последовательности», недопустимые в современном Unicode, могут скрывать символ «<», который все еще будет распознаваться старыми браузерами (по крайней мере, IE6 pre-SP2, Opera 7). </p>

ETA:

Итак, я ввел строку, содержащую байт 146

Нет, вы ввели символ Unicode U + 201B. Браузер работает с символами Unicode, а не с байтами, вплоть до момента, когда он должен отправить сериализованную форму на сервер. Тогда он решает, как превратить символы в байты, и если страница обрабатывается как UTF-8, он всегда будет выбирать UTF-8.

(Если это не UTF-8, браузеры склонны к мошенничеству нестандартным способом: для всех символов, которые не могут поместиться в кодировке, он будет кодировать их в ссылки на символы HTML, такие как '' '. Это неправильно, потому что теперь вы не можете отличить экранированную браузером '&' от реальной, & типизированной пользователем '&', и это коварно неверно, потому что если вы затем отобразите ссылку в виде неэкранированного HTML, это будет похоже на вас ' правильно, что вы на самом деле только что сделали большую старую дыру в безопасности.)

Он вошел в базу данных как 146

Действительно, байт ‘\ x92’, а не ‘\ xC2 \ x92’, ‘\ xE2 \ x80 \ x99’ или ‘’ ’?

оно появилось, когда я создал XML (в кодировке UTF-8), как 146. Никаких жалоб из браузера

Тогда это не получилось как один 146 байт. Браузер будет жаловаться, когда ему дается given \ x92 ’в файле XML. (Не HTML-файл, в котором недопустимые последовательности UTF-8 выглядят как глиф отсутствующего символа.)

Я подозреваю, что он выходит как символьная ссылка ‘’, которая хорошо сформирована (хотя символ U + 0092 является частью набора элементов управления C1, поэтому не будет отображаться как что-либо полезное). Если это то, что происходит, ваша страница формы в конце концов не воспринимается как UTF-8, и вы столкнулись с проблемой браузера-авто-экранирования-отправки, описанной выше.

2 голосов
/ 15 апреля 2009

Вы можете попробовать модуль Perl Encode . Он поддерживает преобразование между несколькими наборами символов, включая UTF-8 couse. Я только что проверил мою установку Perl, и она также поддерживала "cp1252", который является еще одним названием для Windows-1252 согласно Википедии. Вы можете проверить свою собственную установку со следующим одним вкладышем:

perl -MEncode -e 'print map {"$_\n"} Encode->encodings(":all");'
1 голос
/ 16 апреля 2009

«Могу ли я просто установить атрибут accept-charset в форме и сделать так, чтобы браузер сделал это для меня?»

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

(Также см. Предупреждения Бобинса об IE ...)

Иэн

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