There's a few threads over on the jPlayer Google Group about this, but File above web root? has the most useful information.

I think we can implement something similar to this. My initial research / thoughts are:

  • The filefield (or site file system in Drupal 6) would need to be set to Private.
  • We can add a jQuery behavior to the player such that when the file needs to be downloaded, an AJAX request is first sent that includes the path to the file and the current time. We may have to do different code for the Flash player, but since it's controlled by JavaScript we should be able to hook into the file download action the same way. That timestamp can be saved in $_SESSION.
  • In hook_file_download(), we can compare the timestamp to the current time, and allow access if the time passed is less than some specified period (like 5 seconds).
  • If the timestamp isn't present or if it's expired, we can deny access. The 403 could be logged to the watchdog, or perhaps even a separate table for authenticated users. That way, should be easy to track users who are attempting to download the file directly.

I need this for Drupal 6, but I might write it for D7 first and backport. I'm filing this against 7.x-2.x due to #1173678: Add 6.x-1.x-dev release.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

deviantintegral’s picture

Status: Active » Needs review
FileSize
16.46 KB

Here's a patch against 6.x-1.x withe the following commits:

  • df50fde #1173692: Add settings for content protection.
  • 9518ac6 #1173692: Implement basic content protection for filefields using jPlayer.
  • 7b8b0f3 #1173692: Add missing semicolons in javascript.
  • b67f675 #1173692: Only add the content protection handler if content protection is enabled.
  • 9344e4e #1173692: Fix renaming of the base64 function.
deviantintegral’s picture

Here's a new patch with a few more commits. We now prevent clients from setting their clock to be too far in the future, increased the default window to 30 seconds, and only allow access to a file once.

  • 461599f #1173692: Add settings for content protection.
  • 0238216 #1173692: Implement basic content protection for filefields using jPlayer.
  • 65cec78 #1173692: Add missing semicolons in javascript.
  • 11d9c27 #1173692: Only add the content protection handler if content protection is enabled.
  • aa22fa1 #1173692: Fix renaming of the base64 function.
  • 4c825f0 Issue #1173692: Prevent clients from setting the expiry to be too far in the future, and show a message if jPlayer is denied access to the file.
  • a5072d3 Issue #1173692: By default, allow access to files for 30 seconds.
  • e706691 Issue #1173692: Only allow accessing a protected file once.
deviantintegral’s picture

New commits:

  • e6d1192 Issue #1173692: Fix the multifile player when accessing protected files.
  • edf4342 Issue #1173692: Authorize access to protected files when autoplay is enabled.

Also, it looks like there is an issue with Chrome where it double-requests audio files. The second request is denied (since the token has expired) breaking the player. It works fine in other browsers, or if the flash player is used. I'm going to look into this some more, but I'm thinking that if the browser is chrome, download protection is on, and flash is available, that the flash player should be forced.

deviantintegral’s picture

Here's a new patch that fixes the issue with Chrome requesting a file multiple times.

  • 55fa2ac Issue #1173692: Only show the content protection settings if the site is set to private file downloads.
  • 82e4c0e Issue #1173692: Handle browsers requesting a file multiple times to fetch metadata.
deviantintegral’s picture

Here should hopefully be a final patch that adds logging for when files are blocked and provides a table of the top-denied users. That way, admins can contact or block users who are trying to download files (or be aware of any possible browser issues).

  • 0908468 Issue #1173692: Add a table to log when jPlayer denies access to a file.
  • e8ce497 Issue #1173692: Add a page showing the top 50 users who have been denied access to jPlayer files.
deviantintegral’s picture

Version: 7.x-2.x-dev » 6.x-1.0-beta3
deviantintegral’s picture

Two more. The big change is that private downloading can be enabled even if the access is public, in case a custom .htaccess rule is redirecting access to system/files.

  • 188c685 Issue #1173692: Allow setting protected access for media in case the site has .htaccess or other configuration enforcing private files for the media.
  • 9fe3901 Issue #1173692: Check for unencoded URLs as mod_rewrite will decode URL entities.
deviantintegral’s picture

Implementing hook_install() and uninstalling our variables in hook_uninstall().

deviantintegral’s picture

Here's an additional fix that cleans up detecting when the "playlist" player is in use. Otherwise, the wrong file path is sent to the server. This adds a playerType variable to the player that can easily be used by other JS functions.

deviantintegral’s picture

I curse IE to as much pain as it has caused me.

izmeez’s picture

subscribing

deviantintegral’s picture

Version: 6.x-1.0-beta3 » 7.x-2.x-dev

This needs to be ported to 7.x-2.x. It's large enough that I'm hesitant to commit it to 6.x-1.x by itself.

deviantintegral’s picture

Here's an untested reroll against the latest 6.x-1.x. Once I've tested that the rebase didn't break anything, I'll start porting to 7.x-2.x.

deviantintegral’s picture

Status: Needs review » Fixed
FileSize
36.21 KB

I've attached a patch porting all of the changes to 7.x-2.x. I've posted it here for reference, but I'll be committing a squashed version of it along with the 6.x-1.x version.

Everything works in the 7.x-2.x version, but there are still some TODOs left. I'm going to file separate issues for everything else left to be done.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.