first commit
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/ContextFileManager.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ContextFileManager
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @brief Class defining operations for private context file management.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use APP\core\Application;
|
||||
|
||||
class ContextFileManager extends PrivateFileManager
|
||||
{
|
||||
/** @var int the ID of the associated context */
|
||||
public $contextId;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a manager for handling context file uploads.
|
||||
*/
|
||||
public function __construct($contextId)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->contextId = (int) $contextId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base path for file storage
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePath()
|
||||
{
|
||||
$dirNames = Application::getFileDirectories();
|
||||
return parent::getBasePath() . $dirNames['context'] . $this->contextId . '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\ContextFileManager', '\ContextFileManager');
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/FileArchive.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class FileArchive
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @brief Class provides functionality for creating an archive of files.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use Exception;
|
||||
use PKP\config\Config;
|
||||
use ZipArchive;
|
||||
|
||||
class FileArchive
|
||||
{
|
||||
/**
|
||||
* Assembles an array of filenames into either a tar.gz or a .zip
|
||||
* file, based on what is available. Returns a string representing
|
||||
* the path to the archive on disk.
|
||||
*
|
||||
* @param array $files the files to add, in an associative array of the
|
||||
* format ('serverPath' => 'clientFilename')
|
||||
* @param string $filesDir a path to the files on disk.
|
||||
*
|
||||
* @return string the path to the archive.
|
||||
*/
|
||||
public function create($files, $filesDir)
|
||||
{
|
||||
// Create a temporary file.
|
||||
$archivePath = tempnam('/tmp', 'sf-');
|
||||
if ($archivePath === false) {
|
||||
return false;
|
||||
}
|
||||
unlink($archivePath);
|
||||
|
||||
// attempt to use Zip first, if it is available. Otherwise
|
||||
// fall back to the tar CLI.
|
||||
$zipTest = false;
|
||||
if (self::zipFunctional()) {
|
||||
$zipTest = true;
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($archivePath, ZipArchive::CREATE) == true) {
|
||||
foreach ($files as $serverPath => $clientFilename) {
|
||||
$zip->addFile($filesDir . '/' . $serverPath, $clientFilename);
|
||||
}
|
||||
$zip->close();
|
||||
}
|
||||
} elseif (self::tarFunctional()) {
|
||||
// Create the archive and download the file.
|
||||
exec(
|
||||
Config::getVar('cli', 'tar') . ' -c -z ' .
|
||||
'-f ' . escapeshellarg($archivePath) . ' ' .
|
||||
'-C ' . escapeshellarg($filesDir) . ' ' .
|
||||
implode(' ', array_map('escapeshellarg', array_keys($files)))
|
||||
);
|
||||
} else {
|
||||
throw new Exception('No archive tool is available!');
|
||||
}
|
||||
|
||||
return $archivePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the zip extension is loaded.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function zipFunctional()
|
||||
{
|
||||
return (extension_loaded('zip'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the tar tools are configured.
|
||||
*/
|
||||
public static function tarFunctional()
|
||||
{
|
||||
$tarBinary = Config::getVar('cli', 'tar');
|
||||
return !empty($tarBinary) && file_exists($tarBinary);
|
||||
}
|
||||
|
||||
public static function isFunctional()
|
||||
{
|
||||
return self::zipFunctional() || self::tarFunctional();
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\FileArchive', '\FileArchive');
|
||||
}
|
||||
@@ -0,0 +1,849 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @defgroup file File
|
||||
* Implements file management tools, including a database-backed list of files
|
||||
* associated with submissions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file classes/file/FileManager.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
* ePUB mime type added Leah M Root (rootl) SUNY Geneseo
|
||||
*
|
||||
* @class FileManager
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @brief Class defining basic operations for file management.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use APP\core\Application;
|
||||
use Exception;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
use PKP\config\Config;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\plugins\Hook;
|
||||
use SplFileObject;
|
||||
use Throwable;
|
||||
|
||||
class FileManager
|
||||
{
|
||||
public const FILE_MODE_MASK = 0666;
|
||||
public const DIRECTORY_MODE_MASK = 0777;
|
||||
|
||||
public const DOCUMENT_TYPE_DEFAULT = 'default';
|
||||
public const DOCUMENT_TYPE_AUDIO = 'audio';
|
||||
public const DOCUMENT_TYPE_EXCEL = 'excel';
|
||||
public const DOCUMENT_TYPE_HTML = 'html';
|
||||
public const DOCUMENT_TYPE_IMAGE = 'image';
|
||||
public const DOCUMENT_TYPE_PDF = 'pdf';
|
||||
public const DOCUMENT_TYPE_WORD = 'word';
|
||||
public const DOCUMENT_TYPE_EPUB = 'epub';
|
||||
public const DOCUMENT_TYPE_VIDEO = 'video';
|
||||
public const DOCUMENT_TYPE_ZIP = 'zip';
|
||||
public const DOCUMENT_TYPE_URL = 'url';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if an uploaded file exists.
|
||||
*
|
||||
* @param string $fileName the name of the file used in the POST form
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function uploadedFileExists($fileName)
|
||||
{
|
||||
if (isset($_FILES[$fileName]) && isset($_FILES[$fileName]['tmp_name'])
|
||||
&& is_uploaded_file($_FILES[$fileName]['tmp_name'])) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true iff an error occurred when trying to upload a file.
|
||||
*
|
||||
* @param string $fileName the name of the file used in the POST form
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function uploadError($fileName)
|
||||
{
|
||||
return (isset($_FILES[$fileName]) && $_FILES[$fileName]['error'] != UPLOAD_ERR_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error code of a file upload
|
||||
*
|
||||
* @see http://php.net/manual/en/features.file-upload.errors.php
|
||||
*
|
||||
* @param string $fileName the name of the file used in the POST form
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getUploadErrorCode($fileName)
|
||||
{
|
||||
return $_FILES[$fileName]['error'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filename of the first uploaded file in the $_FILES array. The
|
||||
* returned filename is the value used in the form that submitted the request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstUploadedPostName()
|
||||
{
|
||||
return key($_FILES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the (temporary) path to an uploaded file.
|
||||
*
|
||||
* @param string $fileName the name of the file used in the POST form
|
||||
*
|
||||
* @return string (boolean false if no such file)
|
||||
*/
|
||||
public function getUploadedFilePath($fileName)
|
||||
{
|
||||
if (isset($_FILES[$fileName]['tmp_name']) && is_uploaded_file($_FILES[$fileName]['tmp_name'])) {
|
||||
return $_FILES[$fileName]['tmp_name'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user-specific (not temporary) filename of an uploaded file.
|
||||
*
|
||||
* @param string $fileName the name of the file used in the POST form
|
||||
*
|
||||
* @return string (boolean false if no such file)
|
||||
*/
|
||||
public function getUploadedFileName($fileName)
|
||||
{
|
||||
if (isset($_FILES[$fileName]['name'])) {
|
||||
return $_FILES[$fileName]['name'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of an uploaded file.
|
||||
*
|
||||
* @param string $fileName the name of the file used in the POST form
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUploadedFileType($fileName)
|
||||
{
|
||||
if (isset($_FILES[$fileName])) {
|
||||
$exploded = explode('.', $_FILES[$fileName]['name']);
|
||||
|
||||
$type = PKPString::mime_content_type(
|
||||
$_FILES[$fileName]['tmp_name'], // Location on server
|
||||
array_pop($exploded) // Extension on client machine
|
||||
);
|
||||
|
||||
if (!empty($type)) {
|
||||
return $type;
|
||||
}
|
||||
return $_FILES[$fileName]['type'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file.
|
||||
*
|
||||
* @param string $fileName the name of the file used in the POST form
|
||||
*
|
||||
* @return bool returns true if successful
|
||||
*/
|
||||
public function uploadFile($fileName, $destFileName)
|
||||
{
|
||||
$destDir = dirname($destFileName);
|
||||
if (!$this->fileExists($destDir, 'dir')) {
|
||||
// Try to create the destination directory
|
||||
$this->mkdirtree($destDir);
|
||||
}
|
||||
if (!isset($_FILES[$fileName])) {
|
||||
return false;
|
||||
}
|
||||
if (move_uploaded_file($_FILES[$fileName]['tmp_name'], $destFileName)) {
|
||||
return $this->setMode($destFileName, self::FILE_MODE_MASK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a file.
|
||||
*
|
||||
* @param string $dest the path where the file is to be saved
|
||||
* @param string $contents the contents to write to the file
|
||||
*
|
||||
* @return bool returns true if successful
|
||||
*/
|
||||
public function writeFile($dest, $contents)
|
||||
{
|
||||
$success = true;
|
||||
$destDir = dirname($dest);
|
||||
if (!$this->fileExists($destDir, 'dir')) {
|
||||
// Try to create the destination directory
|
||||
$this->mkdirtree($destDir);
|
||||
}
|
||||
if (($f = fopen($dest, 'wb')) === false) {
|
||||
$success = false;
|
||||
}
|
||||
if ($success && fwrite($f, $contents) === false) {
|
||||
$success = false;
|
||||
}
|
||||
@fclose($f);
|
||||
|
||||
if ($success) {
|
||||
return $this->setMode($dest, self::FILE_MODE_MASK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file.
|
||||
*
|
||||
* @param string $source the source URL for the file
|
||||
* @param string $dest the path where the file is to be saved
|
||||
*
|
||||
* @return bool returns true if successful
|
||||
*/
|
||||
public function copyFile($source, $dest)
|
||||
{
|
||||
$destDir = dirname($dest);
|
||||
if (!$this->fileExists($destDir, 'dir')) {
|
||||
// Try to create the destination directory
|
||||
$this->mkdirtree($destDir);
|
||||
}
|
||||
if (copy($source, $dest)) {
|
||||
return $this->setMode($dest, self::FILE_MODE_MASK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a directory.
|
||||
* Adapted from code by gimmicklessgpt at gmail dot com, at http://php.net/manual/en/function.copy.php
|
||||
*
|
||||
* @param string $source the path to the source directory
|
||||
* @param string $dest the path where the directory is to be saved
|
||||
*
|
||||
* @return bool returns true if successful
|
||||
*/
|
||||
public function copyDir($source, $dest)
|
||||
{
|
||||
if (is_dir($source)) {
|
||||
$this->mkdir($dest);
|
||||
$destDir = dir($source);
|
||||
|
||||
while (($entry = $destDir->read()) !== false) {
|
||||
if ($entry == '.' || $entry == '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$Entry = "{$source}/{$entry}";
|
||||
if (is_dir($Entry)) {
|
||||
$this->copyDir($Entry, "{$dest}/{$entry}");
|
||||
continue;
|
||||
}
|
||||
$this->copyFile($Entry, "{$dest}/{$entry}");
|
||||
}
|
||||
|
||||
$destDir->close();
|
||||
} else {
|
||||
$this->copyFile($source, $dest);
|
||||
}
|
||||
|
||||
if ($this->fileExists($dest, 'dir')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves whether the filename is a URL
|
||||
*/
|
||||
public static function isVirtualPath(string $filenameOrUrl): bool
|
||||
{
|
||||
return !!filter_var($filenameOrUrl, FILTER_VALIDATE_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a PSR7 stream given a filename or URL.
|
||||
*/
|
||||
public static function getStream(string $filenameOrUrl): ?Stream
|
||||
{
|
||||
if (static::isVirtualPath($filenameOrUrl)) {
|
||||
// Remote URL.
|
||||
$client = Application::get()->getHttpClient();
|
||||
$response = $client->request('GET', $filenameOrUrl);
|
||||
return Utils::streamFor($response->getBody());
|
||||
} elseif (file_exists($filenameOrUrl) && is_readable($filenameOrUrl)) {
|
||||
$resource = fopen($filenameOrUrl, 'r');
|
||||
return Utils::streamFor($resource);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a file's contents.
|
||||
*
|
||||
* @param string $filePath the location of the file to be read
|
||||
* @param bool $output output the file's contents instead of returning a string
|
||||
*
|
||||
* @return string|boolean
|
||||
*/
|
||||
public function readFileFromPath($filePath, $output = false)
|
||||
{
|
||||
if (is_readable($filePath)) {
|
||||
$f = fopen($filePath, 'rb');
|
||||
if (!$f) {
|
||||
return false;
|
||||
}
|
||||
$data = '';
|
||||
while (!feof($f)) {
|
||||
$data .= fread($f, 4096);
|
||||
if ($output) {
|
||||
echo $data;
|
||||
$data = '';
|
||||
}
|
||||
}
|
||||
fclose($f);
|
||||
|
||||
if ($output) {
|
||||
return true;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file.
|
||||
* Outputs HTTP headers and file content for download
|
||||
*
|
||||
* @param string $filePath the location of the file to be sent
|
||||
* @param string $mediaType the MIME type of the file, optional
|
||||
* @param bool $inline print file as inline instead of attachment, optional
|
||||
* @param string $fileName Optional filename to use on the client side
|
||||
*
|
||||
* @return ?bool
|
||||
*/
|
||||
public function downloadByPath($filePath, $mediaType = null, $inline = false, $fileName = null)
|
||||
{
|
||||
$result = null;
|
||||
if (Hook::call('FileManager::downloadFile', [&$filePath, &$mediaType, &$inline, &$result, &$fileName])) {
|
||||
return $result;
|
||||
}
|
||||
if (is_readable($filePath)) {
|
||||
if ($mediaType === null) {
|
||||
// If the media type wasn't specified, try to detect.
|
||||
$mediaType = PKPString::mime_content_type($filePath);
|
||||
if (empty($mediaType)) {
|
||||
$mediaType = 'application/octet-stream';
|
||||
}
|
||||
}
|
||||
if ($fileName === null) {
|
||||
// If the filename wasn't specified, use the server-side.
|
||||
$fileName = basename($filePath);
|
||||
}
|
||||
|
||||
// Stream the file to the end user.
|
||||
header("Content-Type: {$mediaType}");
|
||||
header('Content-Length: ' . filesize($filePath));
|
||||
header('Accept-Ranges: none');
|
||||
header('Content-Disposition: ' . ($inline ? 'inline' : 'attachment') . "; filename=\"{$fileName}\"");
|
||||
header('Cache-Control: private'); // Workarounds for IE weirdness
|
||||
header('Pragma: public');
|
||||
$this->readFileFromPath($filePath, true);
|
||||
$returner = true;
|
||||
} else {
|
||||
$returner = false;
|
||||
}
|
||||
Hook::call('FileManager::downloadFileFinished', [&$returner]);
|
||||
return $returner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file.
|
||||
*
|
||||
* @param string $filePath the location of the file to be deleted
|
||||
*
|
||||
* @return ?bool returns true if successful
|
||||
*/
|
||||
public function deleteByPath($filePath)
|
||||
{
|
||||
if ($this->fileExists($filePath)) {
|
||||
$result = null;
|
||||
if (Hook::call('FileManager::deleteFile', [$filePath, &$result])) {
|
||||
return $result;
|
||||
}
|
||||
return unlink($filePath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new directory.
|
||||
*
|
||||
* @param string $dirPath the full path of the directory to be created
|
||||
* @param string $perms the permissions level of the directory (optional)
|
||||
*
|
||||
* @return bool returns true if successful
|
||||
*/
|
||||
public function mkdir($dirPath, $perms = null)
|
||||
{
|
||||
if ($perms !== null) {
|
||||
return mkdir($dirPath, $perms);
|
||||
} else {
|
||||
if (is_dir($dirPath) || mkdir($dirPath)) {
|
||||
return $this->setMode($dirPath, static::DIRECTORY_MODE_MASK);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a directory.
|
||||
*
|
||||
* @param string $dirPath the full path of the directory to be delete
|
||||
*
|
||||
* @return bool returns true if successful
|
||||
*/
|
||||
public function rmdir($dirPath)
|
||||
{
|
||||
return rmdir($dirPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all contents including directory (equivalent to "rm -r")
|
||||
*
|
||||
* @param string $file the full path of the directory to be removed
|
||||
*
|
||||
* @return bool true iff success, otherwise false
|
||||
*/
|
||||
public function rmtree($file)
|
||||
{
|
||||
if (file_exists($file)) {
|
||||
if (is_dir($file)) {
|
||||
$handle = opendir($file);
|
||||
while (($filename = readdir($handle)) !== false) {
|
||||
if ($filename != '.' && $filename != '..') {
|
||||
if (!$this->rmtree($file . '/' . $filename)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
if (!rmdir($file)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!unlink($file)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new directory, including all intermediate directories if required (equivalent to "mkdir -p")
|
||||
*
|
||||
* @param string $dirPath the full path of the directory to be created
|
||||
* @param string $perms the permissions level of the directory (optional)
|
||||
*
|
||||
* @return bool returns true if successful
|
||||
*/
|
||||
public function mkdirtree($dirPath, $perms = null)
|
||||
{
|
||||
if (!file_exists($dirPath)) {
|
||||
//Avoid infinite recursion when file_exists reports false for root directory
|
||||
if ($dirPath == dirname($dirPath)) {
|
||||
fatalError('There are no readable files in this directory tree. Are safe mode or open_basedir active?');
|
||||
return false;
|
||||
} elseif ($this->mkdirtree(dirname($dirPath), $perms)) {
|
||||
return $this->mkdir($dirPath, $perms);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file path is valid;
|
||||
*
|
||||
* @param string $filePath the file/directory to check
|
||||
* @param string $type (file|dir) the type of path
|
||||
*/
|
||||
public function fileExists($filePath, $type = 'file')
|
||||
{
|
||||
switch ($type) {
|
||||
case 'file':
|
||||
return file_exists($filePath);
|
||||
case 'dir':
|
||||
return file_exists($filePath) && is_dir($filePath);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a file type, based on generic categories defined above
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return string (Enumerated DOCUMENT_TYPEs)
|
||||
*/
|
||||
public function getDocumentType($type)
|
||||
{
|
||||
if ($this->getImageExtension($type)) {
|
||||
return self::DOCUMENT_TYPE_IMAGE;
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'application/pdf':
|
||||
case 'application/x-pdf':
|
||||
case 'text/pdf':
|
||||
case 'text/x-pdf':
|
||||
return self::DOCUMENT_TYPE_PDF;
|
||||
case 'application/msword':
|
||||
case 'application/word':
|
||||
return self::DOCUMENT_TYPE_WORD;
|
||||
case 'application/excel':
|
||||
return self::DOCUMENT_TYPE_EXCEL;
|
||||
case 'text/html':
|
||||
return self::DOCUMENT_TYPE_HTML;
|
||||
case 'application/zip':
|
||||
case 'application/x-zip':
|
||||
case 'application/x-zip-compressed':
|
||||
case 'application/x-compress':
|
||||
case 'application/x-compressed':
|
||||
case 'multipart/x-zip':
|
||||
return self::DOCUMENT_TYPE_ZIP;
|
||||
case 'application/epub':
|
||||
case 'application/epub+zip':
|
||||
return self::DOCUMENT_TYPE_EPUB;
|
||||
default:
|
||||
return self::DOCUMENT_TYPE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns file extension associated with the given document type,
|
||||
* or false if the type does not belong to a recognized document type.
|
||||
*
|
||||
* @param string $type
|
||||
*/
|
||||
public function getDocumentExtension($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'application/pdf':
|
||||
return '.pdf';
|
||||
case 'application/word':
|
||||
return '.doc';
|
||||
case 'text/css':
|
||||
return '.css';
|
||||
case 'text/html':
|
||||
return '.html';
|
||||
case 'application/epub+zip':
|
||||
return '.epub';
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns file extension associated with the given image type,
|
||||
* or false if the type does not belong to a recognized image type.
|
||||
*
|
||||
* @param string $type
|
||||
*/
|
||||
public function getImageExtension($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'image/gif':
|
||||
return '.gif';
|
||||
case 'image/jpeg':
|
||||
case 'image/pjpeg':
|
||||
return '.jpg';
|
||||
case 'image/png':
|
||||
case 'image/x-png':
|
||||
return '.png';
|
||||
case 'image/vnd.microsoft.icon':
|
||||
case 'image/x-icon':
|
||||
case 'image/x-ico':
|
||||
case 'image/ico':
|
||||
return '.ico';
|
||||
case 'application/x-shockwave-flash':
|
||||
return '.swf';
|
||||
case 'video/x-flv':
|
||||
case 'application/x-flash-video':
|
||||
case 'flv-application/octet-stream':
|
||||
return '.flv';
|
||||
case 'audio/mpeg':
|
||||
return '.mp3';
|
||||
case 'audio/x-aiff':
|
||||
return '.aiff';
|
||||
case 'audio/x-wav':
|
||||
return '.wav';
|
||||
case 'video/mpeg':
|
||||
return '.mpg';
|
||||
case 'video/quicktime':
|
||||
return '.mov';
|
||||
case 'video/mp4':
|
||||
return '.mp4';
|
||||
case 'text/javascript':
|
||||
return '.js';
|
||||
case 'image/webp':
|
||||
return '.webp';
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse file extension from file name.
|
||||
*
|
||||
* @param string $fileName a valid file name
|
||||
*
|
||||
* @return string extension
|
||||
*/
|
||||
public function getExtension($fileName)
|
||||
{
|
||||
$extension = '';
|
||||
$fileParts = explode('.', $fileName);
|
||||
if (is_array($fileParts)) {
|
||||
$extension = $fileParts[count($fileParts) - 1];
|
||||
}
|
||||
return $extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate a filename to fit in the specified length.
|
||||
*/
|
||||
public function truncateFileName($fileName, $length = 127)
|
||||
{
|
||||
if (PKPString::strlen($fileName) <= $length) {
|
||||
return $fileName;
|
||||
}
|
||||
$ext = $this->getExtension($fileName);
|
||||
$truncated = PKPString::substr($fileName, 0, $length - 1 - PKPString::strlen($ext)) . '.' . $ext;
|
||||
return PKPString::substr($truncated, 0, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pretty file size string (in B, KB, MB, or GB units).
|
||||
*
|
||||
* @param int $size file size in bytes
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNiceFileSize($size)
|
||||
{
|
||||
$niceFileSizeUnits = ['B', 'KB', 'MB', 'GB'];
|
||||
for ($i = 0; $i < 4 && $size > 1024; $i++) {
|
||||
$size >>= 10;
|
||||
}
|
||||
return $size . $niceFileSizeUnits[$i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file/directory mode based on the 'umask' config setting.
|
||||
*
|
||||
* @param string $path
|
||||
* @param int $mask
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setMode($path, $mask)
|
||||
{
|
||||
$umask = Config::getVar('files', 'umask');
|
||||
if (!$umask) {
|
||||
return true;
|
||||
}
|
||||
return chmod($path, $mask & ~$umask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the file extension from a filename/path.
|
||||
*
|
||||
* @param string $fileName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function parseFileExtension($fileName)
|
||||
{
|
||||
$fileParts = explode('.', $fileName);
|
||||
if (is_array($fileParts) && count($fileParts) > 1) {
|
||||
$fileExtension = $fileParts[count($fileParts) - 1];
|
||||
}
|
||||
|
||||
// FIXME Check for evil
|
||||
if (!isset($fileExtension) || stristr($fileExtension, 'php') || strlen($fileExtension) > 6 || !preg_match('/^\w+$/', $fileExtension)) {
|
||||
$fileExtension = 'txt';
|
||||
}
|
||||
|
||||
// consider .tar.gz extension
|
||||
if (strtolower(substr($fileName, -7)) == '.tar.gz') {
|
||||
$fileExtension = substr($fileName, -6);
|
||||
}
|
||||
|
||||
return $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress passed gziped file.
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return string $filePath The file path that was created.
|
||||
*
|
||||
*/
|
||||
public function gzDecompressFile(string $filePath): string
|
||||
{
|
||||
$bufferSize = 4096; // read 4kb at a time
|
||||
$destPath = str_replace('.gz', '', $filePath);
|
||||
|
||||
// Open our files (in binary mode)
|
||||
$file = gzopen($filePath, 'rb');
|
||||
if ($file === false) {
|
||||
throw new Exception(__('admin.error.gzDecompressFile.gzopen', ['filePath' => $filePath]));
|
||||
}
|
||||
$destFile = fopen($destPath, 'wb');
|
||||
if ($destFile === false) {
|
||||
throw new Exception(__('admin.error.gzDecompressFile.fopen', ['filePath' => $destPath]));
|
||||
}
|
||||
while (!gzeof($file)) {
|
||||
// Read buffer-size bytes
|
||||
$contents = gzread($file, $bufferSize);
|
||||
if ($contents === false) {
|
||||
throw new Exception(__('admin.error.gzDecompressFile.gzread', ['file' => $file]));
|
||||
}
|
||||
if (fwrite($destFile, $contents) === false) {
|
||||
throw new Exception(__('admin.error.gzDecompressFile.fwrite', ['filePath' => $destFile]));
|
||||
}
|
||||
}
|
||||
$success = fclose($destFile);
|
||||
if (false === $success) {
|
||||
throw new Exception(__('admin.error.gzDecompressFile.fclose', ['filePath' => $destFile]));
|
||||
}
|
||||
$success = gzclose($file);
|
||||
if (false === $success) {
|
||||
throw new Exception(__('admin.error.gzDecompressFile.gzclose', ['filePath' => $file]));
|
||||
}
|
||||
|
||||
if (unlink($filePath) === false) {
|
||||
throw new Exception(__('admin.error.gzDecompressFile.unlink', ['filePath' => $filePath]));
|
||||
}
|
||||
return $destPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress passed file.
|
||||
*
|
||||
* @param string $filePath The file to be compressed.
|
||||
* @param int $level Compression level
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return string The file path that was created.
|
||||
*
|
||||
*/
|
||||
public function gzCompressFile(string $filePath, int $level = 9): string
|
||||
{
|
||||
$bufferSize = 4096; // read 4kb at a time
|
||||
$destPath = $filePath . '.gz';
|
||||
$mode = 'wb' . $level;
|
||||
|
||||
$destFile = gzopen($destPath, $mode);
|
||||
if ($destFile === false) {
|
||||
throw new Exception(__('admin.error.gzCompressFile.gzopen', ['filePath' => $destPath]));
|
||||
}
|
||||
$file = fopen($filePath, 'rb');
|
||||
if ($file === false) {
|
||||
throw new Exception(__('admin.error.gzCompressFile.fopen', ['filePath' => $filePath]));
|
||||
}
|
||||
while (!feof($file)) {
|
||||
$contents = fread($file, $bufferSize);
|
||||
if ($contents === false) {
|
||||
throw new Exception(__('admin.error.gzCompressFile.fread', ['filePath' => $file]));
|
||||
}
|
||||
if (gzwrite($destFile, $contents) === false) {
|
||||
throw new Exception(__('admin.error.gzCompressFile.gzwrite', ['filePath' => $destFile]));
|
||||
}
|
||||
}
|
||||
$success = fclose($file);
|
||||
if (false === $success) {
|
||||
throw new Exception(__('admin.error.gzCompressFile.fclose', ['filePath' => $file]));
|
||||
}
|
||||
$success = gzclose($destFile);
|
||||
if (false === $success) {
|
||||
throw new Exception(__('admin.error.gzCompressFile.gzclose', ['filePath' => $destFile]));
|
||||
}
|
||||
|
||||
if (unlink($filePath) === false) {
|
||||
throw new Exception(__('admin.error.gzCompressFile.unlink', ['filePath' => $filePath]));
|
||||
}
|
||||
return $destPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to create a readable, writable and locked (configurable) temporary file
|
||||
* The prefix/suffix will be appended to the filename and might receive a minor sanitization
|
||||
*/
|
||||
public static function getTemporaryFile(?string $prefix = null, ?string $suffix = null, ?int $lockType = LOCK_EX, int $maxRetries = 10): SplFileObject
|
||||
{
|
||||
// Sanitize the filename, mostly to avoid navigating through the filesystem with ".."
|
||||
$sanitize = fn (?string $path) => preg_replace('/[^\w.-]/', '', (string) $path);
|
||||
$basePath = rtrim(sys_get_temp_dir(), '\\/') . '/';
|
||||
$lastException = null;
|
||||
for ($maxRetries = max(0, $maxRetries) + 1; $maxRetries--;) {
|
||||
$path = $basePath . $sanitize($prefix) . substr(md5(random_int(0, PHP_INT_MAX)), 0, 10) . $sanitize($suffix);
|
||||
try {
|
||||
// If the file already exists, an Exception will be raised due to the "x" mode
|
||||
$file = new SplFileObject($path, 'x+');
|
||||
if ($lockType) {
|
||||
$file->flock($lockType) || throw new Exception("Failed to acquire lock using operation \"{$lockType}\"");
|
||||
}
|
||||
return $file;
|
||||
} catch (Throwable $e) {
|
||||
// Keeps track of the last exception, so it can be re-thrown when the retries are over
|
||||
$lastException = new Exception("Failed to create temporary file \"{$path}\"" . ($maxRetries ? ", {$maxRetries} retries remaining" : ''), 0, $e);
|
||||
error_log($lastException);
|
||||
}
|
||||
}
|
||||
throw $lastException;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\FileManager', '\FileManager');
|
||||
foreach ([
|
||||
'FILE_MODE_MASK',
|
||||
'DIRECTORY_MODE_MASK',
|
||||
'DOCUMENT_TYPE_DEFAULT', 'DOCUMENT_TYPE_AUDIO', 'DOCUMENT_TYPE_EXCEL', 'DOCUMENT_TYPE_HTML', 'DOCUMENT_TYPE_IMAGE', 'DOCUMENT_TYPE_PDF', 'DOCUMENT_TYPE_WORD', 'DOCUMENT_TYPE_EPUB', 'DOCUMENT_TYPE_VIDEO', 'DOCUMENT_TYPE_ZIP',
|
||||
] as $constantName) {
|
||||
define($constantName, constant('\FileManager::' . $constantName));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/PKPFile.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PKPFile
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @brief Base PKP file class.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use APP\core\Services;
|
||||
|
||||
class PKPFile extends \PKP\core\DataObject
|
||||
{
|
||||
//
|
||||
// Get/set methods
|
||||
//
|
||||
/**
|
||||
* Get server-side file name of the file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getServerFileName()
|
||||
{
|
||||
return $this->getData('fileName');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set server-side file name of the file.
|
||||
*
|
||||
* @param string $fileName
|
||||
*/
|
||||
public function setServerFileName($fileName)
|
||||
{
|
||||
$this->setData('fileName', $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get original uploaded file name of the file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOriginalFileName()
|
||||
{
|
||||
return $this->getData('originalFileName');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set original uploaded file name of the file.
|
||||
*
|
||||
* @param string $originalFileName
|
||||
*/
|
||||
public function setOriginalFileName($originalFileName)
|
||||
{
|
||||
$this->setData('originalFileName', $originalFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type of the file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFileType()
|
||||
{
|
||||
return $this->getData('filetype');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type of the file.
|
||||
*/
|
||||
public function setFileType($fileType)
|
||||
{
|
||||
$this->setData('filetype', $fileType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get uploaded date of file.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateUploaded()
|
||||
{
|
||||
return $this->getData('dateUploaded');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set uploaded date of file.
|
||||
*
|
||||
* @param string $dateUploaded
|
||||
*/
|
||||
public function setDateUploaded($dateUploaded)
|
||||
{
|
||||
return $this->SetData('dateUploaded', $dateUploaded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get file size of file.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFileSize()
|
||||
{
|
||||
return $this->getData('fileSize');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file size of file.
|
||||
*
|
||||
* @param int $fileSize
|
||||
*/
|
||||
public function setFileSize($fileSize)
|
||||
{
|
||||
return $this->SetData('fileSize', $fileSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return pretty file size string (in B, KB, MB, or GB units).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNiceFileSize()
|
||||
{
|
||||
return Services::get('file')->getNiceFileSize($this->getFileSize());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Abstract template methods to be implemented by subclasses.
|
||||
//
|
||||
/**
|
||||
* Return absolute path to the file on the host filesystem.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilePath()
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\PKPFile', '\PKPFile');
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/PKPLibraryFileManager.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2003-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PKPLibraryFileManager
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @brief Wrapper class for uploading files to a site/context' library directory.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use PKP\context\LibraryFile;
|
||||
use PKP\context\LibraryFileDAO;
|
||||
use PKP\file\TemporaryFile;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\db\DAORegistry;
|
||||
|
||||
class PKPLibraryFileManager extends PrivateFileManager
|
||||
{
|
||||
/** @var int Context id for the current context */
|
||||
public $contextId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $contextId
|
||||
*/
|
||||
public function __construct($contextId)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->contextId = $contextId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base path for file storage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePath()
|
||||
{
|
||||
return parent::getBasePath() . '/contexts/' . $this->contextId . '/library/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file by ID.
|
||||
*
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function deleteById($fileId)
|
||||
{
|
||||
$libraryFileDao = DAORegistry::getDAO('LibraryFileDAO'); /** @var LibraryFileDAO $libraryFileDao */
|
||||
$libraryFile = $libraryFileDao->getById($fileId);
|
||||
|
||||
parent::deleteByPath($this->getBasePath() . $libraryFile->getServerFileName());
|
||||
|
||||
$libraryFileDao->deleteById($fileId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a filename for a library file.
|
||||
*
|
||||
* @param int $type LIBRARY_FILE_TYPE_...
|
||||
* @param string $originalFileName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateFileName($type, $originalFileName)
|
||||
{
|
||||
$libraryFileDao = DAORegistry::getDAO('LibraryFileDAO'); /** @var LibraryFileDAO $libraryFileDao */
|
||||
$suffix = $this->getFileSuffixFromType($type);
|
||||
$ext = $this->getExtension($originalFileName);
|
||||
$truncated = $this->truncateFileName($originalFileName, 127 - PKPString::strlen($suffix) - 1);
|
||||
$baseName = PKPString::substr($truncated, 0, PKPString::strpos($originalFileName, $ext) - 1);
|
||||
|
||||
// Try a simple syntax first
|
||||
$fileName = $baseName . '-' . $suffix . '.' . $ext;
|
||||
if (!$libraryFileDao->filenameExists($this->contextId, $fileName)) {
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
for ($i = 1; ; $i++) {
|
||||
$fullSuffix = $suffix . '-' . $i;
|
||||
//truncate more if necessary
|
||||
$truncated = $this->truncateFileName($originalFileName, 127 - PKPString::strlen($fullSuffix) - 1);
|
||||
// get the base name and append the suffix
|
||||
$baseName = PKPString::substr($truncated, 0, PKPString::strpos($originalFileName, $ext) - 1);
|
||||
|
||||
//try the following
|
||||
$fileName = $baseName . '-' . $fullSuffix . '.' . $ext;
|
||||
if (!$libraryFileDao->filenameExists($this->contextId, $fileName)) {
|
||||
return $fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Routine to copy a library file from a temporary file.
|
||||
*
|
||||
* @param object $temporaryFile
|
||||
* @param int $libraryFileType LIBRARY_FILE_TYPE_...
|
||||
*
|
||||
* @return false|LibraryFile the generated file, prepared as much as possible for insert (false if upload failed)
|
||||
*/
|
||||
public function ©FromTemporaryFile(&$temporaryFile, $libraryFileType)
|
||||
{
|
||||
$libraryFileDao = DAORegistry::getDAO('LibraryFileDAO'); /** @var LibraryFileDAO $libraryFileDao */
|
||||
$libraryFile = $libraryFileDao->newDataObject();
|
||||
|
||||
$libraryFile = $this->assignFromTemporaryFile($temporaryFile, $libraryFileType, $libraryFile);
|
||||
if (!$this->copyFile($temporaryFile->getFilePath(), $this->getBasePath() . $libraryFile->getServerFileName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $libraryFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routine to replace a library file from a temporary file.
|
||||
* @param $libraryFileType int LIBRARY_FILE_TYPE_...
|
||||
* @return LibraryFile|false the updated LibraryFile, or false on error
|
||||
*/
|
||||
function replaceFromTemporaryFile(TemporaryFile $temporaryFile, int $libraryFileType, LibraryFile $libraryFile) {
|
||||
$originalServerFilename = $libraryFile->getServerFileName();
|
||||
|
||||
$libraryFile = $this->assignFromTemporaryFile($temporaryFile, $libraryFileType, $libraryFile);
|
||||
if (!$this->copyFile($temporaryFile->getFilePath(), $this->getBasePath() . $libraryFile->getServerFileName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($originalServerFilename !== $libraryFile->getServerFileName()) {
|
||||
unlink($this->getBasePath() . $originalServerFilename);
|
||||
}
|
||||
return $libraryFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Routine to assign metadata to a library file from a temporary file
|
||||
* @param $temporaryFile TemporaryFile
|
||||
* @param $libraryFileType int LIBRARY_FILE_TYPE_...
|
||||
* @param $libraryFile LibraryFile
|
||||
* @return LibraryFile the updated LibraryFile
|
||||
*/
|
||||
function &assignFromTemporaryFile($temporaryFile, $libraryFileType, $libraryFile) {
|
||||
$libraryFile->setDateUploaded($temporaryFile->getDateUploaded());
|
||||
$libraryFile->setDateModified($temporaryFile->getDateUploaded());
|
||||
$libraryFile->setFileType($temporaryFile->getFileType());
|
||||
$libraryFile->setFileSize($temporaryFile->getFileSize());
|
||||
$libraryFile->setServerFileName($this->generateFileName($libraryFileType, $temporaryFile->getOriginalFileName()));
|
||||
$libraryFile->setOriginalFileName($temporaryFile->getOriginalFileName());
|
||||
return $libraryFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file suffix for the given file type
|
||||
*
|
||||
* @param int $type LIBRARY_FILE_TYPE_...
|
||||
*/
|
||||
public function getFileSuffixFromType($type)
|
||||
{
|
||||
$typeSuffixMap = & $this->getTypeSuffixMap();
|
||||
return $typeSuffixMap[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type => suffix mapping array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function &getTypeSuffixMap()
|
||||
{
|
||||
static $map = [
|
||||
LibraryFile::LIBRARY_FILE_TYPE_MARKETING => 'MAR',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_PERMISSION => 'PER',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_REPORT => 'REP',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_OTHER => 'OTH'
|
||||
];
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the symbolic name from the type
|
||||
*
|
||||
* @param int $type LIBRARY_FILE_TYPE_...
|
||||
*/
|
||||
public function getNameFromType($type)
|
||||
{
|
||||
$typeNameMap = & $this->getTypeNameMap();
|
||||
if (isset($typeNameMap[$type])) {
|
||||
return $typeNameMap[$type];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type => locale key mapping array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function &getTypeTitleKeyMap()
|
||||
{
|
||||
static $map = [
|
||||
LibraryFile::LIBRARY_FILE_TYPE_MARKETING => 'settings.libraryFiles.category.marketing',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_PERMISSION => 'settings.libraryFiles.category.permissions',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_REPORT => 'settings.libraryFiles.category.reports',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_OTHER => 'settings.libraryFiles.category.other'
|
||||
];
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display name locale key from the type title
|
||||
*
|
||||
* @param int $type LIBRARY_FILE_TYPE_...
|
||||
*/
|
||||
public function getTitleKeyFromType($type)
|
||||
{
|
||||
$typeTitleKeyMap = & $this->getTypeTitleKeyMap();
|
||||
return $typeTitleKeyMap[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type => name mapping array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function &getTypeNameMap()
|
||||
{
|
||||
static $typeNameMap = [
|
||||
LibraryFile::LIBRARY_FILE_TYPE_MARKETING => 'marketing',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_PERMISSION => 'permissions',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_REPORT => 'reports',
|
||||
LibraryFile::LIBRARY_FILE_TYPE_OTHER => 'other',
|
||||
];
|
||||
return $typeNameMap;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\PKPLibraryFileManager', '\PKPLibraryFileManager');
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/PKPPublicFileManager.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PKPPublicFileManager
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @brief Wrapper class for uploading files to a site/journal's public directory.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use PKP\config\Config;
|
||||
|
||||
abstract class PKPPublicFileManager extends FileManager
|
||||
{
|
||||
/**
|
||||
* Get the path to the site public files directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSiteFilesPath()
|
||||
{
|
||||
return Config::getVar('files', 'public_files_dir') . '/site';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to a context's public files directory.
|
||||
*
|
||||
* @param int $contextId Context ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getContextFilesPath($contextId);
|
||||
|
||||
/**
|
||||
* Upload a file to a context's public directory.
|
||||
*
|
||||
* @param int $contextId The context ID
|
||||
* @param string $fileName the name of the file in the upload form
|
||||
* @param string $destFileName the destination file name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function uploadContextFile($contextId, $fileName, $destFileName)
|
||||
{
|
||||
return $this->uploadFile($fileName, $this->getContextFilesPath($contextId) . '/' . $destFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a file to a context's public directory.
|
||||
*
|
||||
* @param int $contextId Context ID
|
||||
* @param string $destFileName the destination file name
|
||||
* @param string $contents the contents to write to the file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function writeContextFile($contextId, $destFileName, $contents)
|
||||
{
|
||||
return $this->writeFile($this->getContextFilesPath($contextId) . '/' . $destFileName, $contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file to the site's public directory.
|
||||
*
|
||||
* @param string $fileName the name of the file in the upload form
|
||||
* @param string $destFileName the destination file name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function uploadSiteFile($fileName, $destFileName)
|
||||
{
|
||||
return $this->uploadFile($fileName, $this->getSiteFilesPath() . '/' . $destFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file to the site's public directory.
|
||||
*
|
||||
* @param string $sourceFile the source of the file to copy
|
||||
* @param string $destFileName the destination file name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function copySiteFile($sourceFile, $destFileName)
|
||||
{
|
||||
return $this->copyFile($sourceFile, $this->getSiteFilesPath() . '/' . $destFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file to a site's public directory.
|
||||
*
|
||||
* @param int $contextId Context ID
|
||||
* @param string $sourceFile the source of the file to copy
|
||||
* @param string $destFileName the destination file name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function copyContextFile($contextId, $sourceFile, $destFileName)
|
||||
{
|
||||
return $this->copyFile($sourceFile, $this->getContextFilesPath($contextId) . '/' . $destFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file from a context's public directory.
|
||||
*
|
||||
* @param int $contextId Context ID
|
||||
* @param string $fileName the target file name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function removeContextFile($contextId, $fileName)
|
||||
{
|
||||
return $this->deleteByPath($this->getContextFilesPath($contextId) . '/' . $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file from the site's public directory.
|
||||
*
|
||||
* @param string $fileName the target file name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function removeSiteFile($fileName)
|
||||
{
|
||||
return $this->deleteByPath($this->getSiteFilesPath() . '/' . $fileName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\PKPPublicFileManager', '\PKPPublicFileManager');
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/PrivateFileManager.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PrivateFileManager
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @brief Class defining operations for private file management.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use PKP\config\Config;
|
||||
|
||||
class PrivateFileManager extends FileManager
|
||||
{
|
||||
/** @var string $filesDir */
|
||||
public $filesDir;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->filesDir = $this->getBasePath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base path for file storage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePath()
|
||||
{
|
||||
return Config::getVar('files', 'files_dir');
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\PrivateFileManager', '\PrivateFileManager');
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/TemporaryFile.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class TemporaryFile
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @see TemporaryFileDAO
|
||||
*
|
||||
* @brief Temporary file class.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
class TemporaryFile extends PKPFile
|
||||
{
|
||||
/**
|
||||
* Return absolute path to the file on the host filesystem.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilePath()
|
||||
{
|
||||
$temporaryFileManager = new TemporaryFileManager();
|
||||
return $temporaryFileManager->getBasePath() . $this->getServerFileName();
|
||||
}
|
||||
|
||||
//
|
||||
// Get/set methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Get ID of associated user.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->getData('userId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ID of associated user.
|
||||
*
|
||||
* @param int $userId
|
||||
*/
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->setData('userId', $userId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\TemporaryFile', '\TemporaryFile');
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/TemporaryFileDAO.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class TemporaryFileDAO
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @see TemporaryFile
|
||||
*
|
||||
* @brief Operations for retrieving and modifying TemporaryFile objects.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use PKP\plugins\Hook;
|
||||
use PKP\db\DAOResultFactory;
|
||||
|
||||
class TemporaryFileDAO extends \PKP\db\DAO
|
||||
{
|
||||
/**
|
||||
* Retrieve a temporary file by ID.
|
||||
*
|
||||
* @param int $fileId
|
||||
* @param int $userId
|
||||
*
|
||||
* @return ?TemporaryFile
|
||||
*/
|
||||
public function getTemporaryFile($fileId, $userId)
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
'SELECT t.* FROM temporary_files t WHERE t.file_id = ? and t.user_id = ?',
|
||||
[(int) $fileId, (int) $userId]
|
||||
);
|
||||
|
||||
$row = (array) $result->current();
|
||||
return $row ? $this->_returnTemporaryFileFromRow($row) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve temporary files by user Id
|
||||
* @param $userId int
|
||||
* @return DAOResultFactory
|
||||
*/
|
||||
public function getTemporaryFilesByUserId(int $userId): DAOResultFactory
|
||||
{
|
||||
$result = $this->retrieve(
|
||||
'SELECT * FROM temporary_files WHERE user_id = ? ORDER BY date_uploaded DESC',
|
||||
[(int) $userId]
|
||||
);
|
||||
return new DAOResultFactory($result, $this, '_returnTemporaryFileFromRow');
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate and return a new data object.
|
||||
*
|
||||
* @return TemporaryFile
|
||||
*/
|
||||
public function newDataObject()
|
||||
{
|
||||
return new TemporaryFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function to return a TemporaryFile object from a row.
|
||||
*
|
||||
* @param array $row
|
||||
*
|
||||
* @return TemporaryFile
|
||||
*/
|
||||
public function _returnTemporaryFileFromRow($row)
|
||||
{
|
||||
$temporaryFile = $this->newDataObject();
|
||||
$temporaryFile->setId($row['file_id']);
|
||||
$temporaryFile->setServerFileName($row['file_name']);
|
||||
$temporaryFile->setFileType($row['file_type']);
|
||||
$temporaryFile->setFileSize($row['file_size']);
|
||||
$temporaryFile->setUserId($row['user_id']);
|
||||
$temporaryFile->setOriginalFileName($row['original_file_name']);
|
||||
$temporaryFile->setDateUploaded($this->datetimeFromDB($row['date_uploaded']));
|
||||
|
||||
Hook::call('TemporaryFileDAO::_returnTemporaryFileFromRow', [&$temporaryFile, &$row]);
|
||||
|
||||
return $temporaryFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new TemporaryFile.
|
||||
*
|
||||
* @param TemporaryFile $temporaryFile
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function insertObject($temporaryFile)
|
||||
{
|
||||
$this->update(
|
||||
sprintf(
|
||||
'INSERT INTO temporary_files
|
||||
(user_id, file_name, file_type, file_size, original_file_name, date_uploaded)
|
||||
VALUES
|
||||
(?, ?, ?, ?, ?, %s)',
|
||||
$this->datetimeToDB($temporaryFile->getDateUploaded())
|
||||
),
|
||||
[
|
||||
(int) $temporaryFile->getUserId(),
|
||||
$temporaryFile->getServerFileName(),
|
||||
$temporaryFile->getFileType(),
|
||||
(int) $temporaryFile->getFileSize(),
|
||||
$temporaryFile->getOriginalFileName()
|
||||
]
|
||||
);
|
||||
|
||||
$temporaryFile->setId($this->getInsertId());
|
||||
return $temporaryFile->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing temporary file.
|
||||
*/
|
||||
public function updateObject($temporaryFile)
|
||||
{
|
||||
$this->update(
|
||||
sprintf(
|
||||
'UPDATE temporary_files
|
||||
SET
|
||||
file_name = ?,
|
||||
file_type = ?,
|
||||
file_size = ?,
|
||||
user_id = ?,
|
||||
original_file_name = ?,
|
||||
date_uploaded = %s
|
||||
WHERE file_id = ?',
|
||||
$this->datetimeToDB($temporaryFile->getDateUploaded())
|
||||
),
|
||||
[
|
||||
$temporaryFile->getServerFileName(),
|
||||
$temporaryFile->getFileType(),
|
||||
(int) $temporaryFile->getFileSize(),
|
||||
(int) $temporaryFile->getUserId(),
|
||||
$temporaryFile->getOriginalFileName(),
|
||||
(int) $temporaryFile->getId()
|
||||
]
|
||||
);
|
||||
|
||||
return $temporaryFile->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a temporary file by ID.
|
||||
*
|
||||
* @param int $fileId
|
||||
* @param int $userId
|
||||
*/
|
||||
public function deleteTemporaryFileById($fileId, $userId)
|
||||
{
|
||||
return $this->update('DELETE FROM temporary_files WHERE file_id = ? AND user_id = ?', [(int) $fileId, (int) $userId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete temporary files by user ID.
|
||||
*
|
||||
* @param int $userId
|
||||
*/
|
||||
public function deleteByUserId($userId)
|
||||
{
|
||||
return $this->update('DELETE FROM temporary_files WHERE user_id = ?', [(int) $userId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all expired temorary files.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getExpiredFiles()
|
||||
{
|
||||
// Files older than one day can be cleaned up.
|
||||
$expiryThresholdTimestamp = time() - (60 * 60 * 24);
|
||||
$temporaryFiles = [];
|
||||
$result = $this->retrieve('SELECT * FROM temporary_files WHERE date_uploaded < ' . $this->datetimeToDB($expiryThresholdTimestamp));
|
||||
foreach ($result as $row) {
|
||||
$temporaryFiles[] = $this->_returnTemporaryFileFromRow((array) $row);
|
||||
}
|
||||
return $temporaryFiles;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\TemporaryFileDAO', '\TemporaryFileDAO');
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/file/TemporaryFileManager.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class TemporaryFileManager
|
||||
*
|
||||
* @ingroup file
|
||||
*
|
||||
* @see TemporaryFileDAO
|
||||
*
|
||||
* @brief Class defining operations for temporary file management.
|
||||
*/
|
||||
|
||||
namespace PKP\file;
|
||||
|
||||
use PKP\core\Core;
|
||||
use PKP\core\PKPString;
|
||||
use PKP\db\DAORegistry;
|
||||
|
||||
class TemporaryFileManager extends PrivateFileManager
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->_performPeriodicCleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base path for temporary file storage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBasePath()
|
||||
{
|
||||
return parent::getBasePath() . '/temp/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve file information by file ID.
|
||||
*
|
||||
* @return TemporaryFile
|
||||
*/
|
||||
public function getFile($fileId, $userId)
|
||||
{
|
||||
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
|
||||
return $temporaryFileDao->getTemporaryFile($fileId, $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file by ID.
|
||||
*
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function deleteById($fileId, $userId)
|
||||
{
|
||||
$temporaryFile = $this->getFile($fileId, $userId);
|
||||
|
||||
parent::deleteByPath($this->getBasePath() . $temporaryFile->getServerFileName());
|
||||
|
||||
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
|
||||
$temporaryFileDao->deleteTemporaryFileById($fileId, $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file.
|
||||
*
|
||||
* @param int $fileId the file id of the file to download
|
||||
* @param bool $inline print file as inline instead of attachment, optional
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function downloadById(int $fileId, int $userId, bool $inline = false)
|
||||
{
|
||||
$temporaryFile = $this->getFile($fileId, $userId);
|
||||
if (isset($temporaryFile)) {
|
||||
$filePath = $this->getBasePath() . $temporaryFile->getServerFileName();
|
||||
return parent::downloadByPath($filePath, null, $inline);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload the file and add it to the database.
|
||||
*
|
||||
* @param string $fileName index into the $_FILES array
|
||||
* @param int $userId
|
||||
*
|
||||
* @return object|boolean The new TemporaryFile or false on failure
|
||||
*/
|
||||
public function handleUpload($fileName, $userId)
|
||||
{
|
||||
// Get the file extension, then rename the file.
|
||||
$fileExtension = $this->parseFileExtension($this->getUploadedFileName($fileName));
|
||||
|
||||
if (!$this->fileExists($this->getBasePath(), 'dir')) {
|
||||
// Try to create destination directory
|
||||
$this->mkdirtree($this->getBasePath());
|
||||
}
|
||||
|
||||
$newFileName = basename(tempnam($this->getBasePath(), $fileExtension));
|
||||
if (!$newFileName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->uploadFile($fileName, $this->getBasePath() . $newFileName)) {
|
||||
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
|
||||
$temporaryFile = $temporaryFileDao->newDataObject();
|
||||
|
||||
$temporaryFile->setUserId($userId);
|
||||
$temporaryFile->setServerFileName($newFileName);
|
||||
$exploded = explode('.', $_FILES[$fileName]['name']);
|
||||
$temporaryFile->setFileType(PKPString::mime_content_type($this->getBasePath() . $newFileName, array_pop($exploded)));
|
||||
$temporaryFile->setFileSize($_FILES[$fileName]['size']);
|
||||
$temporaryFile->setOriginalFileName($this->truncateFileName($_FILES[$fileName]['name'], 127));
|
||||
$temporaryFile->setDateUploaded(Core::getCurrentDate());
|
||||
|
||||
$temporaryFileDao->insertObject($temporaryFile);
|
||||
|
||||
return $temporaryFile;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a TemporaryFile entry in DB based on an existing file in the system temp directory
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function createTempFileFromExisting(string $fileName, int $userId): int
|
||||
{
|
||||
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
|
||||
$temporaryFile = $temporaryFileDao->newDataObject();
|
||||
|
||||
$temporaryFile->setUserId($userId);
|
||||
$temporaryFile->setServerFileName(pathinfo($fileName, PATHINFO_BASENAME));
|
||||
$fileSize = filesize($fileName);
|
||||
$temporaryFile->setFileSize($fileSize);
|
||||
$temporaryFile->setDateUploaded(Core::getCurrentDate());
|
||||
|
||||
return $temporaryFileDao->insertObject($temporaryFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform periodic cleanup tasks. This is used to occasionally
|
||||
* remove expired temporary files.
|
||||
*/
|
||||
public function _performPeriodicCleanup()
|
||||
{
|
||||
if (time() % 100 == 0) {
|
||||
$temporaryFileDao = DAORegistry::getDAO('TemporaryFileDAO'); /** @var TemporaryFileDAO $temporaryFileDao */
|
||||
$expiredFiles = $temporaryFileDao->getExpiredFiles();
|
||||
foreach ($expiredFiles as $expiredFile) {
|
||||
$this->deleteById($expiredFile->getId(), $expiredFile->getUserId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\file\TemporaryFileManager', '\TemporaryFileManager');
|
||||
}
|
||||
Reference in New Issue
Block a user