download files with spaces in their name - restriction through htaccess
Asked Answered
T

1

7

I stumbled upon strange way to protect files.

Basicly there is empty download.php file in protected folder and two files that cause file to be downloaded (from the same folder): .htpwd where password is stored and .htaccess:

RewriteEngine On
##RewriteBase /
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example.com [NC]
RewriteRule \.(.*)$ - [NC,F,L]

RewriteCond %{QUERY_STRING} ^filename=(.*)$
RewriteRule ^download\.php$ %1
RewriteRule (.*) - [E=file:$1]
Header set Content-type "octet-stream"
Header set Content-disposition "attachment; filename=%{file}e" env=file

##AuthName "Restricted Access" 
##AuthType Basic
##AuthUserFile /local/home/example/example.com/downloads/.htpwd
##AuthGroupFile /dev/null 
##require valid-user

Example of download link:
http://www.example.com/downloads/download.php?filename=dog%20cat%20cow.zip

If filename is dog-cat-cow.zip - all works. Problem starts when filename is: "dog cat cow.zip" then file will be downloaded but its file name after download will be "dog" instead of "dog cat cow.zip". So problem is people get file without even extension and have no idea what to do with it.

How this can be solved considering i simply cannot rename those files and remove spaces? I'm not expert on how to read .htaccess and no phrase that I could think of to search gives any similar problem resolution. Any ideas?

Tolley answered 5/8, 2015 at 14:50 Comment(5)
i recommend you do something like this Header set Content-disposition "attachment; filename='%{file}e'" env=file, filename in quotesEran
As @anonymous says, since the filename has spaces, you'll need quote delimiters. However, what is that extra e for?Asshur
"but its file name after download" - you can get the browser to always prompt for the location of the download (recommended) - at that stage the user can correct the filename.Asshur
Trick from the 1st comment did the job but only when I tried in new browser. Any good way to force clearing cache for this htaccess?Tolley
The cache is for that particular request ie. /downloads/download.php?filename=dog%20cat%20cow.zip, not "for this .htaccess" - will many users that have already downloaded that file want to download it again? The problem with this is that if the user has already cached it then there's not much you can do about it. You can only minimise the cache time from now going forward, for new requests. But then you will never benefit from the client-side cache for these download requests.Asshur
M
1

As mentioned in comments, maybe try:

RewriteEngine On
##RewriteBase /
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example.com [NC]
RewriteRule \.(.*)$ - [NC,F,L]

RewriteCond %{QUERY_STRING} ^filename=(.*)$
RewriteRule ^download\.php$ %1
RewriteRule (.*) - [E=file:$1]
Header set Content-type "octet-stream"
Header set Content-disposition "attachment; filename='%{file}'" env=file

##AuthName "Restricted Access" 
##AuthType Basic
##AuthUserFile /local/home/example/example.com/downloads/.htpwd
##AuthGroupFile /dev/null 
##require valid-user

Alternately, why not set the Content Type and Disposition within your download.php file itself?

$fileStorageDirectory = '/the/folder/the/downloadable/files/are/in/';

// Check for Parameter
if( !isset( $_GET['filename'] ) || $_GET['filename']=='' ){
  header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found', true, 404);
  die('No File Specified');
}

$fileName = trim( $_GET['filename'] );
$fileRequested = $fileStorageDirectory.$fileName;
// Check File Exists
if( !file_exists( $fileRequested ) ){
  header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found', true, 404);
  die('File Not Found');
}
// Check File is Readable
if( !is_readable( $fileRequested ) ){
  header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found', true, 404);
  die('File Not Accessible');
}
// Send the File
header( 'Content-Type: application/octet-stream' );
header( 'Content-Disposition: attachment; filename="'.fileName.'"' );
readfile( $fileRequested );
exit;
Masthead answered 8/9, 2015 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.