[drupal-devel] restricting access to file downloads with flexinode

David Cohen drupal at dave-cohen.com
Tue Aug 2 18:14:33 UTC 2005

Hey all,

I'm using Drupal on a project where some content is available to all,
but some content restricted to paid subscribers.  To make uploading
content easy for the site administrators, I've created a custom node
type with the wonderful flexinode module.  This allows the admins to
upload several files (which belong together) in one easy step.  This
works great, but I wouldn't be writing if it didn't get more
complicated, so please read on.

My node type corresponds to a 'lesson'.  Each lesson has some public
information which everyone can see, such as a title, and a preview
image.  Other content is restricted to only paid users, this includes
flash files and quicktime videos.  I'm using templates and php code to
ensure users see only the portions they're supposed to see.

My problem is the uploaded files.  By default, anyone can download the
files uploaded via flexinode.  I never show an anonymous user the link
to a flash file, but if they type "system/files?file=private-file.swf"
in the URL, they'll be able to download it anyway.

My second problem is that lots of files will be uploaded, and eventually
the files directory will be a real mess.  So I want to control where
each of these files goes.  For instance, the previews could all go to
'files/preview_images' and the movies to 'files/videos'.

I've address both of these problems in the attached patch to flexinode. 
I'd appreciate it if some experienced drupal coders would check my work.
 I'd like to see something like this checked into the code base.  I hope
this would be useful to others as well.  I'm happy to keep working on it
if that's what it takes.  If you review the code, search for '???' and
see if you can answer the questions I left in the comments.

Also - yes, I'm aware much of flexinode's functionality will be replaced
by CCK, but I need this functionality today.  And, I'd hoped to isolate
my changes by adding another field type to flexinode.  But to make it
work I had to change flexinode's file download hook.  And since I had to
do that, I figured I might as well make the changes to the existing
field_file.inc.  As far as I know, the changes do not affect behavior
for existing flexinode files.

Here's how it works....

When adding a file field to a flexinode, you now have the option of
specifiying a permission with that file.  User's can download only if
they have that permission.  Note that different files within a node can
have different permissions.  This allows me to keep the preview images
public but restrict access to the other files.

Also, you have the option of specifying a subdirectory of files/ where
the file will be saved.  I plan to make this more dynamic, so that the
directory can be a function of the other fields in the node.  For
instance, instead of just typeing 'private-files', you could type
'private-files/%flexinode_2' and %flexinode_2 would be substituted with
a value from the node.  This might get a little tricky but it will
really help me organize the files.

Finally, while I have your attention (if you're still reading) a couple
questions about drupal's file handling...

How much overhead is involved in using drupal to restrict access to the
files?  That is, can I serve a lot of large files via the file_transfer
method?  Is there some better way through Apache?

Also, the file.inc seems pretty heavy handed about forcing all files to
be in a subdirectory of files/ (the 'file_directory_path' variable).  It
would be nice to have some public files in files/ but also be able to
save some uploads elsewhere (say /var/private-files).  file_save_upload
currently makes this impossible.  If it were possible, some files could
be served up efficiently via urls like 'mysite.com/files/foo.swf' while
others could be restricted
'mysite.com/system/file?file=/var/private-files/bar.swf'.  I'd like to
see something like that.

This concludes my first post to drupal-devel.  I hope I haven't offended
anyone ;)  Drupal is a really great product.  Cheers,


P.S. Also attaching a patch to file.inc.  The call to
drupal_access_denied when downloading a file should return immediately
after that call.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: flexinode-file-permission.patch
Type: application/octet-stream
Size: 5661 bytes
Desc: not available
Url : http://drupal3.drupal.org/pipermail/development/attachments/20050802/2a5dcbbf/flexinode-file-permission.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: file.inc.patch
Type: application/octet-stream
Size: 1017 bytes
Desc: not available
Url : http://drupal3.drupal.org/pipermail/development/attachments/20050802/2a5dcbbf/file.inc.obj

More information about the drupal-devel mailing list