pfdp.module in Private files download permission 8.2
Same filename and directory in other branches
Implements the main module function and generic helper functions.
File
pfdp.moduleView source
<?php
/**
* @file
* Implements the main module function and generic helper functions.
*/
use Drupal\pfdp\Entity\DirectoryEntity;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
/**
* Returns a properly formatted user string to be used in a log line.
*/
function pfdp_get_user_log_details($user) {
if (!$user) {
return NULL;
}
return $user
->id() . ' (' . ($user
->getAccountName() ? $user
->getAccountName() : '-') . ', ' . ($user
->getDisplayName() ? $user
->getDisplayName() : '-') . ')';
}
/**
* Returns an array of users with no '0' values, as '0' means 'unchecked'.
*/
function pfdp_get_proper_user_array($users) {
while (in_array('0', $users)) {
$k = array_search('0', $users);
unset($users[$k]);
}
return $users;
}
/**
* Returns a proper array to be used for downloads.
*/
function pfdp_get_download_headers($uri) {
$settings = \Drupal::config('pfdp.settings');
//
if ($settings
->get('attachment_mode')) {
return [
'Content-Type' => \Drupal::service('file.mime_type.guesser')
->guess($uri),
'Content-Disposition' => 'attachment; filename=' . \Drupal::service('file_system')
->basename($uri),
];
}
else {
return [
'Content-Type' => \Drupal::service('file.mime_type.guesser')
->guess($uri),
'Content-Disposition' => 'inline',
];
}
}
/**
* Forces a file to be downloaded to the browser.
*/
function pfdp_force_download($uri, $uri_download_headers) {
// Create a response here and send it to the browser.
$file = new BinaryFileResponse($uri, 200, $uri_download_headers, false);
$file
->send();
// Exit to avoid duplication of HTTP transmission.
exit;
}
/**
* {@inheritdoc}
*/
function pfdp_file_download($uri) {
$settings = \Drupal::config('pfdp.settings');
$logger = \Drupal::logger('pfdp');
$user = \Drupal::currentUser();
// Check if $uri is valid.
if ('://' === mb_substr($uri, -3, 3) || is_dir($uri)) {
$logger
->warning('Invalid uri: "%uri".', [
'%uri' => $uri,
]);
return -1;
}
// Retrieve the download headers for $uri.
$uri_download_headers = pfdp_get_download_headers($uri);
// Check if the user may bypass permission restrictions.
if ($user
->hasPermission('bypass pfdp')) {
if ($settings
->get('debug_mode')) {
$logger
->info('User %user granted permission to download uri "%uri".', [
'%user' => pfdp_get_user_log_details($user),
'%uri' => $uri,
]);
}
return $settings
->get('override_mode') ? pfdp_force_download($uri, $uri_download_headers) : $uri_download_headers;
}
elseif ($user
->hasPermission('bypass pfdp for temporary files') && 'temporary://' === mb_substr($uri, 0, 12)) {
if ($settings
->get('debug_mode')) {
$logger
->info('User %user granted permission to download uri "%uri".', [
'%user' => pfdp_get_user_log_details($user),
'%uri' => $uri,
]);
}
return $settings
->get('override_mode') ? pfdp_force_download($uri, $uri_download_headers) : $uri_download_headers;
}
else {
// Extract the path from $uri, removing the protocol prefix and the file name.
$uri_path = array_slice(explode('/', $uri), 2, -1);
// Add a leading slash to $uri_path.
$uri_path = '/' . implode('/', $uri_path);
// Find the directory which best matches $uri_path.
$best_matching_length = 0;
$best_matching_directory = NULL;
foreach (DirectoryEntity::loadMultiple() as $directory) {
// Search for the best matching substring.
$directory_path = $directory->path;
if (0 === stripos($uri_path, $directory_path)) {
if ($best_matching_length < mb_strlen($directory_path)) {
$best_matching_length = mb_strlen($directory_path);
$best_matching_directory = $directory;
}
}
}
if (NULL != $best_matching_directory) {
// Check if this module should ignore the call.
if ($best_matching_directory->bypass) {
return NULL;
}
// Check if the file owner is allowed to access $uri.
if ($best_matching_directory->grant_file_owners) {
$files = \Drupal::entityTypeManager()
->getStorage('file')
->loadByProperties([
'uri' => $uri,
]);
if (!empty($files)) {
$file = array_shift($files);
if ($file
->getOwnerId() == $user
->id()) {
if ($settings
->get('debug_mode')) {
$logger
->info('User %user granted permission to download uri "%uri".', [
'%user' => pfdp_get_user_log_details($user),
'%uri' => $uri,
]);
}
return $settings
->get('override_mode') ? pfdp_force_download($uri, $uri_download_headers) : $uri_download_headers;
}
}
}
// Evaluate user and role permissions and optionally allow access to $uri.
if ($settings
->get('by_user_checks')) {
if (in_array($user
->id(), pfdp_get_proper_user_array($best_matching_directory->users))) {
if ($settings
->get('debug_mode')) {
$logger
->info('User %user granted permission to download uri "%uri".', [
'%user' => pfdp_get_user_log_details($user),
'%uri' => $uri,
]);
}
return $settings
->get('override_mode') ? pfdp_force_download($uri, $uri_download_headers) : $uri_download_headers;
}
}
foreach ($user
->getRoles() as $rid) {
if (in_array($rid, $best_matching_directory->roles)) {
if ($settings
->get('debug_mode')) {
$logger
->info('User %user granted permission to download uri "%uri".', [
'%user' => pfdp_get_user_log_details($user),
'%uri' => $uri,
]);
}
return $settings
->get('override_mode') ? pfdp_force_download($uri, $uri_download_headers) : $uri_download_headers;
}
}
}
}
// By default, deny access.
if ($settings
->get('debug_mode')) {
$logger
->warning('User %user denied permission to download uri "%uri".', [
'%user' => pfdp_get_user_log_details($user),
'%uri' => $uri,
]);
}
return -1;
}
Functions
Name | Description |
---|---|
pfdp_file_download | |
pfdp_force_download | Forces a file to be downloaded to the browser. |
pfdp_get_download_headers | Returns a proper array to be used for downloads. |
pfdp_get_proper_user_array | Returns an array of users with no '0' values, as '0' means 'unchecked'. |
pfdp_get_user_log_details | Returns a properly formatted user string to be used in a log line. |