Voici comment vous pouvez nettoyer un système de fichiers comme demandé
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;
}
Tout le reste est autorisé dans un système de fichiers, donc la question est parfaitement répondue ...
... mais il pourrait être dangereux d'autoriser, par exemple, des guillemets simples '
dans un nom de fichier si vous l'utilisez plus tard dans un contexte HTML dangereux car ce nom de fichier absolument légal:
' onerror= 'alert(document.cookie).jpg
devient un trou XSS :
<img src='<? echo $image ?>' />
// output:
<img src=' ' onerror= 'alert(document.cookie)' />
Pour cette raison, le logiciel CMS populaire Wordpress les supprime, mais ils ne couvrent tous les caractères pertinents qu'après quelques mises à jour :
$special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));
// ... a few rows later are whitespaces removed as well ...
preg_replace( '/[\r\n\t -]+/', '-', $filename )
Enfin leur liste inclut désormais la plupart des personnages qui font partie de l' URI rerserved-caractères et URL caractères dangereux liste.
Bien sûr, vous pouvez simplement encoder tous ces caractères sur la sortie HTML, mais la plupart des développeurs et moi aussi, suivons l'idiome "Mieux vaut prévenir que guérir" et les supprimer à l'avance.
Alors enfin, je suggérerais d'utiliser ceci:
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;
}
Tout le reste qui ne pose pas de problème avec le système de fichiers doit faire partie d'une fonction supplémentaire:
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;
}
Et à ce stade, vous devez générer un nom de fichier si le résultat est vide et vous pouvez décider si vous souhaitez encoder des caractères UTF-8. Mais vous n'en avez pas besoin car UTF-8 est autorisé dans tous les systèmes de fichiers utilisés dans les contextes d'hébergement Web.
La seule chose que vous devez faire est d'utiliser urlencode()
(comme vous le faites avec toutes vos URL) afin que le nom de fichier საბეჭდი_მანქანა.jpg
devienne cette URL en tant que votre <img src>
ou <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 fait cela, donc je peux publier ce lien comme le ferait un utilisateur:
http://www.maxrev.de/html/img/ საბეჭდი_მანქანა. Jpg
C'est donc un nom de fichier légal complet et pas un problème comme @ SequenceDigitale.com l'a mentionné dans sa réponse .