Ось як можна попросити санітувати файлову систему
function filter_filename($name) {
// remove illegal file system characters https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
$name = str_replace(array_merge(
array_map('chr', range(0, 31)),
array('<', '>', ':', '"', '/', '\\', '|', '?', '*')
), '', $name);
// maximise filename length to 255 bytes http://serverfault.com/a/9548/44086
$ext = pathinfo($name, PATHINFO_EXTENSION);
$name= mb_strcut(pathinfo($name, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($name)) . ($ext ? '.' . $ext : '');
return $name;
}
Все інше дозволено у файловій системі, тому на запитання ідеально відповідає ...
... але може бути небезпечним дозволити, наприклад, одинарні лапки '
у імені файлу, якщо ви будете використовувати його згодом у небезпечному контексті HTML, оскільки це абсолютно легальне ім'я файлу:
' onerror= 'alert(document.cookie).jpg
стає отвором XSS :
<img src='<? echo $image ?>' />
// output:
<img src=' ' onerror= 'alert(document.cookie)' />
Через це популярне програмне забезпечення CMS Wordpress видаляє їх, але вони охоплюють усі відповідні характеристики лише після деяких оновлень :
$special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));
// ... a few rows later are whitespaces removed as well ...
preg_replace( '/[\r\n\t -]+/', '-', $filename )
Нарешті, їхній список тепер включає більшість символів, що входять до списку захищених символів URI та URL-адрес небезпечних символів .
Звичайно, ви можете просто закодувати всі ці символи у виведенні HTML, але більшість розробників і я також дотримуйтесь ідіому «Краще безпечно, ніж вибачте» та видаліть їх заздалегідь.
Тож нарешті я б запропонував скористатися цим:
function filter_filename($filename, $beautify=true) {
// sanitize filename
$filename = preg_replace(
'~
[<>:"/\\|?*]| # file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
[\x00-\x1F]| # control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
[\x7F\xA0\xAD]| # non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
[#\[\]@!$&\'()+,;=]| # URI reserved https://tools.ietf.org/html/rfc3986#section-2.2
[{}^\~`] # URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
~x',
'-', $filename);
// avoids ".", ".." or ".hiddenFiles"
$filename = ltrim($filename, '.-');
// optional beautification
if ($beautify) $filename = beautify_filename($filename);
// maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$filename = mb_strcut(pathinfo($filename, PATHINFO_FILENAME), 0, 255 - ($ext ? strlen($ext) + 1 : 0), mb_detect_encoding($filename)) . ($ext ? '.' . $ext : '');
return $filename;
}
Все інше, що не викликає проблем з файловою системою, повинно бути частиною додаткової функції:
function beautify_filename($filename) {
// reduce consecutive characters
$filename = preg_replace(array(
// "file name.zip" becomes "file-name.zip"
'/ +/',
// "file___name.zip" becomes "file-name.zip"
'/_+/',
// "file---name.zip" becomes "file-name.zip"
'/-+/'
), '-', $filename);
$filename = preg_replace(array(
// "file--.--.-.--name.zip" becomes "file.name.zip"
'/-*\.-*/',
// "file...name..zip" becomes "file.name.zip"
'/\.{2,}/'
), '.', $filename);
// lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625
$filename = mb_strtolower($filename, mb_detect_encoding($filename));
// ".file-name.-" becomes "file-name"
$filename = trim($filename, '.-');
return $filename;
}
І в цей момент вам потрібно створити ім’я файлу, якщо результат порожній, і ви можете вирішити, чи потрібно кодувати UTF-8 символів. Але вам цього не потрібно, оскільки UTF-8 дозволений у всіх файлових системах, які використовуються в контекстах веб-хостингу.
Єдине, що вам потрібно зробити - це використовувати urlencode()
(як ви сподіваєтесь це зробити з усіма своїми URL-адресами), щоб ім'я файлу საბეჭდი_მანქანა.jpg
стало цією URL-адресою як ваша <img src>
або <a href>
:
http://www.maxrev.de/html/img/%E1%83% A1% E1% 83% 90% E1% 83% 91% E1% 83% 94% E1% 83% AD% E1% 83% 93% E1% 83% 98_% E1% 83% 9B% E1% 83% 90% E1% 83% 9C% E1% 83% A5% E1% 83% 90% E1% 83% 9C% E1% 83% 90.jpg
Stackoverflow робить це, тому я можу розмістити це посилання так, як це зробив би користувач:
http://www.maxrev.de/html/img/ საბეჭდი_მანქანა. Jpg
Отже, це повне юридичне ім'я файлу, а не проблема, як @ SequenceDigitale.com згадував у своїй відповіді .