%PDF- %PDF-
| Direktori : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/modules/file/actions/ |
| Current File : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/modules/file/actions/DownloadAction.php |
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\file\actions;
use Firebase\JWT\JWT;
use humhub\modules\file\Module;
use humhub\modules\user\models\User;
use Yii;
use yii\helpers\Url;
use yii\web\HttpException;
use yii\base\Action;
use humhub\modules\file\models\File;
use humhub\modules\file\libs\FileHelper;
use yii\filters\HttpCache;
/**
* DownloadAction
*
* @since 1.2
* @author Luke
*/
class DownloadAction extends Action
{
/**
* @see HttpCache
* @var boolean enable Http Caching
*/
public $enableHttpCache = true;
/**
* @var File the requested file object
*/
protected $file;
/**
* @var string the requested file variant
*/
protected $variant;
/**
* @var boolean force download response
*/
protected $download = false;
/**
* @inheritdoc
*/
public function init()
{
$this->loadFile(Yii::$app->request->get('guid'), Yii::$app->request->get('token'));
$this->download = (boolean)Yii::$app->request->get('download', false);
$this->loadVariant(Yii::$app->request->get('variant', null));
$this->checkFileExists();
}
/**
* @inheritdoc
* @throws HttpException
*/
public function beforeRun()
{
if (Yii::$app->request->isPjax) {
throw new HttpException(400, 'File downloads are not allowed with pjax!');
}
if (!parent::beforeRun()) {
return false;
}
if (!$this->enableHttpCache) {
return true;
}
$httpCache = new HttpCache();
$httpCache->lastModified = function () {
return Yii::$app->formatter->asTimestamp($this->file->updated_at);
};
$httpCache->etagSeed = function () {
if (file_exists($this->getStoredFilePath())) {
return md5_file($this->getStoredFilePath());
}
return null;
};
if (!$httpCache->beforeAction($this)) {
return false;
}
return true;
}
/**
* @inheritdoc
*/
public function run()
{
$fileName = $this->getFileName();
$mimeType = FileHelper::getMimeTypeByExtension($fileName);
$options = [
'inline' => (!$this->download && in_array($mimeType, $this->getModule()->inlineMimeTypes)),
'mimeType' => $mimeType
];
if ($this->useXSendFile()) {
Yii::$app->response->xSendFile($this->getStoredFilePath(), $fileName, $options);
} else {
Yii::$app->response->sendFile($this->getStoredFilePath(), $fileName, $options);
}
}
/**
* Loads the file by given guid
*
* @param string $guid
* @param string $token
* @return File the loaded file instance
* @throws HttpException
*/
protected function loadFile($guid, $token = null)
{
$file = File::findOne(['guid' => $guid]);
if ($file == null) {
throw new HttpException(404, Yii::t('FileModule.base', 'Could not find requested file!'));
}
$user = nulL;
if ($token !== null) {
$user = static::getUserByDownloadToken($token, $file);
}
// File is not assigned to any database record (yet)
if (empty($file->object_model) && (Yii::$app->user->isGuest || $file->created_by != Yii::$app->user->id)) {
throw new HttpException(401, Yii::t('FileModule.base', 'Insufficient permissions!'));
}
if (!$file->canRead($user)) {
throw new HttpException(401, Yii::t('FileModule.base', 'Insufficient permissions!'));
}
$this->file = $file;
}
/**
* Loads a variant and verifies
*
* @param string $variant
* @throws HttpException
*/
protected function loadVariant($variant)
{
// For compatibility reasons (prior 1.1) check the old 'suffix' parameter
if ($variant === null) {
$variant = Yii::$app->request->get('suffix', null);
}
if ($variant !== null) {
// Check if variant is available by file
if (!in_array($variant, $this->file->store->getVariants())) {
throw new HttpException(404, Yii::t('FileModule.base', 'Could not find requested file variant!'));
}
}
$this->variant = $variant;
}
/**
* Returns the file module
*
* @return \humhub\modules\file\Module
*/
protected function getModule()
{
return Yii::$app->getModule('file');
}
/**
* Check if requested file exists
*
* @throws HttpException
*/
protected function checkFileExists()
{
if (!file_exists($this->file->store->get($this->variant))) {
throw new HttpException(404, Yii::t('FileModule.base', 'Could not find requested file!'));
}
}
/**
* Returns the filename
*
* @return string
*/
protected function getFileName()
{
if (!$this->variant) {
return $this->file->file_name;
}
// Build filename by variant
if (FileHelper::hasExtension($this->variant)) {
// Use extension of variant
$variantParts = pathinfo($this->variant);
$orgParts = pathinfo($this->file->file_name);
return $orgParts['filename'] . '_' . $variantParts['filename'] . '.' . $variantParts['extension'];
} elseif (FileHelper::hasExtension($this->file->file_name)) {
// Use extension of original file
$parts = pathinfo($this->file->file_name);
return $parts['filename'] . '_' . $this->variant . '.' . $parts['extension'];
}
return $this->file->file_name . '_' . $this->variant;
}
/**
* Checks if XSendFile downloads are enabled
*
* @return boolean
*/
protected function useXSendFile()
{
return ($this->getModule()->settings->get('useXSendfile'));
}
/**
* Returns the file path of the stored file
*
* @return string path to the saved file
*/
protected function getStoredFilePath()
{
return $this->file->store->get($this->variant);
}
/**
* Returns the User model by given JWT token
*
* @param string $token
* @param File $file
* @return User|null
*/
public static function getUserByDownloadToken(string $token, File $file)
{
try {
$decoded = JWT::decode($token, static::getDownloadTokenKey(), ['HS256']);
} catch (\Exception $ex) {
Yii::warning('Could not decode provided JWT token. ' . $ex->getMessage());
}
if (!empty($decoded->sub) && !empty($decoded->aud) && $decoded->aud == $file->id) {
return User::findOne(['id' => $decoded->sub]);
}
return null;
}
/**
* Returns a token to access this file by JWT token
*
* @param File $file
* @param User $user
* @return string
*/
public static function generateDownloadToken(File $file, User $user)
{
$token = [
'iss' => 'dld-token-v1',
'sub' => $user->id,
'aud' => $file->id
];
return JWT::encode($token, static::getDownloadTokenKey());
}
/**
* @return string the secret key for file download tokens
* @throws \yii\base\Exception
*/
private static function getDownloadTokenKey()
{
/** @var Module $module */
$module = Yii::$app->getModule('file');
$key = $module->settings->get('downloadTokenKey');
if (empty($key)) {
$key = Yii::$app->security->generateRandomString(32);
$module->settings->set('downloadTokenKey', $key);
}
return $key;
}
}