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:
parent
e6bfa5b970
commit
c2c14e707f
|
|
@ -10,51 +10,75 @@ use Exception;
|
||||||
/**
|
/**
|
||||||
* Backend files controller
|
* Backend files controller
|
||||||
*
|
*
|
||||||
|
* Used for delivering protected system files, and generating URLs
|
||||||
|
* for accessing them.
|
||||||
|
*
|
||||||
* @package october\backend
|
* @package october\backend
|
||||||
* @author Alexey Bobkov, Samuel Georges
|
* @author Alexey Bobkov, Samuel Georges
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Files extends Controller
|
class Files extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Output file, or fall back on the 404 page
|
||||||
|
*/
|
||||||
public function get($code = null)
|
public function get($code = null)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (!$code) {
|
echo $this->findFileObject($code)->output();
|
||||||
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();
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
catch (Exception $ex) {}
|
catch (Exception $ex) {}
|
||||||
|
|
||||||
/*
|
|
||||||
* Fall back on Cms controller
|
|
||||||
*/
|
|
||||||
return App::make('Cms\Classes\Controller')->setStatusCode(404)->run('/404');
|
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)
|
public static function getDownloadUrl($file)
|
||||||
{
|
{
|
||||||
return Backend::url('backend/files/get/' . self::getUniqueCode($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)
|
public static function getUniqueCode($file)
|
||||||
{
|
{
|
||||||
if (!$file) {
|
if (!$file) {
|
||||||
|
|
@ -64,4 +88,34 @@ class Files extends Controller
|
||||||
$hash = md5($file->file_name . '!' . $file->disk_name);
|
$hash = md5($file->file_name . '!' . $file->disk_name);
|
||||||
return base64_encode($file->id . '!' . $hash);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ use System\Models\File;
|
||||||
use ApplicationException;
|
use ApplicationException;
|
||||||
use Backend\Classes\FormField;
|
use Backend\Classes\FormField;
|
||||||
use Backend\Classes\FormWidgetBase;
|
use Backend\Classes\FormWidgetBase;
|
||||||
|
use Backend\Controllers\Files as FilesController;
|
||||||
use ValidationException;
|
use ValidationException;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
|
|
@ -116,8 +117,8 @@ class FileUpload extends FormWidgetBase
|
||||||
*/
|
*/
|
||||||
protected function prepareVars()
|
protected function prepareVars()
|
||||||
{
|
{
|
||||||
$this->vars['fileList'] = $this->getFileList();
|
$this->vars['fileList'] = $fileList = $this->getFileList();
|
||||||
$this->vars['singleFile'] = array_get($this->vars['fileList'], 0, null);
|
$this->vars['singleFile'] = $fileList->first();
|
||||||
$this->vars['displayMode'] = $this->getDisplayMode();
|
$this->vars['displayMode'] = $this->getDisplayMode();
|
||||||
$this->vars['emptyIcon'] = $this->getConfig('emptyIcon', 'icon-plus');
|
$this->vars['emptyIcon'] = $this->getConfig('emptyIcon', 'icon-plus');
|
||||||
$this->vars['imageHeight'] = $this->imageHeight;
|
$this->vars['imageHeight'] = $this->imageHeight;
|
||||||
|
|
@ -386,8 +387,8 @@ class FileUpload extends FormWidgetBase
|
||||||
|
|
||||||
$result = [
|
$result = [
|
||||||
'id' => $file->id,
|
'id' => $file->id,
|
||||||
'thumb' => $file->thumb,
|
'thumb' => $file->thumbUrl,
|
||||||
'path' => $file->path
|
'path' => $file->pathUrl
|
||||||
];
|
];
|
||||||
|
|
||||||
Response::json($result, 200)->send();
|
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
|
* @return System\Models\File
|
||||||
*/
|
*/
|
||||||
protected function decorateFileAttributes($file)
|
protected function decorateFileAttributes($file)
|
||||||
{
|
{
|
||||||
$file->thumb = ($this->imageWidth || $this->imageHeight)
|
/*
|
||||||
? $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions)
|
* File is protected, create a secure public path
|
||||||
: $file->path;
|
*/
|
||||||
|
if (!$file->isPublic()) {
|
||||||
|
$path = $thumb = FilesController::getDownloadUrl($file);
|
||||||
|
|
||||||
// Internal download link
|
if ($this->imageWidth || $this->imageHeight) {
|
||||||
if (!$file->isImage() || !$file->isPublic()) {
|
$thumb = FilesController::getThumbUrl($file, $this->imageWidth, $this->imageHeight, $this->thumbOptions);
|
||||||
$file->pathOverride = \Backend\Controllers\Files::getDownloadUrl($file);
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* 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;
|
return $file;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="file-upload-modal-image-header">
|
<div class="file-upload-modal-image-header">
|
||||||
<button type="button" class="close" data-dismiss="popup">×</button>
|
<button type="button" class="close" data-dismiss="popup">×</button>
|
||||||
<img
|
<img
|
||||||
src="<?= $file->thumb ?>"
|
src="<?= $file->thumbUrl ?>"
|
||||||
class="img-responsive center-block"
|
class="img-responsive center-block"
|
||||||
alt=""
|
alt=""
|
||||||
title="<?= e(trans('backend::lang.fileupload.attachment')) ?>: <?= e($file->file_name) ?>"
|
title="<?= e(trans('backend::lang.fileupload.attachment')) ?>: <?= e($file->file_name) ?>"
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<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
|
<i class="oc-icon-link"></i>Attachment URL
|
||||||
</a>
|
</a>
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
<!-- Existing files -->
|
<!-- Existing files -->
|
||||||
<div class="upload-files-container">
|
<div class="upload-files-container">
|
||||||
<?php foreach ($fileList as $file): ?>
|
<?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">
|
<div class="icon-container">
|
||||||
<i class="icon-file"></i>
|
<i class="icon-file"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<!-- Existing file -->
|
<!-- Existing file -->
|
||||||
<div class="upload-files-container">
|
<div class="upload-files-container">
|
||||||
<?php if ($singleFile): ?>
|
<?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">
|
<div class="icon-container">
|
||||||
<i class="icon-file"></i>
|
<i class="icon-file"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
<!-- Existing files -->
|
<!-- Existing files -->
|
||||||
<div class="upload-files-container">
|
<div class="upload-files-container">
|
||||||
<?php foreach ($fileList as $file): ?>
|
<?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">
|
<div class="icon-container image">
|
||||||
<img src="<?= $file->thumb ?>" />
|
<img src="<?= $file->thumbUrl ?>" />
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h4 class="filename">
|
<h4 class="filename">
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@
|
||||||
<!-- Existing file -->
|
<!-- Existing file -->
|
||||||
<div class="upload-files-container">
|
<div class="upload-files-container">
|
||||||
<?php if ($singleFile): ?>
|
<?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">
|
<div class="icon-container image">
|
||||||
<img src="<?= $singleFile->thumb ?>" />
|
<img src="<?= $singleFile->thumbUrl ?>" />
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h4 class="filename">
|
<h4 class="filename">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue