Estoy tratando de encontrar una función que haga un buen trabajo al desinfectar ciertas cadenas para que sean seguras de usar en la URL (como un mensaje de publicación) y también seguras para usar como nombres de archivo. Por ejemplo, cuando alguien sube un archivo, quiero asegurarme de eliminar todos los caracteres peligrosos del nombre.
Hasta ahora, se me ocurrió la siguiente función, que espero resuelva este problema y también permita datos UTF-8 externos.
/**
* 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');
}
¿Alguien tiene datos de muestra difíciles con los que pueda ejecutar esto, o conozca una mejor manera de proteger nuestras aplicaciones de los malos nombres?
$ is-filename permite algunos caracteres adicionales como archivos temporales vim
actualización: eliminé el personaje estrella ya que no podía pensar en un uso válido
fuente
Respuestas:
Algunas observaciones sobre su solución:
Creando la babosa
Probablemente no debería incluir caracteres acentuados, etc. en su mensaje de publicación ya que, técnicamente, deberían estar codificados en porcentaje (según las reglas de codificación de URL) para que tenga URL de aspecto feo.
Entonces, si fuera usted, después de minúsculas, convertiría cualquier carácter 'especial' a su equivalente (por ejemplo, é -> e) y reemplazaría los caracteres que no sean [az] con '-', limitando las ejecuciones de un solo '-' como lo has hecho Hay una implementación de conversión de caracteres especiales aquí: https://web.archive.org/web/20130208144021/http://neo22s.com/slug
Desinfección en general
OWASP tiene una implementación PHP de su API de seguridad empresarial que, entre otras cosas, incluye métodos para codificar y decodificar de forma segura la entrada y salida en su aplicación.
La interfaz del codificador proporciona:
https://github.com/OWASP/PHP-ESAPI https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API
fuente
สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt
y luego creé un archivo HTML UTF-8 con un enlace. Sorprendentemente funcionó, ¡incluso en Windows! Sin embargo, luego tuve PHPfile_put_contents('สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt')
y no se pudo crear un nombre de archivo de bazar a partir de esa cadena. Luego intenté crearlofopen()
y obtuve el mismo nombre de archivo desordenado. Entonces, aparentemente PHP (al menos en Windows) es incapaz de crear nombres de archivo UTF-8. bugs.php.net/bug.php?id=46990&thanks=6Encontré esta función más grande en el código Chyrp :
y este en el código de wordpress
Actualización de septiembre de 2012
Alix Axel ha hecho un trabajo increíble en esta área. Su marco de funciones incluye varios filtros de texto y transformaciones excelentes.
fuente
apply_filters
/[\s-]+/
con la-
que es mejor que la primera versión (que reemplaza solo/\s+/
) que puede causar múltiples guiones seguidosEsto debería hacer que sus nombres de archivo sean seguros ...
y una solución más profunda a esto es:
Esto supone que desea un punto en el nombre del archivo. si quieres transferirlo a minúsculas, solo usa
para la última línea
fuente
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Prueba esto:
Basado en la respuesta seleccionada en este hilo: ¿ Nombre de usuario amigable de URL en PHP?
fuente
trim()
también debería estarlotrim($string, '-')
.preg_replace()
debería eliminar todos los caracteres peligrosos.Esto no es exactamente una respuesta, ya que no proporciona ninguna solución (¡todavía!), Pero es demasiado grande para caber en un comentario ...
Hice algunas pruebas (con respecto a los nombres de archivo) en Windows 7 y Ubuntu 12.04 y lo que descubrí fue que:
1. PHP no puede manejar nombres de archivos no ASCII
Aunque tanto Windows como Ubuntu pueden manejar nombres de archivos Unicode (incluso RTL como parece) PHP 5.3 requiere hacks para tratar incluso con el viejo ISO-8859-1, por lo que es mejor mantenerlo ASCII solo por seguridad.
2. La longitud de los asuntos de nombre de archivo (especialmente en Windows)
En Ubuntu, la longitud máxima que puede tener un nombre de archivo (incluida la extensión) es 255 (sin incluir la ruta):
Sin embargo, en Windows 7 (NTFS) la longitud máxima que puede tener un nombre de archivo depende de su ruta absoluta:
Wikipedia dice que:
A lo mejor de mi conocimiento (y pruebas), esto está mal.
En total (contando barras) todos estos ejemplos tienen 259 caracteres, si quitas el
C:\
que da 256 caracteres (¡¿no 255 ?!). Los directorios se crearon usando el Explorador y notará que se limita a usar todo el espacio disponible para el nombre del directorio. La razón de esto es permitir la creación de archivos usando la convención de nomenclatura de archivos 8.3 . Lo mismo sucede con otras particiones.Los archivos no necesitan reservar los requisitos de longitud 8.3, por supuesto:
No puede crear más subdirectorios si la ruta absoluta del directorio principal tiene más de 242 caracteres, porque
256 = 242 + 1 + \ + 8 + . + 3
. Con el Explorador de Windows, no puede crear otro directorio si el directorio principal tiene más de 233 caracteres (según la configuración regional del sistema), porque256 = 233 + 10 + \ + 8 + . + 3
; el10
aquí es la longitud de la cadenaNew folder
.El sistema de archivos de Windows plantea un problema desagradable si desea garantizar la interoperabilidad entre los sistemas de archivos.
3. Cuidado con los caracteres reservados y las palabras clave
Además de eliminar caracteres no ASCII, no imprimibles y de control , también debe volver a colocar (colocar / mover):
Simplemente eliminar estos caracteres podría no ser la mejor idea porque el nombre de archivo podría perder parte de su significado. Creo que, al menos, las ocurrencias múltiples de estos caracteres deberían reemplazarse por un solo guión bajo (
_
), o tal vez algo más representativo (esto es solo una idea):"*?
->_
/\|
->-
:
->[ ]-[ ]
<
->(
>
->)
También hay palabras clave especiales que deben evitarse (como
NUL
), aunque no estoy seguro de cómo superar eso. Quizás una lista negra con un nombre aleatorio alternativo sería un buen enfoque para resolverlo.4. Sensibilidad a mayúsculas y minúsculas
Esto debería ser evidente, pero si lo desea, asegúrese de que el archivo sea único en los diferentes sistemas operativos, debe transformar los nombres de los archivos en un caso normalizado, de esa manera
my_file.txt
yMy_File.txt
en Linux no se convertirá en el mismomy_file.txt
archivo en Windows.5. Asegúrese de que sea único
Si el nombre del archivo ya existe, se debe agregar un identificador único a su nombre de archivo base.
Los identificadores únicos comunes incluyen la marca de tiempo UNIX, un resumen del contenido del archivo o una cadena aleatoria.
6. archivos ocultos
El hecho de que se pueda nombrar no significa que deba ...
Los puntos suelen aparecer en la lista blanca en los nombres de archivo, pero en Linux un archivo oculto está representado por un punto inicial.
7. Otras consideraciones
Si tiene que quitar algunos caracteres del nombre del archivo, la extensión suele ser más importante que el nombre base del archivo. Al permitir un número máximo considerable de caracteres para la extensión del archivo (8-16), se deben quitar los caracteres del nombre base. También es importante tener en cuenta que, en el caso improbable de tener más de una extensión larga, como por ejemplo
_.graphmlz.tag.gz
,_.graphmlz.tag
solo_
debe considerarse como el nombre base del archivo en este caso.8. Recursos
Calibre maneja el nombre del archivo de manera bastante decente:
Página de Wikipedia sobre el cambio de nombre de archivo y el capítulo vinculado de Uso de Samba .
Si, por ejemplo, intenta crear un archivo que infringe alguna de las reglas 1/2/3, obtendrá un error muy útil:
fuente
Siempre pensé que Kohana hizo un buen trabajo .
Los prácticos
UTF8::transliterate_to_ascii()
convertirán cosas como ñ => n.Por supuesto, podría reemplazar las otras
UTF8::*
cosas con funciones mb_ *.fuente
En términos de carga de archivos, sería más seguro evitar que el usuario controle el nombre del archivo. Como ya se ha insinuado, almacene el nombre de archivo canonicalizado en una base de datos junto con un nombre elegido aleatoriamente y único que usará como el nombre de archivo real.
Usando OWASP ESAPI, estos nombres podrían generarse así:
Puede agregar una marca de tiempo al $ safeFilename para ayudar a garantizar que el nombre de archivo generado aleatoriamente sea único sin siquiera buscar un archivo existente.
En términos de codificación para URL, y nuevamente usando ESAPI:
Este método realiza la canonicalización antes de codificar la cadena y manejará todas las codificaciones de caracteres.
fuente
Recomiendo * URLify para PHP (480+ estrellas en Github) - "el puerto PHP de URLify.js del proyecto Django. Translitera caracteres no ascii para usar en URL".
Uso básico:
Para generar babosas para URL:
Para generar babosas para nombres de archivo:
* Ninguna de las otras sugerencias coincide con mis criterios:
Como beneficio adicional, URLify también elimina ciertas palabras y elimina todos los caracteres no transcritos.
Aquí hay un caso de prueba con toneladas de caracteres extranjeros que se transcriben correctamente usando URLify: https://gist.github.com/motin/a65e6c1cc303e46900d10894bf2da87f
fuente
Me he adaptado de otra fuente y agregué un par extra, tal vez un poco exagerado
fuente
y esta es la versión Joomla 3.3.2 de
JFile::makeSafe($file)
fuente
No creo que sea seguro tener una lista de caracteres para eliminar. Prefiero usar lo siguiente:
Para nombres de archivo: use una ID interna o un hash del contenido del archivo. Guarde el nombre del documento en una base de datos. De esta manera, puede mantener el nombre de archivo original y aún encontrar el archivo.
Para parámetros de URL: se utiliza
urlencode()
para codificar caracteres especiales.fuente
Dependiendo de cómo lo use, es posible que desee agregar un límite de longitud para proteger contra desbordamientos del búfer.
fuente
Esta es una buena manera de asegurar un nombre de archivo de carga:
fuente
.\x00..\x20
puede reducirse a.\x00\x20
..\x00..\x20
elimina puntos y todos los caracteres entre\x00
y\x20
, mientras.\x00\x20
que solo debería eliminar esos 3 bytes.Aquí está la implementación de CodeIgniter.
Y la
remove_invisible_characters
dependencia.fuente
¿por qué no simplemente usar php's
urlencode
? reemplaza caracteres "peligrosos" con su representación hexadecimal para urls (es decir,%20
para un espacio)fuente
Ya hay varias soluciones proporcionadas para esta pregunta, pero he leído y probado la mayor parte del código aquí y terminé con esta solución, que es una mezcla de lo que aprendí aquí:
La función
La función se incluye aquí en un paquete de Symfony2 pero se puede extraer para usar como PHP simple , solo tiene una dependencia con la
iconv
función que debe habilitarse:Filesystem.php :
Las pruebas unitarias
Lo interesante es que he creado pruebas PHPUnit, primero para probar casos extremos y para que pueda verificar si se ajusta a sus necesidades: (Si encuentra un error, no dude en agregar un caso de prueba)
FilesystemTest.php :
Los resultados de la prueba: (comprobado en Ubuntu con PHP 5.3.2 y MacOsX con PHP 5.3.17:
fuente
Tengo títulos de entrada con todo tipo de caracteres latinos extraños, así como algunas etiquetas HTML que necesitaba traducir a un útil formato de nombre de archivo delimitado por guiones. Combiné la respuesta de @ SoLoGHoST con un par de elementos de la respuesta de @ Xeoncross y lo personalicé un poco.
Necesitaba agregar manualmente el carácter del guión em (-) a la matriz de traducción. Puede haber otros, pero hasta ahora mis nombres de archivo se ven bien.
Entonces:
Parte 1: ¿Los "Žurburts" de mi papá? ¡No son los mejores!
se convierte en:
parte-1-mis-papás-zurburts-ellos-no-son-los-mejores
Solo agrego ".html" a la cadena devuelta.
fuente
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
$string = transliterator_transliterate('Any-Latin;Latin-ASCII;', $string);
vea mi respuesta a continuación o lea la publicación de blog vinculada.Solución n. ° 1: tiene la capacidad de instalar extensiones PHP en el servidor (hosting)
Para la transcripción de "casi todos los idiomas del planeta Tierra" a caracteres ASCII.
Instale la extensión PHP Intl primero. Este es el comando para Debian (Ubuntu):
sudo aptitude install php5-intl
Esta es mi función fileName (crea test.php y pega el siguiente código):
Esta línea es central:
Respuesta basada en esta publicación .
Solución # 2: No tiene la capacidad de instalar extensiones PHP en el servidor (hosting)
Se realiza un trabajo bastante bueno en el módulo de transliteración para CMS Drupal. Es compatible con casi todos los idiomas del planeta Tierra. Sugiero que revise el repositorio de complementos si desea tener una solución realmente completa para la limpieza de las cadenas.
fuente
Esta publicación parece funcionar mejor entre todos los que he vinculado. http://gsynuh.com/php-string-filename-url-safe/205
fuente
Esta es una buena función:
fuente
\\s+
significa una barra invertida seguida de uno o más espacios en blanco. ¿De qué se trata eso? Además, esto usa listas negras en lugar de listas blancas ignorando cosas comoCMD
, nulo oBEL
./blog/2014-02/just-in-time
no están permitidas. Utilice el código probado anteriormente o utilice elphunction
código de marco PHP.preg_replace('~[^\-\pL\pN\s]+~u', '-', $string)
Este es el código utilizado por Prestashop para desinfectar las URL:
es utilizado por
para eliminar diacríticos
fuente
Hay 2 buenas respuestas para usar slugfy sus datos, úselos https://stackoverflow.com/a/3987966/971619 o https://stackoverflow.com/a/7610586/971619
fuente
fuente