PHP interpret file with spaces

I  have a photo gallery where the user is allowed to download a hires version of the images by clicking a link. I usually use non web safe names for the photo naming convention mainly for design purposes. This causes the PHP script to stop interpreting the file name at the first instance of  "%20". So if 50  images have the same name except for a counter, the user will be offered to download the same file name every time.

So... I need to modify the code below to properly interpret file name when it contains "%20".

download.php - this file is in the directory along with hires images.

<?php
// Force download of image file specified in URL query string and which
// is in the same directory as this script:
if(!empty($_GET['img']))
{
   $filename = basename($_GET['img']); // don't accept other directories
   $size = @getimagesize($filename);
   $fp = @fopen($filename, "rb");
   if ($size && $fp)
   {
      header("Content-type: {$size['mime']}");
      header("Content-Length: " . filesize($filename));
      header("Content-Disposition: attachment; filename=$filename");
      header('Content-Transfer-Encoding: binary');
      header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
      fpassthru($fp);
      exit;
   }
}
header("HTTP/1.0 404 Not Found");
?> 

Open in new window


This HTML code invokes the download option:
<img src="/images/download.php?img=imagename.jpg" alt="test">

Open in new window


Example: These file names work:

Game_1_Hopkins_09_10_01.jpg
Game_1_Hopkins_09_10_02.jpg

These don't:
Game%201%20Hopkins%2009%2010%2001.jpg
Game%201%20Hopkins%2009%2010%2002.jpg

I normally would use this naming convention on the original files, and my gallery design software would add the "%20" to enable the browser to interpret the file name. Which has always worked fine except in this instance, which allows a download of the original image.

Game 1 Hopkins.09.10.01.jpg

Which is:  filename:month:year:counter

Sorry for this very long winded description. Just wanted to be clear.

tplowe56Asked:
Who is Participating?
 
DalHorinekConnect With a Mentor Commented:
Also you should use
header("Content-Disposition: attachment; filename=".urlencode($filename));

Maybe some browsers can't handle it :)


Anyway your code works perfectly on my server no  matter what filename is used.
0
 
DalHorinekCommented:
try not to suppress error notifications and see, if there are any errors ...

Generally this should work.
0
 
Chris StanyonConnect With a Mentor Commented:
You can use the urldecode function to convert the %20 back to spaces.

http://php.net/manual/en/function.urldecode.php



$filename = urldecode(basename($_GET['img'])); // don't accept other directories

Open in new window

0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

 
DalHorinekCommented:
This PHP does automatically.

See urldecode Warning:

The superglobals $_GET and $_REQUEST  are already decoded. Using urldecode() on an element in $_GET or $_REQUEST could have unexpected and dangerous results.
0
 
Chris StanyonCommented:
Apparently not!

If it does it automatically, then why are you still getting %20 in the GET variables? These are urlencoded spaces and to convert them back to spaces you need to use urldecode($string);

You could try and echo out the $_GET['img'] value (or $filename) and see what you get.







0
 
tplowe56Author Commented:
I have been investigating this further. The code will work fine if my gallery engine would generate the "%20" for the spaces in this instance, which it isn't and won't. So I think I need to add urlencode to the code above to get it to parse the file names which have spaces in them.

I am not a coder, I am a copy/paste coder. So I am not sure how to do it.

The code invokes a download just fine but it suggests to save every file as "game" (the first word in the file name before a space", thus allowing unsuspecting users to overwrite the last image they downloaded if they are not paying attention.
0
 
tplowe56Author Commented:
OK...I got it working fine now with this code:

<?php
// Force download of image file specified in URL query string and which
// is in the same directory as this script:
if(!empty($_GET['img']))
{
   $filename = basename($_GET['img']); // don't accept other directories
   $size = @getimagesize($filename);
   $fp = @fopen($filename, "rb");
   if ($size && $fp)
   {    
      header("Content-type: {$size['mime']}");
      header("Content-Length: " . filesize($filename));
      header("Content-Disposition: attachment; filename=".urlencode($filename));
      $filename = urlencode(basename($_GET['img'])); // don't accept other directories
      header('Content-Transfer-Encoding: binary');
      header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
      fpassthru($fp);
      exit;
   }
}
header("HTTP/1.0 404 Not Found");
?>


Not sure who gets the credit, I initially describe the problem wrong.
0
 
Chris StanyonCommented:
DalHorinek has already posted the code to urlencode your filename to present to your user.

Change line 13 (in your code above) to the following, and see how you get on.


 
 

 header("Content-Disposition: attachment; filename=" . urlencode($filename));

Open in new window

0
 
DalHorinekCommented:
ChrisStanyon, than it probably depends on configuration, because it works for me.

See
http://www.travelcook.com/~dal/test.php?file=whatever%20with%20spaces.jpg

It's ok.

Even if you try it over telnet (to avoid browsers handling)

telnet travelcook.com 80
Trying 89.185.224.39...
Connected to travelcook.com.
Escape character is '^]'.
GET /~dal/test.php?file=whatever%20with%20spaces.jpg HTTP/1.0

HTTP/1.1 200 OK
Date: Wed, 15 Sep 2010 19:48:33 GMT
Server: Apache
X-Powered-By: PHP/5.3.1-5
Content-Length: 29
Connection: close
Content-Type: text/html; charset=UTF-8

Filename: 'whatever goes.jpg'
0
 
Chris StanyonCommented:
DalHorinek.

It worked for me aswell.

@tplowe56 said that the $filename in his script still contained the %20, which indicated that the GET array wasn't being urldecoded. Turned out to not be the case.






0
 
tplowe56Author Commented:
Thanks guys, experts exchange is THE place for accurate support. Mission accomplished.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.