Я пытаюсь придумать функцию, которая хорошо выполняет очистку определенных строк, чтобы их можно было безопасно использовать в URL (например, после публикации), а также безопасно использовать в качестве имен файлов. Например, когда кто-то загружает файл, я хочу убедиться, что я удаляю все опасные символы из имени.
До сих пор я придумал следующую функцию, которая, я надеюсь, решает эту проблему и позволяет также использовать сторонние данные UTF-8.
/**
* Convert a string to the file/URL safe "slug" form
*
* @param string $string the string to clean
* @param bool $is_filename TRUE will allow additional filename characters
* @return string
*/
function sanitize($string = '', $is_filename = FALSE)
{
// Replace all weird characters with dashes
$string = preg_replace('/[^\w\-'. ($is_filename ? '~_\.' : ''). ']+/u', '-', $string);
// Only allow one dash separator at a time (and make string lowercase)
return mb_strtolower(preg_replace('/--+/u', '-', $string), 'UTF-8');
}
У кого-нибудь есть какие-нибудь хитрые образцы данных, которые я могу использовать против этого, или знаете, как лучше защитить наши приложения от дурных имен?
$ is-filename позволяет использовать некоторые дополнительные символы, такие как временные файлы vim
обновление: убрал символ звезды, так как я не мог придумать правильное использование
источник
Ответы:
Некоторые замечания по вашему решению:
Создание слизняка
Вы, вероятно, не должны включать акцентированные и т. Д. Символы в свой пост-пост, поскольку технически они должны быть закодированы в процентах (согласно правилам кодирования URL), чтобы у вас были уродливые URL.
Таким образом, на вашем месте я бы после преобразования в нижний регистр преобразовал бы любые «специальные» символы в их эквивалент (например, é -> e) и заменил бы не [az] символы на «-», ограничиваясь запусками одного «-» как ты сделал. Здесь есть реализация преобразования специальных символов: https://web.archive.org/web/20130208144021/http://neo22s.com/slug
Санитарная обработка в целом
У OWASP есть реализация PHP их Enterprise Security API на PHP, которая, среди прочего, включает методы для безопасного кодирования и декодирования ввода и вывода в вашем приложении.
Интерфейс Encoder обеспечивает:
https://github.com/OWASP/PHP-ESAPI https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API
источник
สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt
а затем создал HTML-файл UTF-8 со ссылкой на него. Удивительно, но это сработало - даже на окнах! Однако у меня тогда был PHP,file_put_contents('สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt')
и он не смог создать имя файла базара из этой строки. Затем я попытался создать егоfopen()
и получил то же испорченное имя файла. Таким образом, очевидно, что PHP (по крайней мере для Windows) не способен создавать имена файлов UTF-8. bugs.php.net/bug.php?id=46990&thanks=6Я нашел эту большую функцию в коде Chyrp :
и этот в коде WordPress
Обновление сентябрь 2012
Аликс Аксель проделал невероятную работу в этой области. Его функциональная структура включает в себя несколько отличных текстовых фильтров и преобразований.
источник
apply_filters
/[\s-]+/
с-
которой лучше , чем первая версия (которая заменяет только/\s+/
) , что может привести к несколько тире подрядЭто должно сделать ваши имена файлов безопасными ...
и более глубокое решение этого:
Это предполагает, что вы хотите точку в имени файла. если вы хотите перевести его в нижний регистр, просто используйте
для последней строки.
источник
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Попробуй это:
На основании выбранного ответа в этой теме: URL Friendly Username в PHP?
источник
trim()
должно бытьtrim($string, '-')
.preg_replace()
должен удалить все опасные символы.Это не совсем ответ, так как он не дает никаких решений (пока!), Но он слишком велик, чтобы поместиться в комментарии ...
Я провел некоторое тестирование (относительно имен файлов) на Windows 7 и Ubuntu 12.04, и выяснил, что:
1. PHP не может обрабатывать не-ASCII имена файлов
Хотя и Windows, и Ubuntu могут обрабатывать имена файлов Unicode (даже RTL, как кажется), PHP 5.3 требует хаков, чтобы иметь дело даже с простым старым ISO-8859-1, поэтому лучше сохранить его в ASCII только для безопасности.
2. Длина имени файла имеет значение (особенно в Windows)
В Ubuntu максимальная длина имени файла (включая расширение) составляет 255 (без пути):
Однако в Windows 7 (NTFS) максимальная длина имени файла зависит от его абсолютного пути:
Википедия говорит, что:
Насколько мне известно (и тестирование), это неправильно.
В целом (с учетом слеша) все эти примеры имеют 259 символов, если вы
C:\
удалите символ, который дает 256 символов (не 255 ?!). Каталоги были созданы с помощью Проводника, и вы заметите, что он ограничивает себя в использовании всего доступного пространства для имени каталога. Причина этого заключается в том, чтобы разрешить создание файлов с использованием соглашения о присвоении имен 8.3 . То же самое происходит с другими разделами.Файлы не должны резервировать требования 8,3 длины, конечно:
Вы не можете создавать больше подкаталогов, если абсолютный путь родительского каталога содержит более 242 символов, потому что
256 = 242 + 1 + \ + 8 + . + 3
. Используя Windows Explorer, вы не можете создать другой каталог, если родительский каталог содержит более 233 символов (в зависимости от локали системы), потому что256 = 233 + 10 + \ + 8 + . + 3
;10
здесь длина строкиNew folder
.Файловая система Windows представляет собой неприятную проблему, если вы хотите обеспечить взаимодействие между файловыми системами.
3. Остерегайтесь зарезервированных символов и ключевых слов.
Помимо удаления не ASCII, непечатных и управляющих символов , вам также необходимо повторно (поместить / переместить):
Удаление этих символов может быть не самой лучшей идеей, поскольку имя файла может потерять часть своего значения. Я думаю, что, по крайней мере, множественные вхождения этих символов должны быть заменены одним подчеркиванием (
_
) или, возможно, чем-то более представительным (это всего лишь идея):"*?
->_
/\|
->-
:
->[ ]-[ ]
<
->(
>
->)
Есть также специальные ключевые слова, которых следует избегать (например
NUL
), хотя я не уверен, как это преодолеть. Возможно, черный список со случайным резервным именем был бы хорошим подходом для его решения.4. Чувствительность к регистру
Это должно быть само собой разумеющимся, но если вы хотите обеспечить уникальность файлов в разных операционных системах, вам следует преобразовать имена файлов в нормализованный регистр, таким образом
my_file.txt
иMy_File.txt
в Linux оба не станут одним и тем жеmy_file.txt
файлом в Windows.5. Убедитесь, что это уникально
Если имя файла уже существует, к его базовому имени файла должен быть добавлен уникальный идентификатор .
Общие уникальные идентификаторы включают метку времени UNIX, дайджест содержимого файла или случайную строку.
6. Скрытые файлы
То, что его можно назвать, не значит, что оно должно ...
Точки, как правило, заносятся в белый список в именах файлов, но в Linux скрытый файл представлен лидирующей точкой.
7. Другие соображения
Если вам нужно удалить несколько символов имени файла, расширение обычно более важно, чем базовое имя файла. Допуская значительное максимальное количество символов для расширения файла (8-16), следует удалить символы из базового имени. Важно также отметить , что в маловероятном случае наличия более чем один длинное расширения - такие , как
_.graphmlz.tag.gz
-_.graphmlz.tag
только_
следует рассматривать в качестве базового имени файла в этом случае.8. Ресурсы
Калибр обрабатывает искажение имени файла довольно прилично:
Страница Википедии по искажению имени файла и связанная с ним глава из Использование Samba .
Например, если вы попытаетесь создать файл, который нарушает любое из правил 1/2/3, вы получите очень полезную ошибку:
источник
Я всегда думал, что Кохана справилась с этим довольно хорошо .
Удобный
UTF8::transliterate_to_ascii()
превратит вещи, как ñ => n.Конечно, вы могли бы заменить другие
UTF8::*
вещи функциями mb_ *.источник
С точки зрения загрузки файлов вам будет безопаснее запретить пользователю контролировать имя файла. Как уже упоминалось, сохраните канонизированное имя файла в базе данных вместе со случайно выбранным и уникальным именем, которое вы будете использовать в качестве фактического имени файла.
Используя OWASP ESAPI, эти имена могут быть сгенерированы следующим образом:
Вы можете добавить метку времени к $ safeFilename, чтобы убедиться, что случайно сгенерированное имя файла уникально, даже не проверяя существующий файл.
С точки зрения кодирования для URL, и снова с помощью ESAPI:
Этот метод выполняет канонизацию перед кодированием строки и будет обрабатывать все кодировки символов.
источник
Я рекомендую * URLify для PHP (480+ звезд на Github) - «PHP-порт URLify.js из проекта Django. Транслитерирует не-ascii символы для использования в URL».
Основное использование:
Чтобы создать слаг для URL:
Чтобы создать слаг для имен файлов:
* Ни одно из других предложений не соответствовало моим критериям:
В качестве бонуса URLify также удаляет определенные слова и удаляет все символы, не транслитерированные.
Вот тестовый пример с тоннами иностранных символов, которые правильно транслитерируются с помощью URLify: https://gist.github.com/motin/a65e6c1cc303e46900d10894bf2da87f
источник
Я адаптировался из другого источника и добавил пару дополнительных, может быть, немного излишним
источник
и это версия Joomla 3.3.2 из
JFile::makeSafe($file)
источник
Я не думаю, что иметь список символов для удаления безопасно. Я бы предпочел использовать следующее:
Для имен файлов: используйте внутренний идентификатор или хеш содержимого файла. Сохраните название документа в базе данных. Таким образом, вы можете сохранить исходное имя файла и все же найти файл.
Для параметров URL: используйте
urlencode()
для кодирования любых специальных символов.источник
В зависимости от того, как вы будете его использовать, вы можете добавить ограничение длины для защиты от переполнения буфера.
источник
Это хороший способ обеспечить загрузку имени файла:
источник
.\x00..\x20
может быть уменьшен до.\x00\x20
..\x00..\x20
удаляет точки и каждый символ между\x00
и\x20
, тогда как.\x00\x20
следует удалять только эти 3 байта.Вот реализация CodeIgniter.
И
remove_invisible_characters
зависимость.источник
почему бы просто не использовать php
urlencode
? он заменяет «опасные» символы их шестнадцатеричным представлением для URL (то есть%20
для пробела)источник
Для этого вопроса уже предусмотрено несколько решений, но я прочитал и протестировал большую часть кода здесь, и в итоге я получил это решение, представляющее собой смесь того, что я узнал здесь:
Функция
Здесь функция упакована в пакет Symfony2, но ее можно извлечь для использования в качестве простого PHP , она зависит только от
iconv
функции, которая должна быть включена:Filesystem.php :
Юнит тесты
Что интересно, я создал тесты PHPUnit, сначала для тестирования крайних случаев, и поэтому вы можете проверить, соответствует ли он вашим потребностям: (Если вы обнаружите ошибку, не стесняйтесь добавлять тестовый пример)
FilesystemTest.php :
Результаты теста: (проверено на Ubuntu с PHP 5.3.2 и MacOsX с PHP 5.3.17:
источник
У меня есть заголовки со всеми видами странных латинских символов, а также некоторые теги HTML, которые мне нужно было перевести в полезный формат имени файла с разделителями-тире. Я объединил ответ @ SoLoGHoST с парой пунктов из ответа @ Xeoncross и немного настроил его.
Мне нужно было вручную добавить символ тире (-) в массив перевода. Могут быть и другие, но пока мои имена файлов выглядят хорошо.
Так:
Часть 1: «Žurburts» моего отца? - они (не) лучшие!
будет выглядеть так:
часть-1-мой-пап-zurburts-Theyre-не-лучший
Я просто добавляю ".html" в возвращаемую строку.
источник
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
$string = transliterator_transliterate('Any-Latin;Latin-ASCII;', $string);
см. Мой ответ ниже или прочитайте связанный пост в блоге.Решение № 1: У вас есть возможность установить расширения PHP на сервере (хостинг)
Для транслитерации «почти каждого языка на планете Земля» в символы ASCII.
Сначала установите расширение PHP Intl . Это команда для Debian (Ubuntu):
sudo aptitude install php5-intl
Это моя функция fileName (создайте test.php и вставьте туда следующий код):
Эта строка является основной:
Ответ основан на этом посте .
Решение № 2: У вас нет возможности установить расширения PHP на сервере (хостинг)
Довольно хорошая работа проделана в модуле транслитерации для CMS Drupal. Он поддерживает почти каждый язык на планете Земля. Я предлагаю проверить хранилище плагинов, если вы хотите иметь действительно законченное решение для очистки строк.
источник
Этот пост, кажется, работает лучше всего из всех, что я связал. http://gsynuh.com/php-string-filename-url-safe/205
источник
Это хорошая функция:
источник
\\s+
означает обратную косую черту, за которой следует один или несколько пробелов. О чем это? Кроме того, он использует черный список, а не белый, игнорируя такие вещи, какCMD
, ноль илиBEL
./blog/2014-02/just-in-time
не допускаются. Пожалуйста, используйте проверенный код выше или используйтеphunction
код фреймворка PHP.preg_replace('~[^\-\pL\pN\s]+~u', '-', $string)
Это код, используемый Prestashop для очистки URL:
используется
убрать диакритические знаки
источник
Есть 2 хороших ответа, чтобы убить ваши данные, используйте их https://stackoverflow.com/a/3987966/971619 или https://stackoverflow.com/a/7610586/971619
источник
источник