diff --git a/Classes/Aspects/PublicUrlAspect.php b/Classes/Aspects/PublicUrlAspect.php
index c1f43a5..1313e0e 100644
--- a/Classes/Aspects/PublicUrlAspect.php
+++ b/Classes/Aspects/PublicUrlAspect.php
@@ -25,7 +25,7 @@
***************************************************************/
use TYPO3\CMS\Core\Resource;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -90,17 +90,17 @@ public function generatePublicUrl(
$queryParameterArray['p'] = $resourceObject->getUid();
$queryParameterArray['t'] = 'p';
}
- $queryParameterArray['token'] = GeneralUtility::hmac(
+ $queryParameterArray['fal_token'] = GeneralUtility::hmac(
implode('|', $queryParameterArray),
'BeResourceStorageDumpFile'
);
// $urlData['publicUrl'] is passed by reference, so we can change that here and the value will be taken into account
- $urlData['publicUrl'] = BackendUtility::getAjaxUrl(
- 'FalSecuredownload::publicUrl',
+ $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+ $urlData['publicUrl'] = (string) $uriBuilder->buildUriFromRoute(
+ 'ajax_dump_file',
$queryParameterArray,
- false,
- true
+ UriBuilder::ABSOLUTE_URL
);
}
}
diff --git a/Classes/Configuration/ExtensionConfiguration.php b/Classes/Configuration/ExtensionConfiguration.php
index 364eb63..83f6b80 100644
--- a/Classes/Configuration/ExtensionConfiguration.php
+++ b/Classes/Configuration/ExtensionConfiguration.php
@@ -25,6 +25,9 @@
namespace BeechIt\FalSecuredownload\Configuration;
+use TYPO3\CMS\Core\Configuration\ExtensionConfiguration as ExtensionConfigurationCore;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
/**
* Wrapper for the extension configuration
*/
@@ -42,14 +45,18 @@ private static function init()
{
if (!self::$isInitialized) {
self::$isInitialized = true;
-
- $extensionConfig = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['fal_securedownload']);
+ if (class_exists(ExtensionConfigurationCore::class)) {
+ $extensionConfig = GeneralUtility::makeInstance(ExtensionConfigurationCore::class)->get('fal_securedownload');
+ } else {
+ // Fallback for 8LTS
+ $extensionConfig = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['fal_securedownload']);
+ }
self::$loginRedirectUrl = $extensionConfig['login_redirect_url'];
self::$noAccessRedirectUrl = $extensionConfig['no_access_redirect_url'];
self::$forceDownload = (bool)$extensionConfig['force_download'];
self::$forceDownloadForExt = $extensionConfig['force_download_for_ext'];
self::$trackDownloads = (bool)$extensionConfig['track_downloads'];
- self::$resumableDownload = (bool)(isset($extensionConfig['resumable_download']) ? $extensionConfig['resumable_download'] : false);
+ self::$resumableDownload = (isset($extensionConfig['resumable_download']) ? (bool)$extensionConfig['resumable_download'] : false);
}
}
diff --git a/Classes/ContextMenu/ItemProvider.php b/Classes/ContextMenu/ItemProvider.php
new file mode 100644
index 0000000..8cb5684
--- /dev/null
+++ b/Classes/ContextMenu/ItemProvider.php
@@ -0,0 +1,106 @@
+table === 'sys_file' || $this->table === 'sys_file_storage';
+ }
+
+ /**
+ * Initialize file object
+ */
+ protected function initialize()
+ {
+ parent::initialize();
+ $resource = ResourceFactory::getInstance()
+ ->retrieveFileOrFolderObject($this->identifier);
+
+ if ($resource instanceof Folder
+ && !$resource->getStorage()->isPublic()
+ && in_array(
+ $resource->getRole(),
+ [Folder::ROLE_DEFAULT, Folder::ROLE_USERUPLOAD],
+ true
+ )
+ ) {
+ $this->folder = $resource;
+ }
+ }
+
+ /**
+ * Adds the folder permission menu item for folder of a non-public storage
+ *
+ * @param array $items
+ * @return array
+ */
+ public function addItems(array $items): array
+ {
+ $this->initialize();
+ if ($this->folder instanceof Folder) {
+
+ $items += $this->prepareItems([
+ 'permissions_divider' => [
+ 'type' => 'divider',
+ ],
+ 'permissions' => [
+ 'label' => 'LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_be.xlf:clickmenu.folderpermissions',
+ 'iconIdentifier' => 'action-folder',
+ 'callbackAction' => 'folderPermissions'
+ ]
+ ]);
+ }
+
+ return $items;
+ }
+
+ /**
+ * @param string $itemName
+ * @return array
+ */
+ protected function getAdditionalAttributes(string $itemName): array
+ {
+ /** @var Utility $utility */
+ $utility = GeneralUtility::makeInstance(Utility::class);
+ $folderRecord = $utility->getFolderRecord($this->folder);
+
+ return [
+ 'data-callback-module' => 'TYPO3/CMS/FalSecuredownload/ContextMenuActions',
+ 'data-folder-record-uid' => $folderRecord['uid'] ?? 0,
+ 'data-storage' => $this->folder->getStorage()->getUid(),
+ 'data-folder' => $this->folder->getIdentifier(),
+ 'data-folder-hash' => $this->folder->getHashedIdentifier(),
+ ];
+ }
+}
\ No newline at end of file
diff --git a/Classes/Controller/BePublicUrlController.php b/Classes/Controller/BePublicUrlController.php
index d416143..6982cc7 100644
--- a/Classes/Controller/BePublicUrlController.php
+++ b/Classes/Controller/BePublicUrlController.php
@@ -7,7 +7,8 @@
* All code (c) Beech Applications B.V. all rights reserved
*/
-use TYPO3\CMS\Core\Http\AjaxRequestHandler;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Resource\ProcessedFileRepository;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -18,15 +19,14 @@
*/
class BePublicUrlController
{
-
/**
* Dump file content
* Copy from /sysext/core/Resources/PHP/FileDumpEID.php
- *
- * @param array $params
- * @param AjaxRequestHandler $ajaxObj
+ * @param ServerRequestInterface $request
+ * @param ResponseInterface $response
+ * @return ResponseInterface
*/
- public function dumpFile($params = [], AjaxRequestHandler $ajaxObj = null)
+ public function dumpFile(ServerRequestInterface $request, ResponseInterface $response)
{
$parameters = ['eID' => 'dumpFile'];
if (GeneralUtility::_GP('t')) {
@@ -40,7 +40,7 @@ public function dumpFile($params = [], AjaxRequestHandler $ajaxObj = null)
}
if (GeneralUtility::hmac(implode('|', $parameters),
- 'BeResourceStorageDumpFile') === GeneralUtility::_GP('token')
+ 'BeResourceStorageDumpFile') === GeneralUtility::_GP('fal_token')
) {
if (isset($parameters['f'])) {
$file = ResourceFactory::getInstance()->getFileObject($parameters['f']);
@@ -52,7 +52,7 @@ public function dumpFile($params = [], AjaxRequestHandler $ajaxObj = null)
/** @var \TYPO3\CMS\Core\Resource\ProcessedFile $file */
$file = GeneralUtility::makeInstance(ProcessedFileRepository::class)->findByUid($parameters['p']);
if ($file->isDeleted()) {
- $file = null;
+ HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_404);
}
$orgFile = $file->getOriginalFile();
}
@@ -68,6 +68,7 @@ public function dumpFile($params = [], AjaxRequestHandler $ajaxObj = null)
ob_start();
$file->getStorage()->dumpFileContents($file);
+
exit;
} else {
HttpUtility::setResponseCodeAndExit(HttpUtility::HTTP_STATUS_403);
diff --git a/Classes/Domain/Repository/ProcessedFileRepository.php b/Classes/Domain/Repository/ProcessedFileRepository.php
index 7193616..e725fc3 100644
--- a/Classes/Domain/Repository/ProcessedFileRepository.php
+++ b/Classes/Domain/Repository/ProcessedFileRepository.php
@@ -50,17 +50,13 @@ public function findByUid($uid)
throw new \InvalidArgumentException('uid has to be integer.', 1316779798);
}
- if (version_compare(TYPO3_branch, '8.7', '>=')) {
- $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
- $row = $queryBuilder
- ->select('*')
- ->from($this->table)
- ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$uid, \PDO::PARAM_INT)))
- ->execute()
- ->fetch();
- } else {
- $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', $this->table, 'uid=' . (int)$uid);
- }
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($this->table);
+ $row = $queryBuilder
+ ->select('*')
+ ->from($this->table)
+ ->where($queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter((int)$uid, \PDO::PARAM_INT)))
+ ->execute()
+ ->fetch();
if (empty($row) || !is_array($row)) {
throw new \RuntimeException(
diff --git a/Classes/FormEngine/DownloadStatistics.php b/Classes/FormEngine/DownloadStatistics.php
index 314a1d7..7d7d3f1 100644
--- a/Classes/FormEngine/DownloadStatistics.php
+++ b/Classes/FormEngine/DownloadStatistics.php
@@ -27,7 +27,6 @@
use TYPO3\CMS\Backend\Form\AbstractNode;
use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Database\DatabaseConnection;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Lang\LanguageService;
@@ -51,33 +50,22 @@ public function render()
return $this->resultArray;
}
- if (version_compare(TYPO3_branch, '8.7', '>=')) {
- $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file');
- $statistics = $queryBuilder
- ->selectLiteral(
- $queryBuilder->getConnection()->getDatabasePlatform()->getCountExpression(
- $queryBuilder->quoteIdentifier('tx_falsecuredownload_download.file')
- ) . ' AS ' . $queryBuilder->quoteIdentifier('cnt'))
- ->addSelect('sys_file.name')
- ->from('sys_file')
- ->join('sys_file', 'tx_falsecuredownload_download', 'tx_falsecuredownload_download',
- $queryBuilder->expr()->eq('tx_falsecuredownload_download.file', $queryBuilder->quoteIdentifier('sys_file.uid'))
- )
- ->where($queryBuilder->expr()->eq('tx_falsecuredownload_download.feuser', $queryBuilder->createNamedParameter((int)$row['uid'], \PDO::PARAM_INT)))
- ->groupBy('sys_file.name')
- ->orderBy('sys_file.name')
- ->execute()
- ->fetchAll();
- } else {
- $db = $this->getDatabase();
- $statistics = $db->exec_SELECTgetRows(
- 'sys_file.name, count(tx_falsecuredownload_download.file) as cnt',
- 'sys_file JOIN tx_falsecuredownload_download ON tx_falsecuredownload_download.file = sys_file.uid
- AND tx_falsecuredownload_download.feuser = ' . (int)$row['uid'],
- '',
- 'sys_file.name'
- );
- }
+ $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file');
+ $statistics = $queryBuilder
+ ->selectLiteral(
+ $queryBuilder->getConnection()->getDatabasePlatform()->getCountExpression(
+ $queryBuilder->quoteIdentifier('tx_falsecuredownload_download.file')
+ ) . ' AS ' . $queryBuilder->quoteIdentifier('cnt'))
+ ->addSelect('sys_file.name')
+ ->from('sys_file')
+ ->join('sys_file', 'tx_falsecuredownload_download', 'tx_falsecuredownload_download',
+ $queryBuilder->expr()->eq('tx_falsecuredownload_download.file', $queryBuilder->quoteIdentifier('sys_file.uid'))
+ )
+ ->where($queryBuilder->expr()->eq('tx_falsecuredownload_download.feuser', $queryBuilder->createNamedParameter((int)$row['uid'], \PDO::PARAM_INT)))
+ ->groupBy('sys_file.name')
+ ->orderBy('sys_file.name')
+ ->execute()
+ ->fetchAll();
$lang = $this->getLanguageService();
$markup = [];
@@ -110,12 +98,4 @@ protected function getLanguageService()
{
return $GLOBALS['LANG'];
}
-
- /**
- * @return DatabaseConnection
- */
- protected function getDatabase()
- {
- return $GLOBALS['TYPO3_DB'];
- }
}
diff --git a/Classes/Hooks/AbstractBeButtons.php b/Classes/Hooks/AbstractBeButtons.php
index 7c6b732..15ac193 100644
--- a/Classes/Hooks/AbstractBeButtons.php
+++ b/Classes/Hooks/AbstractBeButtons.php
@@ -25,18 +25,18 @@
***************************************************************/
use BeechIt\FalSecuredownload\Service\Utility;
+use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Resource\Exception\InsufficientFolderAccessPermissionsException;
use TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException;
use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Resource\ResourceFactory;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
- * Abstract utility class for classes that want to add album add/edit buttons
- * somewhere like a ClickMenuOptions class.
+ * Abstract utility class for classes that want to add BE buttons
+ * to edit folder permissions
*/
abstract class AbstractBeButtons
{
@@ -153,7 +153,9 @@ protected function buildAddUrl(Folder $folder)
protected function buildUrl(array $parameters)
{
$parameters['returnUrl'] = GeneralUtility::getIndpEnv('REQUEST_URI');
- return BackendUtility::getModuleUrl('record_edit', $parameters);
+ $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+
+ return $uriBuilder->buildUriFromRoute('record_edit', $parameters);
}
/**
diff --git a/Classes/Hooks/ClickMenuOptions.php b/Classes/Hooks/ClickMenuOptions.php
deleted file mode 100644
index 2a813fa..0000000
--- a/Classes/Hooks/ClickMenuOptions.php
+++ /dev/null
@@ -1,92 +0,0 @@
-
- * All rights reserved
- *
- * This script is part of the TYPO3 project. The TYPO3 project is
- * free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * The GNU General Public License can be found at
- * http://www.gnu.org/copyleft/gpl.html.
- *
- * This script is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
-use TYPO3\CMS\Backend\ClickMenu\ClickMenu;
-use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
-
-/**
- * Add ClickMenuOptions in file list
- */
-class ClickMenuOptions extends AbstractBeButtons
-{
- /**
- * @var ClickMenu
- */
- protected $parentObject;
-
- /**
- * Add create tx_ icon to filemenu
- *
- * @param ClickMenu $parentObject Back-reference to the calling object
- * @param array $menuItems Current list of menu items
- * @param string $combinedIdentifier The combined identifier
- * @param integer $uid Id of the clicked on item
- * @return array Modified list of menu items
- */
- public function main(ClickMenu $parentObject, $menuItems, $combinedIdentifier, $uid)
- {
-
- if (!$parentObject->isDBmenu) {
- $this->parentObject = $parentObject;
- $combinedIdentifier = rawurldecode($combinedIdentifier);
-
- $extraMenuItems = $this->generateButtons($combinedIdentifier);
- if (count($extraMenuItems)) {
- $menuItems[] = 'spacer';
- $menuItems = array_merge($menuItems, $extraMenuItems);
- }
- }
-
- return $menuItems;
- }
-
- /**
- * Create click menu item
- *
- * @param string $title
- * @param string $shortTitle
- * @param string $icon
- * @param string $url
- * @param bool $addReturnUrl
- * @return string|array
- */
- protected function createLink($title, $shortTitle, $icon, $url, $addReturnUrl = true)
- {
-
- if (strpos($url, 'alert') !== 0) {
- $url = $this->parentObject->urlRefForCM($url, $addReturnUrl ? 'returnUrl' : '');
- }
-
- /** @var BackendUserAuthentication $beUser */
- $beUser = $GLOBALS['BE_USER'];
-
- return $this->parentObject->linkItem(
- '' . $shortTitle . '',
- !empty($beUser->uc['noMenuMode']) && $beUser->uc['noMenuMode'] !== 'icons' ? '' : ' ' . $icon,
- $url
- );
- }
-}
diff --git a/Classes/Hooks/CmsLayout.php b/Classes/Hooks/CmsLayout.php
index cbc94f1..53f0d9e 100644
--- a/Classes/Hooks/CmsLayout.php
+++ b/Classes/Hooks/CmsLayout.php
@@ -137,15 +137,13 @@ protected function getFieldFromFlexform($key, $sheet = 'sDEF')
*
* @param string $key
* @param string $languageFile
- * @param bool $hsc If set, the return value is htmlspecialchar'ed
* @return string
*/
protected function sL(
$key,
- $languageFile = 'LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_be.xlf',
- $hsc = true
+ $languageFile = 'LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_be.xlf'
) {
- return $this->getLangService()->sL($languageFile . ':' . $key, $hsc);
+ return $this->getLangService()->sL($languageFile . ':' . $key);
}
/**
diff --git a/Classes/Hooks/DocHeaderButtonsHook.php b/Classes/Hooks/DocHeaderButtonsHook.php
index ce0bd2d..6d5a6ee 100644
--- a/Classes/Hooks/DocHeaderButtonsHook.php
+++ b/Classes/Hooks/DocHeaderButtonsHook.php
@@ -1,4 +1,5 @@
= 9LTS
+ ) {
foreach ($this->generateButtons(GeneralUtility::_GP('id')) as $buttonInfo) {
$button = $buttonBar->makeLinkButton();
$button->setIcon($buttonInfo['icon']);
diff --git a/Classes/Hooks/FileDumpHook.php b/Classes/Hooks/FileDumpHook.php
index d850dcd..cd02f04 100644
--- a/Classes/Hooks/FileDumpHook.php
+++ b/Classes/Hooks/FileDumpHook.php
@@ -28,9 +28,9 @@
use BeechIt\FalSecuredownload\Configuration\ExtensionConfiguration;
use BeechIt\FalSecuredownload\Security\CheckPermissions;
use TYPO3\CMS\Core\Database\ConnectionPool;
-use TYPO3\CMS\Core\Database\DatabaseConnection;
use TYPO3\CMS\Core\Resource\File;
use TYPO3\CMS\Core\Resource\FileInterface;
+use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Core\Resource\Hook\FileDumpEIDHookInterface;
use TYPO3\CMS\Core\Resource\ResourceInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -138,13 +138,13 @@ public function checkFileAccess(ResourceInterface $file)
if ($this->loginRedirectUrl !== null) {
$this->redirectToUrl($this->loginRedirectUrl);
} else {
- $this->exitScript('Authentication required!', 401);
+ $this->exitScript('Authentication required!');
}
} else {
if ($this->noAccessRedirectUrl !== null) {
$this->redirectToUrl($this->noAccessRedirectUrl);
} else {
- $this->exitScript('No access!', 403);
+ $this->exitScript('No access!');
}
}
}
@@ -161,25 +161,22 @@ public function checkFileAccess(ResourceInterface $file)
'file' => (int)$this->originalFile->getUid()
];
- if (version_compare(TYPO3_branch, '8.7', '>=')) {
- GeneralUtility::makeInstance(ConnectionPool::class)
- ->getConnectionForTable('tx_falsecuredownload_download')
- ->insert(
- 'tx_falsecuredownload_download',
- $columns,
- [\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT]
- );
-
- } else {
- $db = $this->getDatabase();
- $db->exec_INSERTquery('tx_falsecuredownload_download', $columns);
- }
+ GeneralUtility::makeInstance(ConnectionPool::class)
+ ->getConnectionForTable('tx_falsecuredownload_download')
+ ->insert(
+ 'tx_falsecuredownload_download',
+ $columns,
+ [\PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT, \PDO::PARAM_INT]
+ );
}
- if ($this->forceDownload($this->originalFile->getExtension())) {
- $this->dumpFileContents($this->originalFile, true, $this->resumableDownload);
+ // Dump the precise requested file for File and ProcessedFile, but dump the referenced file for FileReference
+ $dumpFile = $file instanceof FileReference ? $file->getOriginalFile() : $file;
+
+ if ($this->forceDownload($dumpFile->getExtension())) {
+ $this->dumpFileContents($dumpFile, true, $this->resumableDownload);
} elseif ($this->resumableDownload) {
- $this->dumpFileContents($this->originalFile, false, true);
+ $this->dumpFileContents($dumpFile, false, true);
}
}
@@ -195,13 +192,21 @@ public function checkFileAccess(ResourceInterface $file)
*/
protected function dumpFileContents($file, $asDownload, $resumableDownload)
{
+ $downloadName = $file->getProperty('download_name') ?: $file->getName();
+
+ // Make sure downloadName has a file extension
+ $fileParts = pathinfo($downloadName);
+ if (empty($fileParts['extension'])) {
+ $downloadName .= '.' . $file->getExtension();
+ }
+
if (!$resumableDownload) {
- $file->getStorage()->dumpFileContents($file, $asDownload);
+ $file->getStorage()->dumpFileContents($file, $asDownload, $downloadName);
exit;
}
$contentDisposition = $asDownload ? 'attachment' : 'inline';
- header('Content-Disposition: ' . $contentDisposition . '; filename="' . $file->getName() . '"');
+ header('Content-Disposition: ' . $contentDisposition . '; filename="' . $downloadName . '"');
header('Content-Type: ' . $file->getMimeType());
header('Expires: -1');
header('Cache-Control: public, must-revalidate, post-check=0, pre-check=0');
@@ -213,6 +218,13 @@ protected function dumpFileContents($file, $asDownload, $resumableDownload)
header('Content-Range: bytes */' . $fileSize);
exit;
}
+
+ // Find part of file and push this out
+ $filePointer = @fopen($file->getForLocalProcessing(false), 'rb');
+ if ($filePointer === false) {
+ header('HTTP/1.1 404 File not found');
+ exit;
+ }
$dumpSize = $fileSize;
list($begin, $end) = $range;
@@ -230,8 +242,6 @@ protected function dumpFileContents($file, $asDownload, $resumableDownload)
ob_end_clean();
}
- // Find part of file and push this out
- $filePointer = @fopen($file->getForLocalProcessing(false), 'rb');
fseek($filePointer, $begin);
$dumpedSize = 0;
while (!feof($filePointer) && $dumpedSize < $dumpSize) {
@@ -340,14 +350,6 @@ protected function redirectToUrl($url)
exit;
}
- /**
- * @return DatabaseConnection
- */
- protected function getDatabase()
- {
- return $GLOBALS['TYPO3_DB'];
- }
-
/**
* Determines the HTTP range given in the request
*
diff --git a/Classes/Service/Utility.php b/Classes/Service/Utility.php
index 1430df6..9fd491a 100644
--- a/Classes/Service/Utility.php
+++ b/Classes/Service/Utility.php
@@ -54,7 +54,7 @@ public function __construct()
* Get folder configuration record
*
* @param Folder $folder
- * @return array
+ * @return array|false
*/
public function getFolderRecord(Folder $folder)
{
@@ -62,27 +62,15 @@ public function getFolderRecord(Folder $folder)
if (!isset(self::$folderRecordCache[$folder->getCombinedIdentifier()])
|| !array_key_exists($folder->getCombinedIdentifier(), self::$folderRecordCache)
) {
- if (version_compare(TYPO3_branch, '8.7', '>=')) {
-
- $queryBuilder = $this->getQueryBuilder();
- $record = $queryBuilder
- ->select('*')
- ->from('tx_falsecuredownload_folder')
- ->where($queryBuilder->expr()->eq('storage', $queryBuilder->createNamedParameter((int)$folder->getStorage()->getUid(), \PDO::PARAM_INT)))
- ->andWhere($queryBuilder->expr()->eq('folder_hash', $queryBuilder->createNamedParameter($folder->getHashedIdentifier(), \PDO::PARAM_STR)))
- ->execute()
- ->fetch();
-
- } else {
-
- $record = $this->getDatabase()->exec_SELECTgetSingleRow(
- '*',
- 'tx_falsecuredownload_folder',
- 'storage = ' . (int)$folder->getStorage()->getUid() . '
- AND folder_hash = ' . $this->getDatabase()->fullQuoteStr($folder->getHashedIdentifier(), 'tx_falsecuredownload_folder')
- );
+ $queryBuilder = $this->getQueryBuilder();
+ $record = $queryBuilder
+ ->select('*')
+ ->from('tx_falsecuredownload_folder')
+ ->where($queryBuilder->expr()->eq('storage', $queryBuilder->createNamedParameter((int)$folder->getStorage()->getUid(), \PDO::PARAM_INT)))
+ ->andWhere($queryBuilder->expr()->eq('folder_hash', $queryBuilder->createNamedParameter($folder->getHashedIdentifier(), \PDO::PARAM_STR)))
+ ->execute()
+ ->fetch();
- }
// cache results
self::$folderRecordCache[$folder->getCombinedIdentifier()] = $record;
}
@@ -170,16 +158,6 @@ public function deleteFolderRecord($storageUid, $folderHash, $identifier)
}
}
- /**
- * Gets the database object.
- *
- * @return \TYPO3\CMS\Core\Database\DatabaseConnection
- */
- protected function getDatabase()
- {
- return $GLOBALS['TYPO3_DB'];
- }
-
/**
* Gets a query build
*
diff --git a/Classes/ViewHelpers/LeaveStateViewHelper.php b/Classes/ViewHelpers/LeaveStateViewHelper.php
index bbac1f7..75dd495 100644
--- a/Classes/ViewHelpers/LeaveStateViewHelper.php
+++ b/Classes/ViewHelpers/LeaveStateViewHelper.php
@@ -44,23 +44,30 @@ public function initializeArguments()
}
/**
- * renders child if the current visitor ...
- * otherwise renders child.
-
- * @return string
+ * @param array $arguments
+ * @return bool
*/
- public function render()
+ protected static function evaluateCondition($arguments = null)
{
/** @var Folder $folder */
- $folder = $this->arguments['folder'];
+ $folder = $arguments['folder'];
$leafStateService = GeneralUtility::makeInstance(LeafStateService::class);
$feUser = !empty($GLOBALS['TSFE']) ? $GLOBALS['TSFE']->fe_user : false;
- if ($feUser && $leafStateService->getLeafStateForUser($feUser, $folder->getCombinedIdentifier())) {
+ return $feUser && $leafStateService->getLeafStateForUser($feUser, $folder->getCombinedIdentifier());
+ }
+
+ /**
+ * Renders child if $condition is true, otherwise renders child.
+ *
+ * @return string the rendered string
+ */
+ public function render()
+ {
+ if (static::evaluateCondition($this->arguments)) {
return $this->renderThenChild();
- } else {
- return $this->renderElseChild();
}
+ return $this->renderElseChild();
}
}
diff --git a/Classes/ViewHelpers/Security/AssetAccessViewHelper.php b/Classes/ViewHelpers/Security/AssetAccessViewHelper.php
index 10072a6..0b4ced3 100644
--- a/Classes/ViewHelpers/Security/AssetAccessViewHelper.php
+++ b/Classes/ViewHelpers/Security/AssetAccessViewHelper.php
@@ -24,6 +24,7 @@
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
+use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Resource\Folder;
use TYPO3\CMS\Core\Resource\File;
@@ -92,13 +93,23 @@ protected static function evaluateCondition($arguments = null)
/**
* Determines whether the currently logged in FE user belongs to the specified usergroup
*
- * @return boolean|array FALSE when not logged in or else $GLOBALS['TSFE']->fe_user->groupData['uid']
+ * @return boolean|array FALSE when not logged in or else frontend.user.groupIds
*/
protected static function getFeUserGroups()
{
- if (!isset($GLOBALS['TSFE']) || !$GLOBALS['TSFE']->loginUser) {
- return false;
+ if (class_exists(Context::class)) {
+ $context = GeneralUtility::makeInstance(Context::class);
+ if (!$context->getPropertyFromAspect('frontend.user', 'isLoggedIn')) {
+ return false;
+ }
+ return $context->getPropertyFromAspect('frontend.user', 'groupIds');
+ } else {
+ // Fallback for 8LTS
+ if (!isset($GLOBALS['TSFE']) || !$GLOBALS['TSFE']->loginUser) {
+ return false;
+ }
+ return $GLOBALS['TSFE']->fe_user->groupData['uid'];
}
- return $GLOBALS['TSFE']->fe_user->groupData['uid'];
+
}
}
\ No newline at end of file
diff --git a/Configuration/Backend/AjaxRoutes.php b/Configuration/Backend/AjaxRoutes.php
new file mode 100644
index 0000000..8e6ec4f
--- /dev/null
+++ b/Configuration/Backend/AjaxRoutes.php
@@ -0,0 +1,7 @@
+ [
+ 'path' => '/fal_securedownloads/dump_file',
+ 'target' => BeechIt\FalSecuredownload\Controller\BePublicUrlController::class . '::dumpFile'
+ ]
+];
diff --git a/Configuration/TCA/Overrides/sys_file_metadata.php b/Configuration/TCA/Overrides/sys_file_metadata.php
index 8003803..428bf37 100644
--- a/Configuration/TCA/Overrides/sys_file_metadata.php
+++ b/Configuration/TCA/Overrides/sys_file_metadata.php
@@ -4,7 +4,7 @@
$additionalColumns = [
'fe_groups' => [
'exclude' => true,
- 'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.fe_group',
+ 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.fe_group',
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
@@ -12,20 +12,33 @@
'maxitems' => 20,
'items' => [
[
- 'LLL:EXT:lang/locallang_general.xlf:LGL.any_login',
+ 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.any_login',
-2
],
[
- 'LLL:EXT:lang/locallang_general.xlf:LGL.usergroups',
+ 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.usergroups',
'--div--'
]
],
'exclusiveKeys' => '-1,-2',
'foreign_table' => 'fe_groups',
- 'foreign_table_where' => 'ORDER BY fe_groups.title'
+ 'foreign_table_where' => 'ORDER BY fe_groups.title',
+ 'enableMultiSelectFilterTextfield' => true,
]
+ ],
+ 'download_name' => [
+ 'exclude' => true,
+ 'label' => 'LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_db.xlf:downloadName',
+ 'description' => 'LLL:EXT:fal_securedownload/Resources/Private/Language/locallang_db.xlf:downloadName.description',
+ 'config' => [
+ 'type' => 'input',
+ 'size' => '255',
+ 'max' => '255',
+ ]
]
];
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns('sys_file_metadata', $additionalColumns);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('sys_file_metadata', 'fe_groups');
+
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes('sys_file_metadata', 'download_name','', 'after:alternative');
\ No newline at end of file
diff --git a/Configuration/TCA/tx_falsecuredownload_folder.php b/Configuration/TCA/tx_falsecuredownload_folder.php
index 38bcd37..5de07ff 100644
--- a/Configuration/TCA/tx_falsecuredownload_folder.php
+++ b/Configuration/TCA/tx_falsecuredownload_folder.php
@@ -59,7 +59,7 @@
],
'fe_groups' => [
'exclude' => false,
- 'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.fe_group',
+ 'label' => 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.fe_group',
'config' => [
'type' => 'select',
'renderType' => 'selectMultipleSideBySide',
@@ -67,17 +67,18 @@
'maxitems' => 40,
'items' => [
[
- 'LLL:EXT:lang/locallang_general.xlf:LGL.any_login',
+ 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.any_login',
-2
],
[
- 'LLL:EXT:lang/locallang_general.xlf:LGL.usergroups',
+ 'LLL:EXT:lang/Resources/Private/Language/locallang_general.xlf:LGL.usergroups',
'--div--'
]
],
'exclusiveKeys' => '-1,-2',
'foreign_table' => 'fe_groups',
- 'foreign_table_where' => 'ORDER BY fe_groups.title'
+ 'foreign_table_where' => 'ORDER BY fe_groups.title',
+ 'enableMultiSelectFilterTextfield' => true,
]
]
]
diff --git a/Documentation/Images/secure-file-storage.png b/Documentation/Images/secure-file-storage.png
index cff8ad6..8074d75 100644
Binary files a/Documentation/Images/secure-file-storage.png and b/Documentation/Images/secure-file-storage.png differ
diff --git a/Documentation/Images/set-folder-permissions.png b/Documentation/Images/set-folder-permissions.png
index bb6a2f0..eef158f 100644
Binary files a/Documentation/Images/set-folder-permissions.png and b/Documentation/Images/set-folder-permissions.png differ
diff --git a/Documentation/Images/set-folder-permissions2.png b/Documentation/Images/set-folder-permissions2.png
new file mode 100644
index 0000000..e56279e
Binary files /dev/null and b/Documentation/Images/set-folder-permissions2.png differ
diff --git a/Documentation/Misc/Index.rst b/Documentation/Misc/Index.rst
index f67c0d2..36a252e 100644
--- a/Documentation/Misc/Index.rst
+++ b/Documentation/Misc/Index.rst
@@ -85,9 +85,24 @@ To have correct urls to indexed files you need to add/adjust following ext:solr
.. code-block:: ts
+ # Make sure the correct public URL is indexed
plugin.tx_solr.index.queue._FILES.default.filePublicUrl = public_url
plugin.tx_solr.index.queue._FILES.default.url = public_url
+ # Make sure the fe_groups are considered
+ plugin.tx_solr.index.queue._FILES.default.access = TEXT
+ plugin.tx_solr.index.queue._FILES.default.access {
+ value = r:0
+ override {
+ cObject = TEXT
+ cObject {
+ required = 1
+ field = fe_groups
+ wrap = r:|
+ }
+ }
+ }
+
*This feature is sponsored by: STIMME DER HOFFNUNG Adventist Media Center*
diff --git a/README.rst b/README.md
similarity index 82%
rename from README.rst
rename to README.md
index d5e2e55..a4c1656 100644
--- a/README.rst
+++ b/README.md
@@ -1,5 +1,5 @@
FAL SecureDownLoad
-==================
+===
This extension (fal_securedownload) aims to be a general solution to secure your assets.
@@ -7,15 +7,14 @@ When you storage is marked as non-public all links to files from that storage ar
The access to assets can be set on folder/file bases by setting access to fe_groups in the file module.
-**How to use:**
+### How to use
1. Download and install fal_securedownload
-
2. Un-check the 'public' checkbox in your file storage
-
3. Add a .htaccess file with "Deny from all" (Apache < 2.3) or "Require all denied" (Apache >= 2.3) in your file storage root folder or move your storage outside of your webroot
+4. Go to the file list and add access restrictions on file/folder
-**Features**
+### Features
- Restrict FE access on folder level
- Restrict FE access on file level
@@ -24,10 +23,10 @@ The access to assets can be set on folder/file bases by setting access to fe_gro
- Force download for specific file extensions (for protected file storages)
- Keep track of requested downloads (count downloads per user and file)
-**Requirements:**
- TYPO3 7 LTS, TYPO3 8
+### Requirements
+- TYPO3 8 LTS or TYPO3 9 LTS
-**Suggestions:**
- EXT:ke_search v1.8.4
- EXT:solrfal v4.1.0
+### Suggestions
+- EXT:ke_search v1.8.4
+- EXT:solrfal v4.1.0
diff --git a/Resources/Private/Language/locallang_db.xlf b/Resources/Private/Language/locallang_db.xlf
index 5f91bd2..a7b9781 100644
--- a/Resources/Private/Language/locallang_db.xlf
+++ b/Resources/Private/Language/locallang_db.xlf
@@ -13,7 +13,12 @@
Folder
-
+
+ Alternative Download name
+
+
+ Send File with an alternative Filename
+