Doesn't work with private downloads
Mark Theunissen - February 20, 2009 - 11:20
| Project: | File Force |
| Version: | 6.x-1.1 |
| Component: | Code |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | active |
Description
Maybe I'm missing something obvious but it doesn't work with Drupal's private downloads. Should I just write my own hook_download for this, instead of using file_force?
Thanks for any tips! ;)

#1
Though I haven't thoroughly tested it, I would think that File Force would work with private downloads enabled. Could you be more specific about what's not working?
#2
Sure, when you call the file_download() function, File Force passes in the full path 'system/files/image.jpg'.
However, when using private downloads directly, the menu item ['system/files'] maps directly to the file_download() function, and thus it only passes in the file name, i.e. it gets 'image.jpg'.
Put a breakpoint in file_download and see the difference in the arguments.
Thanks!
:)
#3
Hi Garrett, have you had a chance to look at this?
#4
Sorry, no. I've been cramming on other projects lately… It may be a while before I'm able to.
#5
I'm really interested in private download too !
#6
Hi Guys,
I really need to get this working for a customer, so I hack the code myself and succeded to do it !
How to get it working:
1) Edit the file "includes/file.inc"
2) Replace the function file_download() by this one:
function file_download() {
// Merge remainder of arguments from GET['q'], into relative file path.
$args = func_get_args();
$filepath = implode('/', $args);
// Maintain compatibility with old ?file=paths saved in node bodies.
if (isset($_GET['file'])) {
$filepath = $_GET['file'];
}
if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {
$tmp = explode("/",$filepath);
$filepath = file_directory_path()."/".array_pop($tmp);
unset($tmp);
}
if (file_exists(file_create_path($filepath))) {
$headers = module_invoke_all('file_download', $filepath);
if (in_array(-1, $headers)) {
return drupal_access_denied();
}
if (count($headers)) {
file_transfer($filepath, $headers);
}
}
return drupal_not_found();
}
3) Enjoy
4) I've included the patch. This is the first one, I'm sure it's not the best, but at least, I'm trying ;)
#7
Update ! Small bug fix
Replace the function includes/file.php::file_download() (near line 840) by this one:
function file_download() {
// Merge remainder of arguments from GET['q'], into relative file path.
$args = func_get_args();
$filepath = implode('/', $args);
// Maintain compatibility with old ?file=paths saved in node bodies.
if (isset($_GET['file'])) {
$filepath = $_GET['file'];
}
if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {
$filepath = file_directory_path()."/".array_pop(explode('system/files/',$filepath));
}
if (file_exists(file_create_path($filepath))) {
$headers = module_invoke_all('file_download', $filepath);
if (in_array(-1, $headers)) {
return drupal_access_denied();
}
if (count($headers)) {
file_transfer($filepath, $headers);
}
}
return drupal_not_found();
}
#8
Ack! Don't hack core!
#9
Yes we don't have to hack in the core.
But here, without those 3 lines, all the modules that implement file_download() will never be used !
These are the 3 lines of code to add:
if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) {$filepath = file_directory_path()."/".array_pop(explode('system/files/',$filepath));
}
It's impossible to do it in an other way!
So... what to do ?
#10
I committed the patch to core.
It's related to file_force but it's a small bug in file_download()
Link: #432332: Private path and file_download