J'essaie de trouver une fonction qui nettoie bien certaines chaînes afin qu'elles soient sûres à utiliser dans l'URL (comme un slug de publication) et également sûres à utiliser comme noms de fichiers. Par exemple, lorsque quelqu'un télécharge un fichier, je veux m'assurer que je supprime tous les caractères dangereux du nom.
Jusqu'à présent, j'ai proposé la fonction suivante qui, je l'espère, résout ce problème et autorise également les données UTF-8 étrangères.
/**
* 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');
}
Quelqu'un a-t-il des exemples de données délicates que je peux utiliser - ou connaît-il un meilleur moyen de protéger nos applications contre les mauvais noms?
$ is-filename autorise certains caractères supplémentaires comme les fichiers vim temporaires
mise à jour: supprimé le caractère étoile car je ne pouvais pas penser à une utilisation valide
la source
Réponses:
Quelques observations sur votre solution:
Création de la limace
Vous ne devriez probablement pas inclure de caractères accentués, etc. dans votre slug de publication car, techniquement, ils devraient être codés en pourcentage (selon les règles de codage d'URL) afin que vous ayez des URL qui semblent laides.
Donc, si j'étais vous, après la mise en minuscules, je convertirais tous les caractères «spéciaux» en leur équivalent (par exemple é -> e) et remplacerais les caractères non [az] par «-», en se limitant aux exécutions d'un seul «-» comme vous l'avez fait. Il existe une implémentation de la conversion des caractères spéciaux ici: https://web.archive.org/web/20130208144021/http://neo22s.com/slug
Désinfection en général
OWASP dispose d'une implémentation PHP de son API de sécurité d'entreprise qui comprend entre autres des méthodes d'encodage et de décodage sécurisés des entrées et des sorties dans votre application.
L'interface de l'encodeur fournit:
https://github.com/OWASP/PHP-ESAPI https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API
la source
สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt
puis créé un fichier HTML UTF-8 avec un lien vers celui-ci. Étonnamment, cela a fonctionné - même sous Windows! Cependant, j'ai alors eu PHPfile_put_contents('สังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่.txt')
et cela n'a pas réussi à créer un nom de fichier bazar à partir de cette chaîne. Ensuite, j'ai essayé de le créer avecfopen()
et j'ai obtenu le même nom de fichier foiré. Donc apparemment, PHP (au moins sous Windows) est incapable de créer des noms de fichiers UTF-8. bugs.php.net/bug.php?id=46990&thanks=6J'ai trouvé cette fonction plus large dans le code Chyrp :
et celui-ci dans le code wordpress
Mise à jour septembre 2012
Alix Axel a fait un travail incroyable dans ce domaine. Son cadre de fonction comprend plusieurs excellents filtres de texte et transformations.
la source
apply_filters
/[\s-]+/
par-
qui est mieux que la première version (qui remplace uniquement/\s+/
) qui peut provoquer plusieurs tirets d'affiléeCela devrait sécuriser vos noms de fichiers ...
et une solution plus profonde à cela est:
Cela suppose que vous souhaitiez un point dans le nom de fichier. si vous voulez qu'il soit transféré en minuscules, utilisez simplement
pour la dernière ligne.
la source
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
Essaye ça:
Basé sur la réponse sélectionnée dans ce fil: Nom d'utilisateur URL convivial en PHP?
la source
trim()
devrait aussi l'êtretrim($string, '-')
.preg_replace()
devrait supprimer tous les caractères dangereux.Ce n'est pas exactement une réponse car cela ne fournit aucune solution (encore!), Mais c'est trop gros pour tenir sur un commentaire ...
J'ai fait quelques tests (concernant les noms de fichiers) sur Windows 7 et Ubuntu 12.04 et j'ai découvert que:
1. PHP ne peut pas gérer les noms de fichiers non ASCII
Bien que Windows et Ubuntu puissent gérer les noms de fichiers Unicode (même ceux RTL, semble-t-il), PHP 5.3 nécessite des hacks pour gérer même l'ancien ISO-8859-1, il est donc préférable de le garder ASCII uniquement pour la sécurité.
2. La longueur du nom de fichier est importante (spécialement sous Windows)
Sur Ubuntu, la longueur maximale d'un nom de fichier (y compris l'extension de liaison) est de 255 (hors chemin):
Cependant, sous Windows 7 (NTFS), la longueur maximale qu'un nom de fichier peut avoir dépend de son chemin absolu:
Wikipédia dit que:
Au meilleur de ma connaissance (et de mes tests), c'est faux.
Au total (en comptant les barres obliques), tous ces exemples ont 259 caractères, si vous supprimez le,
C:\
cela donne 256 caractères (et non 255?!). Les répertoires ont été créés à l'aide de l'explorateur et vous remarquerez qu'il s'interdit d'utiliser tout l'espace disponible pour le nom du répertoire. La raison en est de permettre la création de fichiers en utilisant la convention de dénomination de fichier 8.3 . La même chose se produit pour les autres partitions.Les fichiers n'ont pas besoin de réserver les exigences de longueur 8.3 bien sûr:
Vous ne pouvez plus créer de sous-répertoires si le chemin absolu du répertoire parent contient plus de 242 caractères, car
256 = 242 + 1 + \ + 8 + . + 3
. À l'aide de l'Explorateur Windows, vous ne pouvez pas créer un autre répertoire si le répertoire parent contient plus de 233 caractères (selon les paramètres régionaux du système), car256 = 233 + 10 + \ + 8 + . + 3
; le10
voici la longueur de la chaîneNew folder
.Le système de fichiers Windows pose un problème désagréable si vous souhaitez assurer l'interopérabilité entre les systèmes de fichiers.
3. Méfiez-vous des caractères et mots-clés réservés
En plus de supprimer les caractères non-ASCII, non imprimables et de contrôle , vous devez également re (placer / déplacer):
Le simple fait de supprimer ces caractères n'est peut-être pas la meilleure idée car le nom de fichier risque de perdre une partie de sa signification. Je pense que, à tout le moins, plusieurs occurrences de ces caractères devraient être remplacées par un seul trait de soulignement (
_
), ou peut-être quelque chose de plus représentatif (ce n'est qu'une idée):"*?
->_
/\|
->-
:
->[ ]-[ ]
<
->(
>
->)
Il y a aussi des mots-clés spéciaux qui devraient être évités (comme
NUL
), même si je ne sais pas comment surmonter cela. Peut-être qu'une liste noire avec un nom de secours aléatoire serait une bonne approche pour le résoudre.4. Sensibilité aux cas
Cela devrait aller de soi, mais si vous voulez assurer l'unicité des fichiers sur différents systèmes d'exploitation, vous devez transformer les noms de fichiers en cas normalisés, de cette façon
my_file.txt
etMy_File.txt
sous Linux ne deviendront pas les deuxmy_file.txt
fichier sous Windows.5. Assurez-vous qu'il est unique
Si le nom de fichier existe déjà, un identifiant unique doit être ajouté à son nom de fichier de base.
Les identificateurs uniques communs incluent l'horodatage UNIX, un résumé du contenu du fichier ou une chaîne aléatoire.
6. Fichiers cachés
Ce n'est pas parce qu'il peut être nommé qu'il devrait ...
Les points sont généralement listés en blanc dans les noms de fichiers, mais sous Linux, un fichier caché est représenté par un point au début.
7. Autres considérations
Si vous devez supprimer certains caractères du nom de fichier, l'extension est généralement plus importante que le nom de base du fichier. En autorisant un nombre maximum considérable de caractères pour l'extension de fichier (8-16), il faut supprimer les caractères du nom de base. Il est également important de noter que dans le cas improbable d'avoir plusieurs extensions longues - telles que
_.graphmlz.tag.gz
-,_.graphmlz.tag
seule_
devrait être considérée comme le nom de base du fichier dans ce cas.8. Ressources
Calibre gère la modification des noms de fichiers assez décemment:
Page Wikipédia sur la modification des noms de fichiers et chapitre lié à l'aide de Samba .
Si, par exemple, vous essayez de créer un fichier qui enfreint l'une des règles 1/2/3, vous obtiendrez une erreur très utile:
la source
J'ai toujours pensé que Kohana avait fait du bon travail .
Le pratique
UTF8::transliterate_to_ascii()
transformera des choses comme ñ => n.Bien sûr, vous pouvez remplacer les autres
UTF8::*
éléments par des fonctions mb_ *.la source
En termes de téléchargement de fichiers, il serait plus sûr d'empêcher l'utilisateur de contrôler le nom du fichier. Comme cela a déjà été suggéré, stockez le nom de fichier canonisé dans une base de données avec un nom unique et choisi au hasard que vous utiliserez comme nom de fichier réel.
En utilisant OWASP ESAPI, ces noms pourraient être générés ainsi:
Vous pouvez ajouter un horodatage au $ safeFilename pour vous assurer que le nom de fichier généré aléatoirement est unique sans même rechercher un fichier existant.
En termes d'encodage pour URL, et encore en utilisant ESAPI:
Cette méthode effectue la canonisation avant d'encoder la chaîne et gérera tous les encodages de caractères.
la source
Je recommande * URLify pour PHP (480+ étoiles sur Github) - "le port PHP de URLify.js du projet Django. Translittère les caractères non-ascii pour une utilisation dans les URL".
Utilisation de base:
Pour générer des slugs pour les URL:
Pour générer des slugs pour les noms de fichiers:
* Aucune des autres suggestions ne correspond à mes critères:
En prime, URLify supprime également certains mots et supprime tous les caractères non translittérés.
Voici un cas de test avec des tonnes de caractères étrangers translittérés correctement à l'aide d'URLify: https://gist.github.com/motin/a65e6c1cc303e46900d10894bf2da87f
la source
J'ai adapté d'une autre source et ajouté quelques extra, peut-être un peu exagéré
la source
et ceci est la version Joomla 3.3.2 de
JFile::makeSafe($file)
la source
Je ne pense pas qu'il soit sûr d'avoir une liste de caractères à supprimer. Je préférerais utiliser ce qui suit:
Pour les noms de fichiers: utilisez un ID interne ou un hachage du contenu du fichier. Enregistrez le nom du document dans une base de données. De cette façon, vous pouvez conserver le nom de fichier d'origine et toujours trouver le fichier.
Pour les paramètres d'url: utilisez
urlencode()
pour encoder les caractères spéciaux.la source
Selon la façon dont vous l'utiliserez, vous souhaiterez peut-être ajouter une limite de longueur pour vous protéger contre les débordements de tampon.
la source
C'est un bon moyen de sécuriser un nom de fichier de téléchargement:
la source
.\x00..\x20
peut se réduire à.\x00\x20
..\x00..\x20
supprime les points et tous les caractères entre\x00
et\x20
, alors que cela.\x00\x20
ne devrait supprimer que ces 3 octets.Voici l'implémentation de CodeIgniter.
Et la
remove_invisible_characters
dépendance.la source
pourquoi ne pas simplement utiliser php
urlencode
? il remplace les caractères "dangereux" par leur représentation hexadécimale pour les URL (c'est-%20
à- dire pour un espace)la source
Il y a déjà plusieurs solutions fournies pour cette question mais j'ai lu et testé la plupart du code ici et je me suis retrouvé avec cette solution qui est un mélange de ce que j'ai appris ici:
La fonction
La fonction est regroupée ici dans un bundle Symfony2 mais elle peut être extraite pour être utilisée comme PHP simple , elle n'a qu'une dépendance avec la
iconv
fonction qui doit être activée:Filesystem.php :
Les tests unitaires
Ce qui est intéressant, c'est que j'ai créé des tests PHPUnit, d'abord pour tester les cas de bord et ainsi vous pouvez vérifier si cela correspond à vos besoins: (Si vous trouvez un bug, n'hésitez pas à ajouter un cas de test)
FilesystemTest.php :
Les résultats du test: (vérifié sur Ubuntu avec PHP 5.3.2 et MacOsX avec PHP 5.3.17:
la source
J'ai des titres d'entrée avec toutes sortes de caractères latins étranges ainsi que des balises HTML que j'avais besoin de traduire dans un format de nom de fichier délimité par des tirets utile. J'ai combiné la réponse de @ SoLoGHoST avec quelques éléments de la réponse de @ Xeoncross et j'ai personnalisé un peu.
J'avais besoin d'ajouter manuellement le caractère tiret em (-) au tableau de traduction. Il peut y en avoir d'autres mais jusqu'à présent, mes noms de fichiers semblent bons.
Alors:
Partie 1: Les «Žurburts» de mon père? - Ce ne sont (pas) les meilleurs!
devient:
partie-1-mes-papas-zurburts-theyre-pas-le-meilleur
J'ajoute simplement ".html" à la chaîne renvoyée.
la source
'ľ' => 'l', 'Ľ' => 'L', 'č' => 'c', 'Č' => 'C', 'ť' => 't', 'Ť' => 'T', 'ň' => 'n', 'Ň' => 'N', 'ĺ' => 'l', 'Ĺ' => 'L', 'Ř' => 'R', 'ř' => 'r', 'ě' => 'e', 'Ě' => 'E', 'ů' => 'u', 'Ů' => 'U'
$string = transliterator_transliterate('Any-Latin;Latin-ASCII;', $string);
voir ma réponse ci-dessous ou lire l'article de blog lié.Solution n ° 1: Vous avez la possibilité d'installer des extensions PHP sur le serveur (hébergement)
Pour la translittération de «presque toutes les langues de la planète Terre» en caractères ASCII.
Installez d' abord l'extension PHP Intl . Voici la commande pour Debian (Ubuntu):
sudo aptitude install php5-intl
Voici ma fonction fileName (créez test.php et collez-y le code suivant):
Cette ligne est essentielle:
Réponse basée sur ce post .
Solution n ° 2: Vous ne pouvez pas installer d'extensions PHP sur le serveur (hébergement)
Un bon travail est fait dans le module de translittération pour CMS Drupal. Il prend en charge presque toutes les langues de la planète Terre. Je suggère de vérifier le référentiel de plugins si vous voulez avoir des chaînes de nettoyage de solution vraiment complètes.
la source
Ce poste semble fonctionner le mieux parmi tout ce que j'ai lié. http://gsynuh.com/php-string-filename-url-safe/205
la source
C'est une bonne fonction:
la source
\\s+
signifie une barre oblique inverse suivie d'un ou plusieurs espaces. De quoi s'agit-il? En outre, cela utilise la liste noire plutôt que la liste blanche en ignorant des éléments tels queCMD
, null ouBEL
./blog/2014-02/just-in-time
ne sont pas autorisées. Veuillez utiliser le code testé ci-dessus ou utiliser lephunction
code du framework PHP.preg_replace('~[^\-\pL\pN\s]+~u', '-', $string)
Voici le code utilisé par Prestashop pour nettoyer les URL:
est utilisé par
pour supprimer les signes diacritiques
la source
Il y a 2 bonnes réponses pour slugfy vos données, utilisez-le https://stackoverflow.com/a/3987966/971619 ou https://stackoverflow.com/a/7610586/971619
la source
la source