I have a some PDF's that are accessed via link in the body of a node that I want to make accessible only to certain users. I have installed the Content Access module so that I can give per node permissions to the node itself. The PDF's are still of course accessible by a direct path in the URL (http://localhost/sites/default/files/rs.pdf)

So I then set the File System as Private and pointed it to a files directory above my webhost directory. The nodes now refer to the file as http://localhost/system/files/rs.pdf and this works fine however even an anonymous user can type this direct URL into his browser and access the pdf.

I must be missing something obvious.

In reality I would rather not move the files dir out of the webhost directory but rather leave it at sites/default/files and created a directory within it called, say 'private' and hide the files in that directory from direct download. Is this possible?

Comments

ludo1960’s picture

drpr’s picture

I'm not sure that this is relevant. It explains how to make sure that Apache does not have write permission on files that it has no need to write.

ardr’s picture

I'm not sure what you are trying to prevent here. Maybe you could clarify this a bit.

  • Are you trying to prevent people linking directly to your files, thereby using your site bandwidth? If someone can see a URL/link to any of your files, then of course you can't prevent them from just copying the URL into their own web page and leeching your bandwidth.
  • Are you trying to prevent 'unauthorised' users from seeing the links to the files?
  • Are you trying to prevent someone browsing the directories on your web server?

Regards,

Alan

drpr’s picture

Hi Alan,

I'm trying to prevent anonymous users from viewing the pdf's since they have information in them that only site members should have access to.

ludo1960’s picture

Sorry that wasn't helpful dpr, if the pdf's are in a block isn't this done by our old friend php?

WorldFallz’s picture

See My receipe for mixed private/public file system for a method to protect a subdirectory without having to use the 'private' file system setting (which has various disadvantages).

drpr’s picture

Thanks, this is really useful, and just what I want to do.

I have not got your scheme working yet, but am very close. I've not got into Drupal module programming yet (so much to learn) so maybe you can spot what I am doing wrong.

I'm running Drupal 6.15

My site is currently running under WAMP Server in a subdirectory called dev (http://localhost/dev)

Filesystem path is sites/default/files and is set to Public

I am trying to protect the directory sites/default/files/private and it has the following .htaccess file in it:

SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /dev/system/files/private
RewriteRule ^(.*)$ $1 [L,R=301]
</IfModule>

I have created a module called privatemodule with the privatemodule.module file containing:

<?php
function privatemodule_menu() {
  $items['system/files/private'] = array(
    'access arguments' => array('access privatemodule'),
    'type' =>  MENU_CALLBACK,
    'page callback' => 'file_download',
    'page arguments' => array('private'),
  );
  return $items;
}

function privatemodule_perm() {
  return array('access privatemodule');
}

In admin/user/permissions I see a private module module with an access privatemodule permission, which I have checked for authenticated users, and left unchecked for anonymous users

If I try to access a file in http://localhost/dev/system/files/private/o.png or http://localhost/dev/sites/default/files/private/o.png (which of course redirects to the first url) I get an Access Denied page both as an anonymous and an authenticated user.

I think I'm very close to getting this working but there is something I have overlooked.

izmeez’s picture

This work around might help
http://drupal.org/node/353817

drpr’s picture

Thanks for that link, it certainly does help.

I was missing the following function in my module to actually permit or deny the access based on the permissions setting.

/**
* Implementation of hook_file_download().
*/
function privatemodule_file_download($filepath) { 
  // We can deny access to files of the form sites/SITE/files/private/FILENAME
  $dirbasename = basename(dirname($filepath));
  if ($dirbasename == 'private') {
    if (user_access('access privatemodule')) {
      // Allow, or rather, say nothing and let filefield handle it.
      return NULL;
    }
    else {
      // Deny.
      return -1;
    }
  }
}

It now works a treat.
Thanks

tpainton’s picture

Great thread, subscribing.

drpr’s picture

OK, minor issue which I'm sure I've seen the answer to somewhere but can't find it.

If I link to a file in the private directory thus a href="/dev/sites/default/files/private/rs.pdf" target="_blank" then the file download dialog opens for the pdf rather than it appearing within a new browser tab.

ludo1960’s picture

Well done for getting this far! Isn't this just a server configuration issue now? What system are you running?

drpr’s picture

I'm not sure.

PDF's accessed via sites/default/files url open in the browser window. Those accessed via system/files (which of course the private directory access url gets rewritted to) give a file download dialog.

anonymous07’s picture

Very useful

crnjin’s picture

A lot of interesting solutions here, but I'm not sure if this is applicable for my case.

Already using TAC module and Field permission and work fine. Now I want to control access over part of Field, namely the tables and links (to PDF), which are in the Body field.

I wonder if there is a module that can solve that, because I failed to find such a, if not, then you try something with this php code.

computer_jin’s picture

Any help for drupal 7?

--
Azhar uddin
Technical Lead
email : engr.azharuddin@gmail.com
skype : computer_jin

jaypan’s picture

Use the private file system.

Contact me to contract me for D7 -> D10/11 migrations.