Así es como puede desinfectar un sistema de archivos como se le pide
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;
}
Todo lo demás está permitido en un sistema de archivos, por lo que la pregunta está perfectamente respondida ...
... pero podría ser peligroso permitir, por ejemplo, comillas simples '
en un nombre de archivo si lo usa más tarde en un contexto HTML inseguro porque este nombre de archivo absolutamente legal:
' onerror= 'alert(document.cookie).jpg
se convierte en un agujero XSS :
<img src='<? echo $image ?>' />
// output:
<img src=' ' onerror= 'alert(document.cookie)' />
Por eso, el popular software CMS Wordpress los elimina, pero cubrieron todos los caracteres relevantes solo después de algunas actualizaciones :
$special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));
// ... a few rows later are whitespaces removed as well ...
preg_replace( '/[\r\n\t -]+/', '-', $filename )
Finalmente su lista incluye ahora la mayoría de los personajes que forman parte de la URI rerserved caracteres y URL personajes inseguros lista.
Por supuesto, podría simplemente codificar todos estos caracteres en la salida HTML, pero la mayoría de los desarrolladores y yo también, seguimos el modismo "Más vale prevenir que curar" y eliminarlos de antemano.
Entonces, finalmente, sugeriría usar esto:
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;
}
Todo lo demás que no cause problemas con el sistema de archivos debe ser parte de una función adicional:
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;
}
Y en este punto, debe generar un nombre de archivo si el resultado está vacío y puede decidir si desea codificar caracteres UTF-8. Pero no lo necesita, ya que UTF-8 está permitido en todos los sistemas de archivos que se utilizan en contextos de alojamiento web.
Lo único que tiene que hacer es usar urlencode()
(como con suerte lo hace con todas sus URL) para que el nombre del archivo se საბეჭდი_მანქანა.jpg
convierta en esta URL como su <img src>
o <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 hace eso, así que puedo publicar este enlace como lo haría un usuario:
http://www.maxrev.de/html/img/ საბეჭდი_მანქანა. Jpg
Así que este es un nombre de archivo legal completo y no es un problema como @ SequenceDigitale.com mencionó en su respuesta .