path validatie
Ik wil valideren of een (ingegeven) pad geldig is. Met een pad bedoel ik dit:
$pad = '/mijn/pad/naar/een_of_andere_directory/in/subdirectory/12';
Nu zit ik een beetje moeilijk te doen om eerst te controleren of het ingegeven pad een string is, of er ongeldige karakters in staan, of het pad niet leeg is enz.
Volgens mij ben ik veel te omslachtig bezig. Ik vraag me dan ook af of PHP standaard een pad validatie functie kent. Of wellicht weet iemand hier een handige preg_match voor? Een pad mag alleen bestaan uit cijfers en letters en mag underscores en forward slashes bevatten, maar geen dubbele forward slashes.
Nog een klein extra vraagje. Geen idee of iemand dit weet... Stel je controleert zo'n pad via een functie of via preg_match, maar in plaats van een string wordt er een boolean of object ingegeven (omdat een programmeur ligt te slapen), resulteert dit dan in een warning? Of ziet de preg_match functie van hé, dit is geen string en handelt ie het dan gewoon netjes af?
Gewijzigd op 09/03/2012 18:20:13 door Ozzie PHP
Zo nee, fout. Zo ja: prima.
Gewijzigd op 09/03/2012 19:22:55 door Eddy E
En als je gewoon controleerd met is_dir, file_exists en is_string?
Als iemand een pad toevoegt dan wil ik controleren of de structuur klopt. Dus als iemand invult:
/mijn/pad!naar@ /
dan moet dat worden afgekeurd.
Zo zou je het kunnen controleren:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
$regex = '/(!|@)/i';
if (preg_match($regex, '/mijn/pad!naar@ /')) {
echo 'wrong path name';
} else {
echo 'path is ok';
}
?>
$regex = '/(!|@)/i';
if (preg_match($regex, '/mijn/pad!naar@ /')) {
echo 'wrong path name';
} else {
echo 'path is ok';
}
?>
Dit /mijn/pad!naar@ / was puur bedoeld als een voorbeeld... waarmee ik duidelijk wilde maken dat er geen ongeldige tekens in het pad mogen staan. Het gaat dus niet om dat ! of @. Dat was puur een voorbeeld.
Moet iemand een pad kunnen toevoegen, of wil je controleren of een url bestaat?
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
$filename = '/path/to/foo.txt';
if (file_exists($filename)) {
echo "The file $filename exists";
} else {
echo "The file $filename does not exist";
}
?>
$filename = '/path/to/foo.txt';
if (file_exists($filename)) {
echo "The file $filename exists";
} else {
echo "The file $filename does not exist";
}
?>
In mijn cms kan een programmeur paden naar bepaalde directories toevoegen. Ik wil valideren of die paden voldoen aan het juiste formaat. Het gaat er dus niet om of de directory wel of niet bestaat. Het gaat er alleen om of het een geldig "formaat" is.
Dit is een geldig pad: 'pad/naar/directory'.
Maar dit bijvoorbeeld niet: 'pad / naar/directory'.
En dit ook niet 'pad@naar/directory';
Ik wil een preg_match waarmee ik kan controleren of:
1. het pad mag bestaan uit: letters, cijfers, underscores, forward slashes, punten
2. het pad mag niet eindigen op een slash
3. er mogen geen dubbele slashes in zitten
Daar moet ik dus een preg_match voor hebben.
Ik ben inmiddels zover dat ik een preg_match heb die controleert op punt 1 (zie hierboven).
preg_match('/^[a-z0-9.\/_]$*/i', $pad);
Maar ik heb geen idee hoe ik punt 2 en 3 in diezelfde preg_match krijg...
Voorbeeld: http://regexr.com?309bb (die global en multiline flags zijn slechts voor het juist testen en moet je dus niet gebruiken)
Even een uitleg:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
/../ een regex
^ match vanaf het begin van een string
(a|b) match a of b
[a-z0-9._-] match a-z 0-9 . _ -
\/(?!\/) match een backslash (\/) die niet wordt gevolgt door nog een backslash ((?!..) is een negative lookahead)
()* match de group 0 of meer keer, zo vaak mogelijk
[^\/]$ match geen \/ als laatste teken van de string ($ = laatste teken)
^ match vanaf het begin van een string
(a|b) match a of b
[a-z0-9._-] match a-z 0-9 . _ -
\/(?!\/) match een backslash (\/) die niet wordt gevolgt door nog een backslash ((?!..) is een negative lookahead)
()* match de group 0 of meer keer, zo vaak mogelijk
[^\/]$ match geen \/ als laatste teken van de string ($ = laatste teken)
Ik heb nog even - toegevoegd. Een - hoort in een url thuis, een _ niet.
Na aanleiding van deze reactie in het andere topic heb ik nu deze regex, deze werkt volgens mij volledig naar jou wensen: http://regexr.com?309bh
/^([a-z0-9._\-]|\/(?!\/))*[a-z0-9._-]$/i
De laatste character class zorgt ervoor dat het alleen a-z 0-9 . _ - als laatste teken mag hebben en geen backslash. Eventueel kan je dit nog stricter maken door ook . _ en - te verbieden als laatste teken.
Gewijzigd op 10/03/2012 00:02:21 door Wouter J
Het lijkt nu in ieder geval te werken. Kan ik straks weer rustig slapen... zucht...
Waarom hoort een _ niet in een url thuis? In de meeste gevallen heb je denk ik wel gelijk, maar iemand zou een directory toch "_private" kunnen noemen of "mijn_directory"?
Toevoeging op 10/03/2012 00:23:17:
P.S.
([a-z0-9._\-]|\/(?!\/))
Wat is de rol van de (dikgedrukte) slash? Ik zie geen verschil als ik m weghaal?
Waarom mag een _ niet in de url staan? Zover ik weet is dit gewoon toegestaan.
@Ozzie,
Gezien de topics die je de laatste tijd gestart hebt, heb ik het idee dat je heel je CMS zaak een beetje overschat. Begrijp me niet verkeerd, ik vind het leuk dat je zulke vragen stelt, maar ik denk dat het overbodig is.
Daarnaast, heb je wel eens nagedacht over de snelheid van jouw framework / CMS? Wanneer je van dit soort validaties erin bouwt wordt het geval steeds trager.
Nogmaals, begrijp me goed, ik raad je het niet af. Ik raad je alleen aan om de juiste beslissingen te nemen en goed na te denken over de overwegingen die je moet maken.
Succes ;-)
Niels Kieviet:
Waarom mag een _ niet in de url staan? Zover ik weet is dit gewoon toegestaan.
Het mag, maar is niet aan te raden. Vooral op SEO gebied is een - noodzakelijk en een _ zowat verboden. Zie ook deze video van Matt Cutts: http://www.youtube.com/watch?v=AQcSFsQyct8
Toevoeging op 10/03/2012 10:14:08:
Niels Kieviet:
Waarom mag een _ niet in de url staan? Zover ik weet is dit gewoon toegestaan.
Het mag, maar is niet aan te raden. Vooral op SEO gebied is een stuk beter om - te gebruiken. Zie ook deze video van Matt Cutts: http://www.youtube.com/watch?v=AQcSFsQyct8
Gewijzigd op 10/03/2012 10:16:17 door Wouter J
Ja inderdaad dat bedoelde ik. Ik gebruik het zelf (ook) niet, maar ik wilde even zeker weten of het mocht ja of nee :-)
Niels
Wouter J op 10/03/2012 10:14:06:
Het mag, maar is niet aan te raden. Vooral op SEO gebied is een - noodzakelijk en een _ zowat verboden.
Ja, dat klopt. Dat wist ik inderdaad. Maar dat heeft vooral betrekking op urls's en niet zozeer op interne paden.
Niels Kieviet op 10/03/2012 10:06:44:
Ik raad je alleen aan om de juiste beslissingen te nemen en goed na te denken over de overwegingen die je moet maken.
Thanks Niels. Daarom zit ik hier ook op het forum ;)
Maar bedoel je dat ik de paden dan gewoon maar helemaal NIET moet controleren? En op het moment dat het fout gaat dan gaat het gewoon fout? Maar dan bestaat ook de kans dat je bijvoorbeeld dubbele slashes in je paden hebt staan. Dit zal in sommige gevallen gewoon werken, maar het is niet netjes. Maar wat is dan de oplossing? Niet controleren en maar er vanuit gaan dat een programmeur het goed invoert? Is dat wat je bedoelt? Ik snap dat je zegt dat je niet te veel moet willen valideren, maar wanneer MOET je nu écht valideren? Ik bedoel, je kan ook helemaal niks valideren en alleen afgaan op de PHP warnings maar dat lijkt me toch ook niet helemaal de bedoeling? Dus in z'n algemeenheid: WANNEER en WAT moet je controleren / valideren? (en wat niet?)
/^(.+|\/(?!\/))+[\/]$/
Ik wil deze preg_match /^([\w.-]|\/(?!\/))+[\/]$/i vereenvoudigen naar de bovenstaande preg_match maar de dubbele slashes werken niet.
Wat ik wil is dat de string:
- uit tenminste 2 tekens bestaat
- eindigt op een slash
- geen dubbele slashes bevat
Ziet iemand wat ik fout doe?
Ik heb [\w.-] veranderd in .+. De bedoeling van .+ was te matchen op een willekeurig karakter. Ziet iemand de fout?
Verder matched een . ook een slash, dus hij zal nooit in het gedeelte van de dubbele slash controle komen. Iets als ([^\/]|\/(?!\/))+ zal beter werken. [^\/] matched alles behalve een slash en daarom gaat hij, bij een slash, naar de dubbele slashes kijken.
godsiedikkie, daar heb je gelijk in! Knap dat je dat zo snel ziet zeg.
([^\/]|\/(?!\/))+ lijkt als een zonnetje te werken! Thanks a lot!!!
Ik zie nu dat je andere vraag op http://www.phphulp.nl/php/forum/topic/dicht-timmeren/83005/last/ toch wel redelijk aan de frontend zit, dus naar de gebruikers toe gaat (of moet ik dit los van elkaar zien?)
Als je controleert of het pad bestaat bij het uploaden of verwijzen (file_exists) en bij een false de suggesties geeft van wat er fout is ben je al een heel eind. (geen of dubbele slashes, verkeerd gebruikte tekens, lijstje met toegestane tekens geven, etc.)
Bij het aanmaken creëren van zo'n folder heb je wel een regex nodig zoals dit. Geef aan wat je mooi vindt en that's it.
Ook is de 'folder' structuur op deze site niks meer dan een iets te grootte structuur gemaakt met htaccess...
Het controleren op ongeldige tekens is natuurlijk heel mooi, maar ik bedacht me dat als er ongeldige tekens instaan de directory ook niet gevonden zal worden. Dus dat stukje controle heb ik nu laten vervallen.
Dus eerst was dit niet toegestaan:
$pad = '/mijn/$pad/;
Omdat er een ongeldig teken in zat, namelijk het $ teken, werd het pad afgekeurd. Echter... ik doe ook een file_exists check. Vanwege het ongeldige teken in het pad zal de file_exists niet slagen. Daarom heb ik die controle op ongeldige tekens laten vervallen.
Goede keuze denk je?
@Wouter: in dit geval gaat het om een "echt" pad :)
Gewijzigd op 14/03/2012 23:25:22 door Ozzie PHP