views:

506

answers:

5
$filename = "Sara & I.mp3";
if (file_exists($filename)) {
 ...
}

If the filename has a "&" PHP does not return true for file_exists

How can I escape "&" in the $filename for the file_exists to work?

Already tried urlecode(), urlrawencode(), htmlentities(), and escaping the '&' with a backslash (\&)... no go

ps. this is on a linux system running RedHat5

thanks in advance

+2  A: 

Are these files uploaded by users? I normally rename any uploaded file to use only letters A-Z, numbers 0-9 and _ or - plus the file extension like .pdf in order to avoid problems with special charachters. Spaces are converted to _.

TYPO3, a large PHP based CMS for example uses these regex in order to clean a filename:

$fileName = preg_replace('/[^.[:alnum:]_-]/','_',trim($fileName));  // converting all on alphanumeric chars to _
$fileName = preg_replace('/\.*$/','',$fileName); // removing dot . after file extension

So a input of foo&.pdf. would be converted to foo.pdf

Max
I'd like to solve this question without the need of renaming files. Thanks Max :)
TheLumin
+1  A: 

If it's a file, shouldn't be escape as the filesystem expects it to be? Shouldn't it be something along the lines of \& or maybe the unicode based escape sequence (which escapes me at the moment ;-) ?

jldupont
+1  A: 

i assume you are passing your parameters as GET requests like script.php?file=this & that.mp3

first be sure you check your input really well, so users can't delete arbitrary files. second: encode your filenames with urlencode when creating the link. the encoded char for & is %26.

your script would be called like this then: script.php?file=this%20%26%20that.mp3 (%20 being a whitespace)

otherwise you will have another GET variable, namely that.mp3, being not assigned. & is used to separate single parameters in your GET request

edit
a question from my side: how do you delete your files? using php’s unlink function? or using exec and calling rm on your system? (which is generally very unsafe). if you’re doing it the second way you could use escapeshellarg. if you don’t escape your shell input, your shell will interpret your command as two commands (afaik, don’t take my word for it)

knittl
TheLumin
just tested. works for me. `unlink('this (also on a linux system)
knittl
+2  A: 

The script seems to work for me.

Make sure that the file you're checking is in the directory where your script is run.

use getcwd() to see where your script is running.

e.g. if your script is in my/scripts/script.php but if it's included and invoked by another script at my/other/scripts/index.php then your script would actually be running in the my/other/scripts directory, NOT in the my/scripts directory as you might expect

Charles Ma
A: 

Where is the ampersand coming from - user input or is it really inside your script? There may be a mix-up in encodings there.

Also, when you do a glob() on the directory, what results do you get? Is the file with the ampersand there? What happens if you copy & paste the glob() output and run file_exists() on it?

Pekka