From fd16f38b1126b846e0addbcdfe7ef0bf45cf596d Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Mon, 29 Feb 2016 18:11:00 +1100 Subject: [PATCH] Implement file definitions (extensions + ignore files) Block "unsafe" extensions from being uploaded to the Media manager Fixes #1801 --- modules/backend/formwidgets/FileUpload.php | 3 ++- modules/cms/classes/MediaLibrary.php | 24 ++++++++--------- modules/cms/classes/MediaLibraryItem.php | 30 +++++++++++---------- modules/cms/lang/en/lang.php | 1 + modules/cms/widgets/AssetList.php | 31 ++-------------------- modules/cms/widgets/MediaManager.php | 9 +++++++ 6 files changed, 41 insertions(+), 57 deletions(-) diff --git a/modules/backend/formwidgets/FileUpload.php b/modules/backend/formwidgets/FileUpload.php index 7bcc47601..cbbd44ad1 100644 --- a/modules/backend/formwidgets/FileUpload.php +++ b/modules/backend/formwidgets/FileUpload.php @@ -11,6 +11,7 @@ use ApplicationException; use Backend\Classes\FormField; use Backend\Classes\FormWidgetBase; use Backend\Controllers\Files as FilesController; +use October\Rain\Filesystem\Definitions as FileDefinitions; use ValidationException; use Exception; @@ -230,7 +231,7 @@ class FileUpload extends FormWidgetBase if ($types === false) { $isImage = starts_with($this->getDisplayMode(), 'image'); - $types = implode(',', File::getDefaultFileTypes($isImage)); + $types = implode(',', FileDefinitions::get($isImage ? 'imageExtensions' : 'defaultExtensions')); } if (!$types || $types == '*') { diff --git a/modules/cms/classes/MediaLibrary.php b/modules/cms/classes/MediaLibrary.php index 76bfa8aee..b4e2f623b 100644 --- a/modules/cms/classes/MediaLibrary.php +++ b/modules/cms/classes/MediaLibrary.php @@ -1,13 +1,14 @@ storagePath = Request::getBasePath() . $this->storagePath; } - $this->ignoreNames = Config::get('cms.storage.media.ignore', $this->defaultIgnoreNames); + $this->ignoreNames = Config::get('cms.storage.media.ignore', FileDefinitions::get('ignoreFiles')); $this->storageFolderNameLength = strlen($this->storageFolder); } diff --git a/modules/cms/classes/MediaLibraryItem.php b/modules/cms/classes/MediaLibraryItem.php index 2631deee2..a540e7c44 100644 --- a/modules/cms/classes/MediaLibraryItem.php +++ b/modules/cms/classes/MediaLibraryItem.php @@ -3,6 +3,7 @@ use File; use Config; use Backend\Models\UserPreferences; +use October\Rain\Filesystem\Definitions as FileDefinitions; use Carbon\Carbon; /** @@ -49,20 +50,21 @@ class MediaLibraryItem public $publicUrl; /** - * @var array Contains a default list of files and directories to ignore. - * The list can be customized with the following configuration options: - * - cms.storage.media.image_extensions - * - cms.storage.media.video_extensions - * - cms.storage.media.audo_extensions + * @var array Contains a default list of image files and directories to ignore. + * Override with config: cms.storage.media.imageExtensions */ - protected static $defaultTypeExtensions = [ - 'image' => ['gif', 'png', 'jpg', 'jpeg', 'bmp'], - 'video' => ['mp4', 'avi', 'mov', 'mpg', 'mpeg', 'mkv', 'webm'], - 'audio' => ['mp3', 'wav', 'wma', 'm4a', 'ogg'] - ]; - protected static $imageExtensions; + + /** + * @var array Contains a default list of video files and directories to ignore. + * Override with config: cms.storage.media.videoExtensions + */ protected static $videoExtensions; + + /** + * @var array Contains a default list of audio files and directories to ignore. + * Override with config: cms.storage.media.audioExtensions + */ protected static $audioExtensions; /** @@ -101,9 +103,9 @@ class MediaLibraryItem } if (!self::$imageExtensions) { - self::$imageExtensions = Config::get('cms.storage.media.image_extensions', self::$defaultTypeExtensions['image']); - self::$videoExtensions = Config::get('cms.storage.media.video_extensions', self::$defaultTypeExtensions['video']); - self::$audioExtensions = Config::get('cms.storage.media.audio_extensions', self::$defaultTypeExtensions['audio']); + self::$imageExtensions = Config::get('cms.storage.media.imageExtensions', FileDefinitions::get('imageExtensions')); + self::$videoExtensions = Config::get('cms.storage.media.videoExtensions', FileDefinitions::get('videoExtensions')); + self::$audioExtensions = Config::get('cms.storage.media.audioExtensions', FileDefinitions::get('audioExtensions')); } $extension = pathinfo($this->path, PATHINFO_EXTENSION); diff --git a/modules/cms/lang/en/lang.php b/modules/cms/lang/en/lang.php index 614184296..daa933ab9 100644 --- a/modules/cms/lang/en/lang.php +++ b/modules/cms/lang/en/lang.php @@ -266,6 +266,7 @@ return [ 'uploading_file_num' => 'Uploading :number file(s)...', 'uploading_complete' => 'Upload complete', 'uploading_error' => 'Upload failed', + 'type_blocked' => 'The file type used is blocked for security reasons.', 'order_by' => 'Order by', 'folder' => 'Folder', 'no_files_found' => 'No files found by your request.', diff --git a/modules/cms/widgets/AssetList.php b/modules/cms/widgets/AssetList.php index 57167a7c2..f2a1a327f 100644 --- a/modules/cms/widgets/AssetList.php +++ b/modules/cms/widgets/AssetList.php @@ -17,6 +17,7 @@ use ApplicationException; use ValidationException; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; +use October\Rain\Filesystem\Definitions as FileDefinitions; use RecursiveIteratorIterator; use RecursiveDirectoryIterator; use DirectoryIterator; @@ -48,31 +49,6 @@ class AssetList extends WidgetBase */ public $deleteConfirmation = 'Do you really want to delete selected files or directories?'; - /** - * @var array A list of default allowed file types. - * This parameter can be overridden with the cms.allowedAssetTypes configuration option. - */ - public $allowedAssetTypes = [ - 'jpg', - 'jpeg', - 'bmp', - 'png', - 'gif', - 'css', - 'js', - 'woff', - 'woff2', - 'svg', - 'ttf', - 'eot', - 'otf', - 'json', - 'md', - 'less', - 'sass', - 'scss' - ]; - public function __construct($controller, $alias) { $this->alias = $alias; @@ -681,10 +657,7 @@ class AssetList extends WidgetBase // Don't rely on Symfony's mime guessing implementation, it's not accurate enough. // Use the simple extension validation. - $allowedAssetTypes = Config::get('cms.allowedAssetTypes'); - if (!$allowedAssetTypes) { - $allowedAssetTypes = $this->allowedAssetTypes; - } + $allowedAssetTypes = FileDefinitions::get('assetExtensions'); $maxSize = UploadedFile::getMaxFilesize(); if ($uploadedFile->getSize() > $maxSize) { diff --git a/modules/cms/widgets/MediaManager.php b/modules/cms/widgets/MediaManager.php index bbeda53d4..7fdf11ca2 100644 --- a/modules/cms/widgets/MediaManager.php +++ b/modules/cms/widgets/MediaManager.php @@ -15,6 +15,7 @@ use Backend\Classes\WidgetBase; use Cms\Classes\MediaLibrary; use Cms\Classes\MediaLibraryItem; use October\Rain\Database\Attach\Resizer; +use October\Rain\Filesystem\Definitions as FileDefinitions; /** * Media Manager widget. @@ -969,6 +970,14 @@ class MediaManager extends WidgetBase $extension = strtolower($uploadedFile->getClientOriginalExtension()); $fileName = File::name($fileName).'.'.$extension; + /* + * Check for unsafe file extensions + */ + $blockedFileTypes = FileDefinitions::get('blockedExtensions'); + if (in_array($extension, $blockedFileTypes)) { + throw new ApplicationException(Lang::get('cms::lang.media.type_blocked')); + } + /* * File name contains non-latin characters, attempt to slug the value */