Back to MediaHelper class

Method canUpload

public bool
canUpload
(mixed $file, mixed $component = 'com_media', mixed $allowedExecutables = array())
Checks if the file can be uploaded
Parameters
  • array $file File information
  • string $component The option name for the component storing the parameters
  • string $allowedExecutables Array of executable file types that shall be whitelisted
Returns
  • bool
Since
  • 3.2
Class: MediaHelper
Project: Joomla

Method canUpload - Source code

/**
 * Checks if the file can be uploaded
 *
 * @param   array   $file                File information
 * @param   string  $component           The option name for the component storing the parameters
 * @param   string  $allowedExecutables  Array of executable file types that shall be whitelisted
 *
 * @return  boolean
 *
 * @since   3.2
 */
public function canUpload($file, $component = 'com_media', $allowedExecutables = array())
{
    $app = Factory::getApplication();
    $params = ComponentHelper::getParams($component);
    if (empty($file['name'])) {
        $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_UPLOAD_INPUT'), 'error');
        return false;
    }
    if ($file['name'] !== File::makeSafe($file['name'])) {
        $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILENAME'), 'error');
        return false;
    }
    $filetypes = explode('.', $file['name']);
    if (\count($filetypes) < 2) {
        // There seems to be no extension
        $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETYPE'), 'error');
        return false;
    }
    array_shift($filetypes);
    // Media file names should never have executable extensions buried in them.
    $executables = array_merge(self::EXECUTABLES, InputFilter::FORBIDDEN_FILE_EXTENSIONS);
    // Remove allowed executables from array
    if (count($allowedExecutables)) {
        $executables = array_diff($executables, $allowedExecutables);
    }
    $check = array_intersect($filetypes, $executables);
    if (!empty($check)) {
        $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETYPE'), 'error');
        return false;
    }
    $filetype = array_pop($filetypes);
    $allowable = array_map('trim', explode(',', $params->get('restrict_uploads_extensions', 'bmp,gif,jpg,jpeg,png,webp,ico,mp3,m4a,mp4a,ogg,mp4,mp4v,mpeg,mov,odg,odp,ods,odt,pdf,png,ppt,txt,xcf,xls,csv')));
    $ignored = array_map('trim', explode(',', $params->get('ignore_extensions', '')));
    if ($filetype == '' || $filetype == false || !\in_array($filetype, $allowable) && !\in_array($filetype, $ignored)) {
        $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETYPE'), 'error');
        return false;
    }
    $maxSize = (int) ($params->get('upload_maxsize', 0) * 1024 * 1024);
    if ($maxSize > 0 && (int) $file['size'] > $maxSize) {
        $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'), 'error');
        return false;
    }
    if ($params->get('restrict_uploads', 1)) {
        $allowedExtensions = array_map('trim', explode(',', $params->get('restrict_uploads_extensions', 'bmp,gif,jpg,jpeg,png,webp,ico,mp3,m4a,mp4a,ogg,mp4,mp4v,mpeg,mov,odg,odp,ods,odt,pdf,png,ppt,txt,xcf,xls,csv')));
        if (\in_array($filetype, $allowedExtensions)) {
            // If tmp_name is empty, then the file was bigger than the PHP limit
            if (!empty($file['tmp_name'])) {
                // Get the mime type this is an image file
                $mime = static::getMimeType($file['tmp_name'], true);
                // Did we get anything useful?
                if ($mime != false) {
                    $result = $this->checkMimeType($mime, $component);
                    // If the mime type is not allowed we don't upload it and show the mime code error to the user
                    if ($result === false) {
                        $app->enqueueMessage(Text::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE', $mime), 'error');
                        return false;
                    }
                } else {
                    $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNINVALID_IMG'), 'error');
                    return false;
                }
            } else {
                $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNFILETOOLARGE'), 'error');
                return false;
            }
        } elseif (!\in_array($filetype, $ignored)) {
            // Get the mime type this is not an image file
            $mime = static::getMimeType($file['tmp_name'], false);
            // Did we get anything useful?
            if ($mime != false) {
                $result = $this->checkMimeType($mime, $component);
                // If the mime type is not allowed we don't upload it and show the mime code error to the user
                if ($result === false) {
                    $app->enqueueMessage(Text::sprintf('JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE', $mime), 'error');
                    return false;
                }
            } else {
                $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNINVALID_MIME'), 'error');
                return false;
            }
            if (!Factory::getUser()->authorise('core.manage', $component)) {
                $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNNOTADMIN'), 'error');
                return false;
            }
        }
    }
    if ($filetype === 'svg') {
        $sanitizer = new Sanitizer();
        $isValid = $sanitizer->sanitize(file_get_contents($file['tmp_name']));
        $svgErrors = $sanitizer->getXmlIssues();
        // We allow comments
        foreach ($svgErrors as $i => $error) {
            if ($error['message'] === 'Suspicious node \'#comment\'') {
                unset($svgErrors[$i]);
            }
        }
        if ($isValid === false || count($svgErrors)) {
            $app->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNIEXSS'), 'error');
            return false;
        }
    }
    return true;
}