Я правильно поддерживаю UTF-8 в своих приложениях PHP?

мне обычно нравится иметь двоичные файлы в базе данных потому что:

  • целостность данных: никакой не имеющий ссылки файл, никакой путь в дб без любого файла не связался
  • непротиворечивость данных: возьмите дамп базы данных, и это - все. нет "O я забыл к targz этот каталог данных".
40
задан Community 23 May 2017 в 11:46
поделиться

5 ответов

Нужно ли мне преобразовывать все, что я получаю от пользовательского агента (HTML-формы и URI), в UTF-8 при загрузке страницы

Нет. Пользовательский агент должен отправлять данные в формате UTF-8; в противном случае вы теряете преимущества Unicode.

Чтобы гарантировать, что пользовательский агент отправляет данные в формате UTF-8, нужно обслуживать страницу, содержащую форму, которую он отправляет, в кодировке UTF-8. Используйте заголовок Content-Type (и мета-http-Equiv также, если вы хотите, чтобы форма была сохранена и работала автономно).

Я слышал, что вы также должны отмечать свои формы как UTF-8 (accept-charset = "UTF -8 ")

Не надо. Это была хорошая идея в стандарте HTML, но IE так и не понял ее. Предполагалось, что в нем будет указан эксклюзивный список допустимых кодировок, но IE рассматривает его как список дополнительных кодировок, которые можно попробовать, для каждого поля. Итак, если у вас есть страница ISO-8859-1 и форма accept-charset = "UTF-8" », IE сначала попытается закодировать поле как ISO-8859-1, и если есть не-8859-1 , затем , он обратится к UTF-8.

Но поскольку IE не сообщает вам, использовал ли он ISO-8859-1 или UTF-8, это абсолютно бесполезно ты. Вам придется угадывать, какая кодировка использовалась отдельно для каждого поля! Не полезно. Опустите атрибут и обслуживайте свои страницы как UTF-8; это лучшее, что вы можете сделать на данный момент.

Если строка UTF закодирована неправильно, что-то пойдет не так

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

Слишком длинные последовательности были запрещены еще в первые дни Unicode, но для этого потребовалось Microsoft очень долго, чтобы собрать все вместе: IE интерпретировал бы последовательность байтов '\ xC0 \ xBC' как '<' до IE6 Service Pack 1. Opera также ошибалась до (примерно, я думаю) версии 7. К счастью, эти старые браузеры вымирают, но все же стоит фильтровать слишком длинные последовательности на случай, если эти браузеры все еще существуют (или новые идиотские браузеры совершат ту же ошибку в будущем). Вы можете сделать это и исправить другие неправильные последовательности с помощью регулярного выражения, которое допускает только правильные UTF-8, например , этот из W3.

Если вы используете функции mb_ в PHP, вы можете изолировать вас от этих проблем. Я не могу сказать наверняка, поскольку mb_ * был непригодным для использования и хрупким, когда я все еще писал PHP.

В любом случае, это также хорошее время для удаления управляющих символов, которые являются большим и обычно недооцененным источником ошибок. Я бы удалил символы 9 и 13 из представленной строки в дополнение к другим, которые извлекает регулярное выражение W3; также стоит удалить простые символы новой строки для строк, которые, как вы знаете, не должны быть многострочными текстовыми полями.

Был ли UTF-16 написан для устранения ограничения в UTF-8?

Нет, UTF-16 является двухбайтовым -кодовая кодировка, которая используется для упрощения индексации строк Unicode в памяти (с тех времен, когда весь Unicode умещался в двух байтах; такие системы, как Windows и Java, по-прежнему делают это так). В отличие от UTF-8 он не совместим с ASCII и практически не используется в Интернете. Но иногда вы встречаете его в сохраненных файлах, обычно в файлах, сохраненных пользователями Windows, которые были введены в заблуждение описанием Windows UTF-16LE как «Unicode» в меню «Сохранить как».

Кажется_utf8

Это очень неэффективно по сравнению с regex!

Также не забудьте использовать utf8_unicode_ci во всех ваших таблицах.

На самом деле вы можете обойтись и без этого, рассматривая MySQL как хранилище только для байтов и интерпретируя их только как UTF-8 в вашем сценарий. Преимущество использования utf8_unicode_ci заключается в том, что он будет сопоставлять (сортировать и сравнивать без учета регистра) со знаниями о символах, отличных от ASCII, поэтому, например. «ŕ» и «Ŕ» - это один и тот же символ. Если вы используете сопоставление, отличное от UTF8, вам следует придерживаться двоичного (с учетом регистра) сопоставления.

Что бы вы ни выбрали, делайте это последовательно: используйте тот же набор символов для ваших таблиц, что и для вашего соединения.

20
ответ дан 27 November 2019 в 01:56
поделиться

database / mysql: Если вы используете SET NAMES и, например, php / mysql , вы оставляете mysql_real_escape_string () в неведении об изменении в кодировке символов. Это может привести к неверным результатам. Итак, если вы полагаетесь на escape-функцию, такую ​​как mysql_real_escape_string (потому что вы не используете подготовленные операторы), SET NAMES - неоптимальное решение. Вот почему был введен mysql_set_charset () или почему gentoo применяет патч, который добавляет параметр конфигурации mysql.connect_charset как для php / mysql, так и для php / mysqli.

Обычно клиент не указывает кодировку параметров, которые он отправляет. Если вы ожидаете данные в кодировке utf-8 и обрабатываете их как таковые , могут быть ошибки кодирования (последовательности байтов, недопустимые в utf-8). Таким образом, данные могут отображаться не так, как ожидалось, или синтаксический анализатор может прервать анализ. Но, по крайней мере, пользовательский ввод не может «ускользнуть» и причинить больше вреда, например, во встроенном выражении sql или выводе HTML. Например, возьмите сценарий (сохраненный как iso-8859-1 или utf-8, не имеет значения)

<?php
$s = 'abcxyz';
var_dump(htmlspecialchars($s, ENT_QUOTES, 'utf-8'));
// adding the byte sequence for äöü in iso-8859-1
$s = 'abc'. chr(0xE4) . chr(0xF6) . chr(0xFC). 'xyz';
var_dump(htmlspecialchars($s, ENT_QUOTES, 'utf-8'));

выводит

string(6) "abcxyz"
string(0) ""

E4F6FC не является допустимой последовательностью байтов utf-8, поэтому htmlspecialchars возвращает пустую строку. Другие функции могут вернуть? или другой "особенный" характер. Но, по крайней мере, они не будут «ошибочно принимать» символ за злонамеренный управляющий символ - пока все они будут придерживаться «правильной» кодировки (в данном случае utf-8).

accept-charset не гарантирует, что вы получите данные только с этой кодировкой. Насколько вам известно, клиент, возможно, даже не "использовал" / не проанализировал ваш html-документ, содержащий элемент формы. Это может помочь, и нет причин, по которым вы не должны устанавливать этот атрибут. Но это ненадежно.

Насколько вам известно, клиент, возможно, даже не "использовал" / не проанализировал ваш html-документ, содержащий элемент формы. Это может помочь, и нет причин, по которым вы не должны устанавливать этот атрибут. Но это ненадежно.

Насколько вам известно, клиент, возможно, даже не "использовал" / не проанализировал ваш html-документ, содержащий элемент формы. Это может помочь, и нет причин, по которым вы не должны устанавливать этот атрибут. Но это ненадежно.

3
ответ дан 27 November 2019 в 01:56
поделиться

Большая часть того, что вы делаете сейчас, должно быть правильным.

Некоторые примечания: любое сопоставление utf _ * в MySQL будет правильно хранить ваши данные как UTF- 8, единственная разница между ними - это сортировка (алфавитный порядок), применяемая при сортировке.

Вы можете указать Apache и PHP, чтобы они выполнили правильную настройку заголовков кодировки AddDefaultCharset utf-8 в httpd.conf /. htaccess и default_charset = "utf-8" в php.ini соответственно.

Вы можете указать расширению mbstring позаботиться о строковых функциях. Это работает для меня:

mbstring.internal_encoding=utf-8
mbstring.http_output=UTF-8
mbstring.encoding_translation=On
mbstring.func_overload=6

(это оставляет функцию mail () нетронутой - я обнаружил, что установка ее на 7 испортила мои заголовки сообщений)

Для преобразования кодировки посмотрите https://sourceforge.net/projects/phputf8/.

PHP не делает ' меня вообще не заботит, что находится в переменной, она просто сохраняет и извлекает ее содержимое вслепую.

Вы получите неожиданные результаты, если объявите один mbstring.internal_encoding и передадите в функцию mb_ * строки в другая кодировка. В любом случае вы можете безопасно отправлять ASCII в функции utf-8.

Если вы беспокоитесь о том, что кто-то намеренно публикует неправильно закодированный материал, я думаю, вам следует подумать о HTML Purifie r для фильтрации данных GET / POST перед обработкой .

Accept-charset всегда присутствует в спецификациях, но его реальная поддержка в браузерах более или менее равна нулю. Браузер обычно использует кодировку страницы, содержащей форму.

UTF-16 не является старшим братом UTF-8, он просто служит другой цели.

он просто слепо сохраняет и извлекает свое содержимое.

Вы получите неожиданные результаты, если объявите один mbstring.internal_encoding и передадите в функцию mb_ * строки в другой кодировке. В любом случае вы можете безопасно отправлять ASCII в функции utf-8.

Если вы беспокоитесь о том, что кто-то намеренно публикует неправильно закодированный материал, я думаю, вам следует подумать о HTML Purifie r для фильтрации данных GET / POST перед обработкой .

Accept-charset всегда присутствует в спецификациях, но его реальная поддержка в браузерах более или менее нулевая. Браузер обычно использует кодировку страницы, содержащей форму.

UTF-16 не является старшим братом UTF-8, он просто служит другой цели.

он просто слепо сохраняет и извлекает свое содержимое.

Вы получите неожиданные результаты, если объявите один mbstring.internal_encoding и передадите в функцию mb_ * строки в другой кодировке. В любом случае вы можете безопасно отправлять ASCII в функции utf-8.

Если вы беспокоитесь о том, что кто-то намеренно публикует неправильно закодированный материал, я думаю, вам следует подумать о HTML Purifie r для фильтрации данных GET / POST перед обработкой .

Accept-charset всегда присутствует в спецификациях, но его реальная поддержка в браузерах более или менее нулевая. Браузер обычно использует кодировку страницы, содержащей форму.

UTF-16 не является старшим братом UTF-8, он просто служит другой цели.

internal_encoding и передать в функцию mb_ * строки в другой кодировке. В любом случае вы можете безопасно отправлять ASCII в функции utf-8.

Если вы беспокоитесь о том, что кто-то намеренно публикует неправильно закодированный материал, я думаю, вам следует подумать о HTML Purifie r для фильтрации данных GET / POST перед обработкой .

Accept-charset всегда присутствует в спецификациях, но его реальная поддержка в браузерах более или менее равна нулю. Браузер обычно использует кодировку страницы, содержащей форму.

UTF-16 не является старшим братом UTF-8, он просто служит другой цели.

internal_encoding и передать в функцию mb_ * строки в другой кодировке. В любом случае вы можете безопасно отправлять ASCII в функции utf-8.

Если вы беспокоитесь о том, что кто-то намеренно публикует неправильно закодированный материал, я думаю, вам следует подумать о HTML Purifie r для фильтрации данных GET / POST перед обработкой .

Accept-charset всегда присутствует в спецификациях, но его реальная поддержка в браузерах более или менее равна нулю. Браузер обычно использует кодировку страницы, содержащей форму.

UTF-16 не является старшим братом UTF-8, он просто служит другой цели.

меня беспокоит, что кто-то намеренно публикует неправильно закодированный материал. Я считаю, что вам следует подумать о HTML Purifie r для фильтрации данных GET / POST перед обработкой.

Accept-charset всегда был в спецификациях, но его реальная поддержка в браузерах более или менее нулевая. Браузер обычно использует кодировку страницы, содержащей форму.

UTF-16 не является старшим братом UTF-8, он просто служит другой цели.

меня беспокоит, что кто-то намеренно публикует неправильно закодированный материал. Я считаю, что вам следует подумать о HTML Purifie r для фильтрации данных GET / POST перед обработкой.

Accept-charset всегда был в спецификациях, но его реальная поддержка в браузерах более или менее нулевая. Браузер обычно использует кодировку страницы, содержащей форму.

UTF-16 не является старшим братом UTF-8, он просто служит другой цели.

11
ответ дан 27 November 2019 в 01:56
поделиться

Для пользовательского ввода из формы я добавляю этот атрибут в свои теги формы : accept-charset = "utf-8" . Таким образом, данные, которые вы получаете , всегда должны быть в кодировке utf-8.

0
ответ дан 27 November 2019 в 01:56
поделиться

UTF-8 подходит и не имеет ограничений, которые разрешает UTF-16. PHP не меняет способ хранения строк в памяти (в отличие от Python). Если весь поток данных использует UTF-8 (веб-формы получают данные UTF-8, таблицы используют кодировку utf8, и вы используете SET NAMES utf8 , и данные сохраняются без изменения (преобразование кодировки отсутствует) ), этого должно быть хорошо.

0
ответ дан 27 November 2019 в 01:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: