Added backend route for protected thumbs, Fixes #1218, thanks @jBOKA

Improved the FileUpload widget code to no longer rely on "pathOverride"
This commit is contained in:
Samuel Georges 2015-06-20 11:27:03 +10:00
parent e6bfa5b970
commit c2c14e707f
7 changed files with 116 additions and 44 deletions

View File

@ -10,51 +10,75 @@ use Exception;
/**
* Backend files controller
*
* Used for delivering protected system files, and generating URLs
* for accessing them.
*
* @package october\backend
* @author Alexey Bobkov, Samuel Georges
*
*/
class Files extends Controller
{
/**
* Output file, or fall back on the 404 page
*/
public function get($code = null)
{
try {
if (!$code) {
throw new ApplicationException('Missing code');
}
$parts = explode('!', base64_decode($code));
if (count($parts) < 2) {
throw new ApplicationException('Invalid code');
}
list($id, $hash) = $parts;
if (!$file = FileModel::find((int) $id)) {
throw new ApplicationException('Unable to find file');
}
$verifyCode = self::getUniqueCode($file);
if ($code != $verifyCode) {
throw new ApplicationException('Invalid hash');
}
echo $file->output();
echo $this->findFileObject($code)->output();
exit;
}
catch (Exception $ex) {}
/*
* Fall back on Cms controller
*/
return App::make('Cms\Classes\Controller')->setStatusCode(404)->run('/404');
}
/**
* Output thumbnail, or fall back on the 404 page
*/
public function thumb($code = null, $width = 100, $height = 100, $mode = 'auto', $extension = 'auto')
{
try {
echo $this->findFileObject($code)->outputThumb(
$width,
$height,
compact('mode','extension')
);
exit;
}
catch (Exception $ex) {}
return App::make('Cms\Classes\Controller')->setStatusCode(404)->run('/404');
}
/**
* Returns the URL for downloading a system file.
* @param $file System\Models\File
* @return string
*/
public static function getDownloadUrl($file)
{
return Backend::url('backend/files/get/' . self::getUniqueCode($file));
}
/**
* Returns the URL for downloading a system file.
* @param $file System\Models\File
* @param $width int
* @param $height int
* @param $options array
* @return string
*/
public static function getThumbUrl($file, $width, $height, $options)
{
return Backend::url('backend/files/thumb/' . self::getUniqueCode($file)) . '/' . $width . '/' . $height . '/' . $options['mode'] . '/' . $options['extension'];
}
/**
* Returns a unique code used for masking the file identifier.
* @param $file System\Models\File
* @return string
*/
public static function getUniqueCode($file)
{
if (!$file) {
@ -64,4 +88,34 @@ class Files extends Controller
$hash = md5($file->file_name . '!' . $file->disk_name);
return base64_encode($file->id . '!' . $hash);
}
}
/**
* Locates a file model based on the unique code.
* @param $code string
* @return System\Models\File
*/
protected function findFileObject($code)
{
if (!$code) {
throw new ApplicationException('Missing code');
}
$parts = explode('!', base64_decode($code));
if (count($parts) < 2) {
throw new ApplicationException('Invalid code');
}
list($id, $hash) = $parts;
if (!$file = FileModel::find((int) $id)) {
throw new ApplicationException('Unable to find file');
}
$verifyCode = self::getUniqueCode($file);
if ($code != $verifyCode) {
throw new ApplicationException('Invalid hash');
}
return $file;
}
}

View File

@ -9,6 +9,7 @@ use System\Models\File;
use ApplicationException;
use Backend\Classes\FormField;
use Backend\Classes\FormWidgetBase;
use Backend\Controllers\Files as FilesController;
use ValidationException;
use Exception;
@ -116,8 +117,8 @@ class FileUpload extends FormWidgetBase
*/
protected function prepareVars()
{
$this->vars['fileList'] = $this->getFileList();
$this->vars['singleFile'] = array_get($this->vars['fileList'], 0, null);
$this->vars['fileList'] = $fileList = $this->getFileList();
$this->vars['singleFile'] = $fileList->first();
$this->vars['displayMode'] = $this->getDisplayMode();
$this->vars['emptyIcon'] = $this->getConfig('emptyIcon', 'icon-plus');
$this->vars['imageHeight'] = $this->imageHeight;
@ -386,8 +387,8 @@ class FileUpload extends FormWidgetBase
$result = [
'id' => $file->id,
'thumb' => $file->thumb,
'path' => $file->path
'thumb' => $file->thumbUrl,
'path' => $file->pathUrl
];
Response::json($result, 200)->send();
@ -401,19 +402,36 @@ class FileUpload extends FormWidgetBase
}
/**
* Adds the bespoke thumb and path property used by this widget.
* Adds the bespoke attributes used internally by this widget.
* - thumbUrl
* - pathUrl
* @return System\Models\File
*/
protected function decorateFileAttributes($file)
{
$file->thumb = ($this->imageWidth || $this->imageHeight)
? $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions)
: $file->path;
/*
* File is protected, create a secure public path
*/
if (!$file->isPublic()) {
$path = $thumb = FilesController::getDownloadUrl($file);
// Internal download link
if (!$file->isImage() || !$file->isPublic()) {
$file->pathOverride = \Backend\Controllers\Files::getDownloadUrl($file);
if ($this->imageWidth || $this->imageHeight) {
$thumb = FilesController::getThumbUrl($file, $this->imageWidth, $this->imageHeight, $this->thumbOptions);
}
}
/*
* Otherwise use public paths
*/
else {
$path = $thumb = $file->getPath();
if ($this->imageWidth || $this->imageHeight) {
$thumb = $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions);
}
}
$file->pathUrl = $path;
$file->thumbUrl = $thumb;
return $file;
}

View File

@ -6,7 +6,7 @@
<div class="file-upload-modal-image-header">
<button type="button" class="close" data-dismiss="popup">&times;</button>
<img
src="<?= $file->thumb ?>"
src="<?= $file->thumbUrl ?>"
class="img-responsive center-block"
alt=""
title="<?= e(trans('backend::lang.fileupload.attachment')) ?>: <?= e($file->file_name) ?>"
@ -39,7 +39,7 @@
</div>
<div class="modal-footer">
<a href="<?= $file->path ?>" class="pull-left btn btn-link fileupload-url-button" target="_blank">
<a href="<?= $file->pathUrl ?>" class="pull-left btn btn-link fileupload-url-button" target="_blank">
<i class="oc-icon-link"></i>Attachment URL
</a>
<button

View File

@ -18,7 +18,7 @@
<!-- Existing files -->
<div class="upload-files-container">
<?php foreach ($fileList as $file): ?>
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->path ?>">
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->pathUrl ?>">
<div class="icon-container">
<i class="icon-file"></i>
</div>

View File

@ -17,7 +17,7 @@
<!-- Existing file -->
<div class="upload-files-container">
<?php if ($singleFile): ?>
<div class="upload-object is-success" data-id="<?= $singleFile->id ?>" data-path="<?= $singleFile->path ?>">
<div class="upload-object is-success" data-id="<?= $singleFile->id ?>" data-path="<?= $singleFile->pathUrl ?>">
<div class="icon-container">
<i class="icon-file"></i>
</div>

View File

@ -18,9 +18,9 @@
<!-- Existing files -->
<div class="upload-files-container">
<?php foreach ($fileList as $file): ?>
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->path ?>">
<div class="upload-object is-success" data-id="<?= $file->id ?>" data-path="<?= $file->pathUrl ?>">
<div class="icon-container image">
<img src="<?= $file->thumb ?>" />
<img src="<?= $file->thumbUrl ?>" />
</div>
<div class="info">
<h4 class="filename">

View File

@ -20,9 +20,9 @@
<!-- Existing file -->
<div class="upload-files-container">
<?php if ($singleFile): ?>
<div class="upload-object is-success" data-id="<?= $singleFile->id ?>" data-path="<?= $singleFile->path ?>">
<div class="upload-object is-success" data-id="<?= $singleFile->id ?>" data-path="<?= $singleFile->pathUrl ?>">
<div class="icon-container image">
<img src="<?= $singleFile->thumb ?>" />
<img src="<?= $singleFile->thumbUrl ?>" />
</div>
<div class="info">
<h4 class="filename">