Download & Extend

View field permissions on 'file' field should block download

Project:CCK Field Permissions
Version:5.x-1.10
Component:Code
Category:bug report
Priority:critical
Assigned:Unassigned
Status:needs work

Issue Summary

Steps to reproduce:

  • install cck and enable
  • install filefield and enable
  • install cck_field_perms and enable
  • add a filefield to a content type
  • restrict access on the field using cck_field_perms
  • grant view access to authenticated users, but not anonymous users
  • enable "private" file transfers at admin/settings/file-system
  • log out and try to browse directly to the file using the "files/" url

Since the field is restricted users should not be able to download it. This can be overridden by implementing the hook_file_download.

Here is my stab at an implementation, but I think it needs some cleanup.

<?php
/**
* Implentation of hook file_download
*/
function cck_field_perms_file_download($file) {
    if (!
user_access('view uploaded files'))
      return -
1;

 
$file = file_create_path($file);
 
$result = db_query("SELECT f.* FROM {files} f WHERE filepath = '%s'", $file);
  if (
$file = db_fetch_object($result)) {
   
$node = node_load($file->nid);
    if (
node_access('view', $node)) {
     
$type = $node->type;
      if (
$types = variable_get('cfp_types', null)) {
        if (
$types[$type]) {
         
$disallowed_fields = unserialize(variable_get('cfp_values', null));
          if (
$disallowed_fields) {
            foreach (
$disallowed_fields[$type] as $disallowed_field => $value ) {
              if (
$value == 0)
                continue;
             
$field = db_fetch_object(db_query("SELECT * FROM {node_field} WHERE field_name = '%s'", $disallowed_field));
              if (
$field->type != 'file')
                continue;
              foreach (
$node->$disallowed_field as $field_instance) {
                if (
$field_instance['fid'] != $file->fid)
                  continue;
                if (!(
user_access(_cfp_content_to_readable($type, $disallowed_field, "view")))) {    
                  return -
1;
                }
              }
            }
          }
        }
      }

     
$type = mime_header_encode($file->filemime);
      return array(
       
'Content-Type: '. $type,
       
'Content-Length: '. $file->filesize,
      );
    }
    else {
      return -
1;
    }
  }
}
?>

Comments

#1

I had an issue with Acrobat Reader displaying PDF files. I had to add 'Cache-Control: private' to the successful return array.

#2

What should the code look like now, please?

nobody click here