A recent "fix" (perhaps http://drupal.org/node/55520 - I'm not sure) introduced a problem for me. I have a module that defines hook_file_download. My problem is that no matter what my hook returns, access is denied to users without "view uploaded files" permission.

The problem is in upload_file_download. If that permission is not available, it returns -1, and file_download interprets that to mean deny access. So, effectively, upload_file_download says "either you can download all files, or you can download none."

In my case, I want some users (anonymous included) to view some uploaded files. My hook_file_download has the logic I need, but upload_file_download gets in the way. I think the rule needs to be "if you're module doesn't know for sure whether a file can be downloaded, then leave it for other modules to decide."

CommentFileSizeAuthor
#1 upload_file_download_sucks.patch.txt482 bytesDave Cohen

Comments

Dave Cohen’s picture

StatusFileSize
new482 bytes

file attachments do not work when submitting an issue.

killes@www.drop.org’s picture

Status: Needs review » Needs work

If I am not greatly mistaken, the download functione respect node_access modules. the patch does not follow coding conventions

dopry’s picture

@yogadex, can you use node access to fix your permissions situation.

view uploaded files is an umbrella permission. If user does not have view uploaded files permission, why should they be allowed to view any file, even if another module says it ok? I think finer grained file permissions are going to have to exist within the scope of view uploaded files for 4.7. We may be able to work on something better for 4.8. Unless someone has a strong argument against the way it is, I'm tempted to either won't fix or 4.7, or make a task of improving file permissions for 4.8.

Dave Cohen’s picture

Here's my situation is slightly complex. I have a node type called a reel. It stores a video file, but only administrators are allowed to view the node directly, no users are.

I have another node type called a 'pitch'. Some users are allowed to view some pitches. And pitches refer to reels. If the user is allowed to view a pitch, the she is allowed to view the videos referred to by that pitch. And she is allowed to view the video files, but not the reel node that contains them.

The logic is not very complex. I have a hook_file_download that takes care of it. However the recent change breaks it.

One question here is: is hook_file_download a function that one and only one module gets to implement? If you have upload.module installed, no other module can implement hook_file_download. Well to be accurate: they can implement, but the most they can do is deny files that upload_file_download would have allowed.

It's pretty clear to me that either upload_file_download has to change, or file_download (in file.inc). The logic there is that if any module returns -1, the file cannot be downloaded, even if another module return valid headers. I hope you agree that this should change.

dopry’s picture

@yogadex, why don't you enable view uploaded files for those roles and have your module specifically deny access where they aren't allowed, or better yet use a node access module that will work with upload.module?

Upload.module provides an umbrella permission for all uploaded files. You can enable that then let your module manage permissions within that scope.

Dave Cohen’s picture

I suppose I could redo my hook_file_download logic so that it denies access instead of allowing it.

I'd like to point out one thing before someone closes this issue... The other drupal access systems, namely hook_access and the node_access table, function by allowing access to things and not by denying it. That is, if they can't give you permission, they leave room for some other module to do so. It works nicely because if hook_access does not return true, the node_access table might provide the grant, and vice-versa. Meanwhile, upload_file_download is the opposite. It says no and the answer is final.

You may be thinking that hook_access also can return false, thereby explicitly denying access to a node. True it can, but now that node_access exists, returning false from hook_access is bad form. It prevents a grant that might be in the node_access table from actually working. If I submitted a bug "module X should not return false in hook_access, because it prevents my node_access grant from working", I suspect the bug would be fixed.

I don't understand the resistance to simply not returning -1. In my mind the permission "view uploaded files" should mean "view files uploaded by the upload module" but it really means "view any files stored on the system regardless of how they got there". I don't think it should mean that.

Finally, I apologize if the tone of any of my earlier comments was out of line (notably the name of my patch file). It took me a while to figure out what was causing my problem and that put me in a bad mood.

Rant over.

Dave Cohen’s picture

I was wrong in my first statement above. I can't re-jigger my logic in hook_file_download to deny access. The problem is the files I want to show the user are in a 'reel' node. I never want users to see the node itself, just the video files stored there.

uplaod_file_download includes a check that the user can see the node to which the file belongs. So even if I give all users "view uploaded files" permission, upload_file_download will return -1 because they can't view the node.

I'll use my patched upload.module.

dopry’s picture

@yogadex, The only resistance I have to changing the behavior of hook_file_download is its late in the release cycle. The patch you presented would make the view uploaded files permission, enable node_access for uploaded files. The issue is a little more indepth, and resolving it properly means coming up with a system for handling contention between modules over file access permissions. Right now we just make upload.module the one with the final say.

jakeg’s picture

this is a general problem that i'm experiencing too. We badly need a better file system API. If upload.module is enabled, it basically hijacks the _file_download() hook, meaing you have to either turn of upload.module or do things in a weird way.

I have a site where I need to have private file downloads with a complex access structure. I'm even thinking about not using Drupal's private file download method at the moment as it is so lacking.

A definite need for 4.8/5.

jakeg’s picture

Status: Needs work » Closed (duplicate)

I've made a patch for this which I think should suit everyone:
http://drupal.org/node/59648

... sorry its in a different thread. Lost where this one was.