[drupal-devel] restricting access to file downloads with flexinode
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, -Dave 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.
On Tue, 2 Aug 2005, David Cohen wrote:
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.
IIRC this was fixed a while ago.
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'.
Sure, look at image.module.
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
Flexinode is maintained by Jonathan Chaffer who seems to be burried under a real lot of work. Your best bet is to create an issue and attach patches. Cheers, Gerhard
Gerhard, Thanks for the info. I did take a look at the image module. Using it as an example, I implemented my node as a custom node, rather than a flexinode. While this took a bit longer, I think I've ended up with something more robust and versatile. More comments inline... On Tue, 2 Aug 2005 20:18:59 +0200, "Gerhard Killesreiter" <killesreiter@physik.uni-freiburg.de> said:
On Tue, 2 Aug 2005, David Cohen wrote:
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.
IIRC this was fixed a while ago.
I didn't mean to say its a shortcoming of Drupal core, but rather of flexinode, that any file uploaded via flexinode can be downloaded by anyone. Its simply because the download hook has no check for permission. Interestingly, the image module does the same thing. For instance, with my newly written custom mode I implement a download hook that returns -1 when an unauthorized user tries to download on of my node's images. But the image module download hook also allows users to download images. If it is called before (or after) my hook, the user will be able to download the file. This can be fixed by having the image module behave a little smarter, I think.
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'.
Sure, look at image.module.
Good advice, thanks. There is still the limit that all files are written within the files/ directory.
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
Flexinode is maintained by Jonathan Chaffer who seems to be burried under a real lot of work. Your best bet is to create an issue and attach patches.
Will do. I'll create issues for all the problems I mention. But they're not major problems. I've managed to get my app working well despite them. Thanks again, -Dave
On Fri, 5 Aug 2005 drupal@dave-cohen.com wrote:
On Tue, 2 Aug 2005 20:18:59 +0200, "Gerhard Killesreiter" <killesreiter@physik.uni-freiburg.de> said:
On Tue, 2 Aug 2005, David Cohen wrote:
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.
IIRC this was fixed a while ago.
I didn't mean to say its a shortcoming of Drupal core, but rather of flexinode, that any file uploaded via flexinode can be downloaded by anyone.
That is what I meant: http://cvs.drupal.org/viewcvs/drupal/contributions/modules/flexinode/flexino... See the commits to 1.49, 1.46.2.2, 1.36.2.5 Cheers, Gerhard
participants (3)
-
David Cohen -
drupal@dave-cohen.com -
Gerhard Killesreiter