Solved

PHP interpret file with spaces

Posted on 2010-09-15
11
533 Views
Last Modified: 2013-12-25
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.

0
Comment
Question by:tplowe56
  • 4
  • 4
  • 3
11 Comments
 
LVL 6

Expert Comment

by:DalHorinek
ID: 33683276
try not to suppress error notifications and see, if there are any errors ...

Generally this should work.
0
 
LVL 6

Accepted Solution

by:
DalHorinek earned 125 total points
ID: 33683343
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
 
LVL 43

Assisted Solution

by:Chris Stanyon
Chris Stanyon earned 125 total points
ID: 33684768
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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 6

Expert Comment

by:DalHorinek
ID: 33685400
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
 
LVL 43

Expert Comment

by:Chris Stanyon
ID: 33685675
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
 

Author Comment

by:tplowe56
ID: 33685771
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
 

Author Comment

by:tplowe56
ID: 33685920
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
 
LVL 43

Expert Comment

by:Chris Stanyon
ID: 33685926
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
 
LVL 6

Expert Comment

by:DalHorinek
ID: 33685942
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
 
LVL 43

Expert Comment

by:Chris Stanyon
ID: 33686054
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
 

Author Comment

by:tplowe56
ID: 33686169
Thanks guys, experts exchange is THE place for accurate support. Mission accomplished.
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
Because your company can’t afford for you to make SEO mistakes, you’ll want to ensure you’re taking the right steps each and every time you post a new piece of content. This list of optimization do’s and don’ts can help you become an SEO wizard.
This tutorial walks through the best practices in adding a local business to Google Maps including how to properly search for duplicates, marker placement, and inputing business details. Login to your Google Account, then search for "Google Mapmaker…
The viewer will learn how to dynamically set the form action using jQuery.

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question