function filefield_file_download in FileField 6.2
Same name and namespace in other branches
- 5.2 filefield.module \filefield_file_download()
- 6.3 filefield.module \filefield_file_download()
Implementation of hook_file_download(). Yes, *that* hook that causes any attempt for file upload module interoperability to fail spectacularly.
File
- ./
filefield.module, line 822
Code
function filefield_file_download($file) {
$file = file_create_path($file);
$result = db_query("SELECT * FROM {files} WHERE filepath = '%s'", $file);
if (!($file = db_fetch_object($result))) {
// We don't really care about this file.
return;
}
// Find out if any filefield contains this file, and if so, which field
// and node it belongs to. Required for later access checking.
$cck_files = array();
foreach (content_fields() as $field) {
if ($field['type'] == 'file') {
$db_info = content_database_info($field);
$table = $db_info['table'];
$fid_column = $db_info['columns']['fid']['column'];
$columns = array(
'vid',
'nid',
);
foreach ($db_info['columns'] as $property_name => $column_info) {
$columns[] = $column_info['column'] . ' AS ' . $property_name;
}
$result = db_query("SELECT " . implode(', ', $columns) . "\n FROM {" . $table . "}\n WHERE " . $fid_column . " = %d", $file->fid);
while ($content = db_fetch_array($result)) {
$content['field'] = $field;
$cck_files[$field['field_name']][$content['vid']] = $content;
}
}
}
// If no filefield item is involved with this file, we don't care about it.
if (empty($cck_files)) {
return;
}
// If any node includes this file but the user may not view this field,
// then deny the download.
foreach ($cck_files as $field_name => $field_files) {
if (!filefield_view_access($field_name)) {
return -1;
}
}
// So the overall field view permissions are not denied, but if access is
// denied for a specific node containing the file, deny the download as well.
// It's probably a little too restrictive, but I can't think of a
// better way at the moment. Input appreciated.
// (And yeah, node access checks also include checking for 'access content'.)
$nodes = array();
foreach ($cck_files as $field_name => $field_files) {
foreach ($field_files as $revision_id => $content) {
// Checking separately for each revision is probably not the best idea -
// what if 'view revisions' is disabled? So, let's just check for the
// current revision of that node.
if (isset($nodes[$content['nid']])) {
continue;
// don't check the same node twice
}
$node = node_load($content['nid']);
if (!node_access('view', $node)) {
// You don't have permission to view the node this file is attached to.
return -1;
}
$nodes[$content['nid']] = $node;
}
}
// Well I guess you can see this file.
$name = mime_header_encode($file->filename);
$type = mime_header_encode($file->filemime);
// Serve images and text inline for the browser to display rather than download.
$disposition = ereg('^(text/|image/)', $file->filemime) ? 'inline' : 'attachment';
return array(
'Content-Type: ' . $type . '; name=' . $name,
'Content-Length: ' . $file->filesize,
'Content-Disposition: ' . $disposition . '; filename=' . $name,
'Cache-Control: private',
);
}