primo commit
This commit is contained in:
@ -0,0 +1,392 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_media
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Media\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\MVC\Model\BaseModel;
|
||||
use Joomla\CMS\Response\JsonResponse;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Session\Session;
|
||||
use Joomla\Component\Media\Administrator\Exception\FileExistsException;
|
||||
use Joomla\Component\Media\Administrator\Exception\FileNotFoundException;
|
||||
use Joomla\Component\Media\Administrator\Exception\InvalidPathException;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Api Media Controller
|
||||
*
|
||||
* This is NO public api controller, it is internal for the com_media component only!
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class ApiController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Execute a task by triggering a method in the derived class.
|
||||
*
|
||||
* @param string $task The task to perform. If no matching task is found, the '__default' task is executed, if defined.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function execute($task)
|
||||
{
|
||||
$method = $this->input->getMethod();
|
||||
|
||||
$this->task = $task;
|
||||
|
||||
try {
|
||||
// Check token for requests which do modify files (all except get requests)
|
||||
if ($method !== 'GET' && !Session::checkToken('json')) {
|
||||
throw new \InvalidArgumentException(Text::_('JINVALID_TOKEN_NOTICE'), 403);
|
||||
}
|
||||
|
||||
$doTask = strtolower($method) . ucfirst($task);
|
||||
|
||||
// Record the actual task being fired
|
||||
$this->doTask = $doTask;
|
||||
|
||||
if (!\in_array($this->doTask, $this->taskMap)) {
|
||||
throw new \Exception(Text::sprintf('JLIB_APPLICATION_ERROR_TASK_NOT_FOUND', $task), 405);
|
||||
}
|
||||
|
||||
$data = $this->$doTask();
|
||||
|
||||
// Return the data
|
||||
$this->sendResponse($data);
|
||||
} catch (FileNotFoundException $e) {
|
||||
$this->sendResponse($e, 404);
|
||||
} catch (FileExistsException $e) {
|
||||
$this->sendResponse($e, 409);
|
||||
} catch (InvalidPathException $e) {
|
||||
$this->sendResponse($e, 400);
|
||||
} catch (\Exception $e) {
|
||||
$errorCode = 500;
|
||||
|
||||
if ($e->getCode() > 0) {
|
||||
$errorCode = $e->getCode();
|
||||
}
|
||||
|
||||
$this->sendResponse($e, $errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Files Get Method
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - GET a list of folders below the root:
|
||||
* index.php?option=com_media&task=api.files
|
||||
* /api/files
|
||||
* - GET a list of files and subfolders of a given folder:
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia
|
||||
* /api/files/sampledata/cassiopeia
|
||||
* - GET a list of files and subfolders of a given folder for a given search term:
|
||||
* use recursive=1 to search recursively in the working directory
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia&search=nasa5
|
||||
* /api/files/sampledata/cassiopeia?search=nasa5
|
||||
* To look up in same working directory set flag recursive=0
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia&search=nasa5&recursive=0
|
||||
* /api/files/sampledata/cassiopeia?search=nasa5&recursive=0
|
||||
* - GET file information for a specific file:
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia/test.jpg
|
||||
* /api/files/sampledata/cassiopeia/test.jpg
|
||||
* - GET a temporary URL to a given file
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia/test.jpg&url=1&temp=1
|
||||
* /api/files/sampledata/cassiopeia/test.jpg&url=1&temp=1
|
||||
* - GET a temporary URL to a given file
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia/test.jpg&url=1
|
||||
* /api/files/sampledata/cassiopeia/test.jpg&url=1
|
||||
*
|
||||
* @return array The data to send with the response
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getFiles()
|
||||
{
|
||||
// Grab options
|
||||
$options = [];
|
||||
$options['url'] = $this->input->getBool('url', false);
|
||||
$options['search'] = $this->input->getString('search', '');
|
||||
$options['recursive'] = $this->input->getBool('recursive', true);
|
||||
$options['content'] = $this->input->getBool('content', false);
|
||||
|
||||
return $this->getModel()->getFiles($this->getAdapter(), $this->getPath(), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Files delete Method
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - DELETE an existing folder in a specific folder:
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia/test
|
||||
* /api/files/sampledata/cassiopeia/test
|
||||
* - DELETE an existing file in a specific folder:
|
||||
* index.php?option=com_media&task=api.files&path=/sampledata/cassiopeia/test.jpg
|
||||
* /api/files/sampledata/cassiopeia/test.jpg
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function deleteFiles()
|
||||
{
|
||||
if (!$this->app->getIdentity()->authorise('core.delete', 'com_media')) {
|
||||
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), 403);
|
||||
}
|
||||
|
||||
$this->getModel()->delete($this->getAdapter(), $this->getPath());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Files Post Method
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - POST a new file or folder into a specific folder, the file or folder information is returned:
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia
|
||||
* /api/files/sampledata/cassiopeia
|
||||
*
|
||||
* New file body:
|
||||
* {
|
||||
* "name": "test.jpg",
|
||||
* "content":"base64 encoded image"
|
||||
* }
|
||||
* New folder body:
|
||||
* {
|
||||
* "name": "test",
|
||||
* }
|
||||
*
|
||||
* @return array The data to send with the response
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function postFiles()
|
||||
{
|
||||
if (!$this->app->getIdentity()->authorise('core.create', 'com_media')) {
|
||||
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED'), 403);
|
||||
}
|
||||
|
||||
$adapter = $this->getAdapter();
|
||||
$path = $this->getPath();
|
||||
$content = $this->input->json;
|
||||
$name = $content->getString('name');
|
||||
$mediaContent = base64_decode($content->get('content', '', 'raw'));
|
||||
$override = $content->get('override', false);
|
||||
|
||||
if ($mediaContent) {
|
||||
$this->checkFileSize(\strlen($mediaContent));
|
||||
|
||||
// A file needs to be created
|
||||
$name = $this->getModel()->createFile($adapter, $name, $path, $mediaContent, $override);
|
||||
} else {
|
||||
// A folder needs to be created
|
||||
$name = $this->getModel()->createFolder($adapter, $name, $path, $override);
|
||||
}
|
||||
|
||||
$options = [];
|
||||
$options['url'] = $this->input->getBool('url', false);
|
||||
|
||||
return $this->getModel()->getFile($adapter, $path . '/' . $name, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Files Put method
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* - PUT a media file, the file or folder information is returned:
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia/test.jpg
|
||||
* /api/files/sampledata/cassiopeia/test.jpg
|
||||
*
|
||||
* Update file body:
|
||||
* {
|
||||
* "content":"base64 encoded image"
|
||||
* }
|
||||
*
|
||||
* - PUT move a file, folder to another one
|
||||
* path : will be taken as the source
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia/test.jpg
|
||||
* /api/files/sampledata/cassiopeia/test.jpg
|
||||
*
|
||||
* JSON body:
|
||||
* {
|
||||
* "newPath" : "/path/to/destination",
|
||||
* "move" : "1"
|
||||
* }
|
||||
*
|
||||
* - PUT copy a file, folder to another one
|
||||
* path : will be taken as the source
|
||||
* index.php?option=com_media&task=api.files&format=json&path=/sampledata/cassiopeia/test.jpg
|
||||
* /api/files/sampledata/cassiopeia/test.jpg
|
||||
*
|
||||
* JSON body:
|
||||
* {
|
||||
* "newPath" : "/path/to/destination",
|
||||
* "move" : "0"
|
||||
* }
|
||||
*
|
||||
* @return array The data to send with the response
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function putFiles()
|
||||
{
|
||||
if (!$this->app->getIdentity()->authorise('core.edit', 'com_media')) {
|
||||
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'), 403);
|
||||
}
|
||||
|
||||
$adapter = $this->getAdapter();
|
||||
$path = $this->getPath();
|
||||
|
||||
$content = $this->input->json;
|
||||
$name = basename($path);
|
||||
$mediaContent = base64_decode($content->get('content', '', 'raw'));
|
||||
$newPath = $content->getString('newPath', null);
|
||||
$move = $content->get('move', true);
|
||||
|
||||
if ($mediaContent != null) {
|
||||
$this->checkFileSize(\strlen($mediaContent));
|
||||
|
||||
$this->getModel()->updateFile($adapter, $name, str_replace($name, '', $path), $mediaContent);
|
||||
}
|
||||
|
||||
if ($newPath != null && $newPath !== $adapter . ':' . $path) {
|
||||
list($destinationAdapter, $destinationPath) = explode(':', $newPath, 2);
|
||||
|
||||
if ($move) {
|
||||
$destinationPath = $this->getModel()->move($adapter, $path, $destinationPath, false);
|
||||
} else {
|
||||
$destinationPath = $this->getModel()->copy($adapter, $path, $destinationPath, false);
|
||||
}
|
||||
|
||||
$path = $destinationPath;
|
||||
}
|
||||
|
||||
return $this->getModel()->getFile($adapter, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the given data as JSON response in the following format:
|
||||
*
|
||||
* {"success":true,"message":"ok","messages":null,"data":[{"type":"dir","name":"banners","path":"//"}]}
|
||||
*
|
||||
* @param mixed $data The data to send
|
||||
* @param integer $responseCode The response code
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function sendResponse($data = null, int $responseCode = 200)
|
||||
{
|
||||
// Set the correct content type
|
||||
$this->app->setHeader('Content-Type', 'application/json');
|
||||
|
||||
// Set the status code for the response
|
||||
http_response_code($responseCode);
|
||||
|
||||
// Send the data
|
||||
echo new JsonResponse($data);
|
||||
|
||||
$this->app->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a model object, loading it if required.
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return BaseModel|boolean Model object on success; otherwise false on failure.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function getModel($name = 'Api', $prefix = 'Administrator', $config = [])
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs file size checks if it is allowed to be saved.
|
||||
*
|
||||
* @param integer $fileSize The size of submitted file
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.4.9
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function checkFileSize(int $fileSize)
|
||||
{
|
||||
$params = ComponentHelper::getParams('com_media');
|
||||
$paramsUploadMaxsize = $params->get('upload_maxsize', 0) * 1024 * 1024;
|
||||
|
||||
if ($paramsUploadMaxsize > 0 && $fileSize > $paramsUploadMaxsize) {
|
||||
$link = 'index.php?option=com_config&view=component&component=com_media';
|
||||
$output = HTMLHelper::_('link', Route::_($link), Text::_('JOPTIONS'));
|
||||
throw new \Exception(Text::sprintf('COM_MEDIA_ERROR_WARNFILETOOLARGE', $output), 403);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Adapter.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function getAdapter()
|
||||
{
|
||||
$parts = explode(':', $this->input->getString('path', ''), 2);
|
||||
|
||||
if (\count($parts) < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $parts[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Path.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function getPath()
|
||||
{
|
||||
$parts = explode(':', $this->input->getString('path', ''), 2);
|
||||
|
||||
if (\count($parts) < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $parts[1];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_media
|
||||
*
|
||||
* @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Media\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Media Manager Component Controller
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* The default view.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $default_view = 'media';
|
||||
|
||||
/**
|
||||
* Method to get a reference to the current view and load it if necessary.
|
||||
*
|
||||
* @param string $name The view name. Optional, defaults to the controller name.
|
||||
* @param string $type The view type. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for view. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\View\ViewInterface Reference to the view or an error.
|
||||
*
|
||||
* @since 3.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getView($name = '', $type = '', $prefix = '', $config = [])
|
||||
{
|
||||
// Force to load the admin view
|
||||
return parent::getView($name, $type, 'Administrator', $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a model object, loading it if required.
|
||||
*
|
||||
* @param string $name The model name. Optional.
|
||||
* @param string $prefix The class prefix. Optional.
|
||||
* @param array $config Configuration array for model. Optional.
|
||||
*
|
||||
* @return \Joomla\CMS\MVC\Model\BaseDatabaseModel|boolean Model object on success; otherwise false on failure.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function getModel($name = '', $prefix = '', $config = [])
|
||||
{
|
||||
// Force to load the admin model
|
||||
return parent::getModel($name, 'Administrator', $config);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Administrator
|
||||
* @subpackage com_media
|
||||
*
|
||||
* @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Media\Administrator\Controller;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\Component\Media\Administrator\Event\OAuthCallbackEvent;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Plugin Controller for OAuth2.0 callbacks
|
||||
*
|
||||
* This controller handles OAuth2 Callbacks
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class PluginController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Handles an OAuth Callback request for a specified plugin.
|
||||
*
|
||||
* URLs containing [sitename]/administrator/index.php?option=com_media&task=plugin.oauthcallback
|
||||
* &plugin=[plugin_name]
|
||||
*
|
||||
* will be handled by this endpoint.
|
||||
* It will select the plugin specified by plugin_name and pass all the data received from the provider
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function oauthcallback()
|
||||
{
|
||||
try {
|
||||
// Load plugin names
|
||||
$pluginName = $this->input->getString('plugin', null);
|
||||
$plugins = PluginHelper::getPlugin('filesystem');
|
||||
|
||||
// If plugin name was not found in parameters redirect back to control panel
|
||||
if (!$pluginName || !$this->containsPlugin($plugins, $pluginName)) {
|
||||
throw new \Exception('Plugin not found!');
|
||||
}
|
||||
|
||||
// Check if the plugin is disabled, if so redirect to control panel
|
||||
if (!PluginHelper::isEnabled('filesystem', $pluginName)) {
|
||||
throw new \Exception('Plugin ' . $pluginName . ' is disabled.');
|
||||
}
|
||||
|
||||
// Only import our required plugin, not entire group
|
||||
PluginHelper::importPlugin('filesystem', $pluginName);
|
||||
|
||||
// Event parameters
|
||||
$eventParameters = ['context' => $pluginName, 'input' => $this->input];
|
||||
$event = new OAuthCallbackEvent('onFileSystemOAuthCallback', $eventParameters);
|
||||
|
||||
// Get results from event
|
||||
$eventResults = (array) $this->app->triggerEvent('onFileSystemOAuthCallback', $event);
|
||||
|
||||
// If event was not triggered in the selected Plugin, raise a warning and fallback to Control Panel
|
||||
if (!$eventResults) {
|
||||
throw new \Exception(
|
||||
'Plugin ' . $pluginName . ' should have implemented onFileSystemOAuthCallback method'
|
||||
);
|
||||
}
|
||||
|
||||
$action = $eventResults['action'] ?? null;
|
||||
|
||||
// If there are any messages display them
|
||||
if (isset($eventResults['message'])) {
|
||||
$message = $eventResults['message'];
|
||||
$messageType = ($eventResults['message_type'] ?? '');
|
||||
|
||||
$this->app->enqueueMessage($message, $messageType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute actions defined by the plugin
|
||||
* Supported actions
|
||||
* - close : Closes the current window, use this only for windows opened by javascript
|
||||
* - redirect : Redirect to a URI defined in 'redirect_uri' parameter, if not fallback to control panel
|
||||
* - media-manager : Redirect to Media Manager
|
||||
* - control-panel : Redirect to Control Panel
|
||||
*/
|
||||
switch ($action) {
|
||||
case 'close':
|
||||
/**
|
||||
* Close a window opened by developer
|
||||
* Use this for close New Windows opened for OAuth Process
|
||||
*/
|
||||
$this->setRedirect(Route::_('index.php?option=com_media&view=plugin&action=close', false));
|
||||
break;
|
||||
|
||||
case 'redirect':
|
||||
// Redirect browser to any page specified by the user
|
||||
if (!isset($eventResults['redirect_uri'])) {
|
||||
throw new \Exception("Redirect URI must be set in the plugin");
|
||||
}
|
||||
|
||||
$this->setRedirect($eventResults['redirect_uri']);
|
||||
break;
|
||||
|
||||
case 'control-panel':
|
||||
// Redirect browser to Control Panel
|
||||
$this->setRedirect(Route::_('index.php', false));
|
||||
break;
|
||||
|
||||
case 'media-manager':
|
||||
default:
|
||||
// Redirect browser to Media Manager
|
||||
$this->setRedirect(Route::_('index.php?option=com_media&view=media', false));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Display any error
|
||||
$this->app->enqueueMessage($e->getMessage(), 'error');
|
||||
$this->setRedirect(Route::_('index.php', false));
|
||||
}
|
||||
|
||||
// Redirect
|
||||
$this->redirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a plugin exists in given plugin array.
|
||||
*
|
||||
* @param array $plugins Array of plugin names
|
||||
* @param string $pluginName Plugin name to look up
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function containsPlugin($plugins, $pluginName)
|
||||
{
|
||||
foreach ($plugins as $plugin) {
|
||||
if ($plugin->name == $pluginName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user