0

On my site I have a bunch of files that require logged-in user for download access. Well that's not about just display access, I also want to avoid passing download links around.

Having read about the performance implications of using private file system, I decided I cannot afford it so I thought I'd write a small module to control the download.

The code looks like the following:

/**
 * Implements hook_permission().
 */
function docwatch_permission() {
  return array(
    'docwatch download restricted documents' => array(
      'title'       => t('Download restricted documents.'),
      'description' => t('Download technical documents from secured directory.'),
    ),
  );
}

/**
 * Implements hook_file_download
 */
function docwatch_file_download($uri) {
  if (strpos(file_uri_target($uri), 'secure/docs') !== 0) {
    if (!user_access('docwatch download restricted documents')) {
      // Access to the file is denied.
      return -1;
    }
    else {
      return array('Content-Type' => file_get_mimetype($uri));
    }
  }
}

And I'm using this debug code to inspect what Drupal "thinks" of the link to the file it displays:

function MYTHEME_file_link(&$variables){
  $file = $variables['file'];
  $uri = $file->uri;

  if (strpos(file_uri_target($uri), 'secure/docs') !== 0) { // <-- part of the secure dir path
    if (!user_access('docwatch download restricted documents')) {
      drupal_add_js("console.log('no access')", 'inline');
      // Access to the file is denied.
      // return -1;
    }
    else {
      drupal_add_js("console.log('ok to download')", 'inline');
      // return array('Content-Type' => file_get_mimetype($uri));
    }
  } else {
    drupal_add_js("console.log('from unsecured')", 'inline');
  }
}

I then open a page where the link is displayed in two browsers, one with a logged-in status for that role, and the other - plainly anonymous. The console properly reports that difference, yet - despite that the anonymous browser is permitted to download the direct link to the document.

What am I doing wrong?

1 Answer 1

1

Having read about the performance implications of using private file system, I decided I cannot afford it so I thought I'd write a small module to control the download.

The performance hit from using the private file system is minimal.

IMHO, using the private file system to control download access to files is the only sane way to do this when using Drupal.

What am I doing wrong?

You err in not using the private file system 😎.

When you hand the direct link to the browser, it goes directly to that link. It does not even see the PHP/JavaScript you've put in place to restrict download access.

To prevent unauthorised downloads, you must enforce that the downloads are managed by Drupal, and that this access control cannot be bypassed by requesting direct links served by the browser. This is what the private file system (aka private download method) does.

This download method stores the files attached to a node in a directory that is not accessible by the browser (preferably above the web-root). The only way to get to these files, are then through Drupal.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.