I have a question if I may. I have a variable named $source
and this should contain a relative path to a file, for example ./uploads/2012/some-document.pdf
Now, this $source
variable will contain user input, via $_GET and $_POST. I don't want people to enter URLs and I only want to do something if the file exists only on the local server.
My question is what is the best way to check if a file exists on the local server only?
This is what I've got so far:
1) file_exists
may return true depending on the server configuration, so I could use this alongside stripos to check if the first few charatcers of the string is http:// like so:
if( file_exists($source) && stripos($source,'http://')!==0 ) {
echo 'File exists on local';
}
However, the downside would be I'd have to specify all the different URL types such as https://, http:// and ftp:// just to be safe.
2) I use realpath
to get the absolute path of the file, and this returns false if it cannot be found. This seems to be pretty solid, but not 100% this is the best application for it
3) Use preg_replace
to remove all URL mentions in the string first, and then simply use file_exists
. Whilst this would probably be the most secure, it would most likely be the most intensive and I'd prefer not to use this method.
In addition to the other answers, you can deny paths that use a scheme simply with:
if (parse_url($path, PHP_URL_SCHEME)) {
// has something:// so ignore
}
This would also work with specialty wrappers such as php://
, zlib://
, etc...
You can also force a local check on the input variable by prepending with file://
:
file_exists('file://' . $path);
Go with realpath()
(in conjunction with file_exists
). It will filter out URLs for you, and you should get a solid reliable result on whether the file exists or not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With