Solved

PHP interpret file with spaces

Posted on 2010-09-15
11
537 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Interactive Way of Training for the AWS CSA Exam

An interactive way of learning that will help you visualize core concepts so that you can be more effective when taking your AWS certification exam.  Built for students by a student to help them understand the concepts that they are being taught.

 
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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

When it comes to write a Context Sensitive Help (an online help that is obtained from a specific point in state of software to provide help with that state) ,  first we need to make the file that contains all topics, which are given exclusive IDs. …
This article will inform Clients about common and important expectations from the freelancers (Experts) who are looking at your Gig.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

617 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