mirror of
https://github.com/Karaka-Management/oms-Media.git
synced 2026-01-11 17:08:40 +00:00
397 lines
9.5 KiB
PHP
397 lines
9.5 KiB
PHP
<?php
|
|
/**
|
|
* Orange Management
|
|
*
|
|
* PHP Version 7.1
|
|
*
|
|
* @category TBD
|
|
* @package TBD
|
|
* @author OMS Development Team <dev@oms.com>
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
* @copyright Dennis Eichhorn
|
|
* @license OMS License 1.0
|
|
* @version 1.0.0
|
|
* @link http://orange-management.com
|
|
*/
|
|
namespace Modules\Media\Models;
|
|
|
|
use phpOMS\System\File\Local\Directory;
|
|
|
|
|
|
/**
|
|
* Upload.
|
|
*
|
|
* @category Modules
|
|
* @package Modules\Media
|
|
* @author OMS Development Team <dev@oms.com>
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
* @license OMS License 1.0
|
|
* @link http://orange-management.com
|
|
* @since 1.0.0
|
|
*/
|
|
class UploadFile
|
|
{
|
|
/* public */ const PATH_GENERATION_LIMIT = 1000;
|
|
|
|
/**
|
|
* Image interlaced.
|
|
*
|
|
* @var int
|
|
* @since 1.0.0
|
|
*/
|
|
private $interlaced = true;
|
|
|
|
/**
|
|
* Upload max size.
|
|
*
|
|
* @var int
|
|
* @since 1.0.0
|
|
*/
|
|
private $maxSize = 50000000;
|
|
|
|
/**
|
|
* Allowed mime types.
|
|
*
|
|
* @var array
|
|
* @since 1.0.0
|
|
*/
|
|
private $allowedTypes = [];
|
|
|
|
/**
|
|
* Output directory.
|
|
*
|
|
* @var string
|
|
* @since 1.0.0
|
|
*/
|
|
private $outputDir = 'Modules/Media/Files';
|
|
|
|
/**
|
|
* Output file name.
|
|
*
|
|
* @var string
|
|
* @since 1.0.0
|
|
*/
|
|
private $fileName = '';
|
|
|
|
/**
|
|
* Output file name.
|
|
*
|
|
* @var bool
|
|
* @since 1.0.0
|
|
*/
|
|
private $preserveFileName = true;
|
|
|
|
/**
|
|
* Upload file to server.
|
|
*
|
|
* @param array $files File data ($_FILE)
|
|
*
|
|
* @return array
|
|
*
|
|
* @throws \Exception
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function upload(array $files) : array
|
|
{
|
|
$result = [];
|
|
|
|
if (count($files) == count($files, COUNT_RECURSIVE)) {
|
|
$files = [$files];
|
|
}
|
|
|
|
$this->findOutputDir($files);
|
|
$path = ROOT_PATH . $this->outputDir;
|
|
|
|
foreach ($files as $key => $f) {
|
|
$result[$key] = [];
|
|
$result[$key]['status'] = UploadStatus::OK;
|
|
|
|
if (!isset($f['error'])) {
|
|
// TODO: handle wrong parameters
|
|
$result[$key]['status'] = UploadStatus::WRONG_PARAMETERS;
|
|
|
|
return $result;
|
|
} elseif ($f['error'] !== UPLOAD_ERR_OK) {
|
|
$result[$key]['status'] = $this->getUploadError($f['error']);
|
|
|
|
return $result;
|
|
}
|
|
|
|
$result[$key]['size'] = $f['size'];
|
|
|
|
if ($f['size'] > $this->maxSize) {
|
|
// too large2
|
|
$result[$key]['status'] = UploadStatus::CONFIG_SIZE;
|
|
|
|
return $result;
|
|
}
|
|
|
|
// TODO: do I need pecl fileinfo?
|
|
if (!empty($this->allowedTypes) && ($ext = array_search($f['type'], $this->allowedTypes, true)) === false) {
|
|
// wrong file format
|
|
$result[$key]['status'] = UploadStatus::WRONG_EXTENSION;
|
|
|
|
return $result;
|
|
}
|
|
|
|
if ($this->preserveFileName) {
|
|
$this->fileName = $f['name'];
|
|
}
|
|
|
|
$split = explode('.', $f['name']);
|
|
$result[$key]['name'] = $split[0];
|
|
$extension = count($split) > 1 ? $split[count($split) - 1] : '';
|
|
$result[$key]['extension'] = $extension;
|
|
|
|
// ! and empty same?!
|
|
$result[$key]['filename'] = $this->fileName;
|
|
if (!$this->fileName || empty($this->fileName) || file_exists($path . '/' . $this->fileName)) {
|
|
$rnd = '';
|
|
|
|
$limit = 0;
|
|
do {
|
|
$sha = sha1_file($f['tmp_name'] . $rnd);
|
|
|
|
if ($sha === false) {
|
|
$result[$key]['status'] = UploadStatus::FAILED_HASHING;
|
|
|
|
return $result;
|
|
}
|
|
|
|
$sha .= '.' . $extension;
|
|
|
|
$this->fileName = $sha;
|
|
$rnd = mt_rand();
|
|
$limit++;
|
|
} while (file_exists($path . '/' . $this->fileName) && $limit < self::PATH_GENERATION_LIMIT);
|
|
|
|
if($limit >= self::PATH_GENERATION_LIMIT) {
|
|
throw new \Exception('No file path could be found. Potential attack!');
|
|
}
|
|
}
|
|
|
|
if (!is_dir($path)) {
|
|
Directory::create($path, 0655, true);
|
|
}
|
|
|
|
if (!is_uploaded_file($f['tmp_name'])) {
|
|
$result[$key]['status'] = UploadStatus::NOT_UPLOADED;
|
|
|
|
return $result;
|
|
}
|
|
|
|
if (!move_uploaded_file($f['tmp_name'], $dest = $path . '/' . $this->fileName)) {
|
|
$result[$key]['status'] = UploadStatus::NOT_MOVABLE;
|
|
|
|
return $result;
|
|
}
|
|
|
|
if($this->interlaced && in_array($extension, ['png', 'jpg', 'jpeg', 'gif'])) {
|
|
$this->interlace($extension, $dest);
|
|
}
|
|
|
|
$result[$key]['path'] = $this->outputDir;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function interlace(string $extension, string $path) /* : void */
|
|
{
|
|
|
|
if($extension === 'png') {
|
|
$img = imagecreatefrompng($path);
|
|
} elseif($extension === 'jpg' || $extension === 'jpeg') {
|
|
$img = imagecreatefromjpeg($path);
|
|
} else {
|
|
$img = imagecreatefromgif($path);
|
|
}
|
|
|
|
imageinterlace($img, (int) $this->interlaced);
|
|
|
|
if($extension === 'png') {
|
|
imagepng($img, $path);
|
|
} elseif($extension === 'jpg' || $extension === 'jpeg') {
|
|
imagejpeg($img, $path);
|
|
} else {
|
|
imagegif($img, $path);
|
|
}
|
|
|
|
imagedestroy($img);
|
|
}
|
|
|
|
/**
|
|
* Find unique output path for batch of files
|
|
*
|
|
* @param array $files Array of files
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
private function findOutputDir(array $files)
|
|
{
|
|
if (count($files) > 1) {
|
|
do {
|
|
$rndPath = str_pad(dechex(rand(0, 65535)), 4, '0', STR_PAD_LEFT);
|
|
} while (file_exists($this->outputDir . '/' . $rndPath));
|
|
|
|
$this->outputDir = $this->outputDir . '/' . $rndPath;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get upload error
|
|
*
|
|
* @param mixed $error Error type
|
|
*
|
|
* @return int
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
private function getUploadError($error) : int
|
|
{
|
|
switch ($error) {
|
|
case UPLOAD_ERR_NO_FILE:
|
|
// TODO: no file sent
|
|
return UploadStatus::NOTHING_UPLOADED;
|
|
case UPLOAD_ERR_INI_SIZE:
|
|
case UPLOAD_ERR_FORM_SIZE:
|
|
return UploadStatus::UPLOAD_SIZE;
|
|
default:
|
|
return UploadStatus::UNKNOWN_ERROR;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return int
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function getMaxSize() : int
|
|
{
|
|
return $this->maxSize;
|
|
}
|
|
|
|
public function setInterlaced(bool $interlaced) /* : void */
|
|
{
|
|
$this->interlaced = $interlaced;
|
|
}
|
|
|
|
/**
|
|
* @param int $maxSize
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function setMaxSize(int $maxSize)
|
|
{
|
|
$this->maxSize = $maxSize;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function getAllowedTypes() : array
|
|
{
|
|
return $this->allowedTypes;
|
|
}
|
|
|
|
/**
|
|
* @param array $allowedTypes
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function setAllowedTypes(array $allowedTypes)
|
|
{
|
|
$this->allowedTypes = $allowedTypes;
|
|
}
|
|
|
|
/**
|
|
* @param array $allowedTypes
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function addAllowedTypes($allowedTypes)
|
|
{
|
|
$this->allowedTypes[] = $allowedTypes;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function getOutputDir() : string
|
|
{
|
|
return $this->outputDir;
|
|
}
|
|
|
|
/**
|
|
* @param string $outputDir
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function setOutputDir(string $outputDir)
|
|
{
|
|
$this->outputDir = $outputDir;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function getFileName() : string
|
|
{
|
|
return $this->fileName;
|
|
}
|
|
|
|
/**
|
|
* @param string $fileName
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function setFileName(string $fileName)
|
|
{
|
|
$this->fileName = $fileName;
|
|
}
|
|
|
|
/**
|
|
* @param bool $preserveFileName
|
|
*
|
|
* @return void
|
|
*
|
|
* @since 1.0.0
|
|
* @author Dennis Eichhorn <d.eichhorn@oms.com>
|
|
*/
|
|
public function setPreserveFileName(bool $preserveFileName)
|
|
{
|
|
$this->preserveFileName = $preserveFileName;
|
|
}
|
|
}
|