composer require ldc/web-status-checker-laravel remove Old static status checker Fix ImportMedia WIP commands OK many fixes Fix and try to optimize folder component Fix front icons + actions based on icons Favico front fix alert Fix Media upload on depot fix folder component buttons Full front fix with perf due tu vuejs Download medias Navigate within medias superfix Move media + loader isLocked boolean and remove media fix Folder scroll fix arcadia link color red Fix panier show external Tons of fixes back as front REwrited all
255 lines
8.5 KiB
PHP
255 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace App\Lib;
|
|
|
|
use App\Enums\MediaExtension;
|
|
use getID3;
|
|
use Illuminate\Support\Str;
|
|
use Imagick;
|
|
use ImagickException;
|
|
|
|
class ToolboxHelper
|
|
{
|
|
/**
|
|
* Get ID3 Play time string
|
|
*
|
|
* @param string $filepath
|
|
* @return string|null
|
|
*/
|
|
public static function getId3Playtime(string $filepath): ?string
|
|
{
|
|
$getID3 = new getID3();
|
|
|
|
$results = $getID3->analyze($filepath);
|
|
|
|
if (array_key_exists('error', $results)) {
|
|
return null;
|
|
}
|
|
if (array_key_exists('playtime_string', $results)) {
|
|
return \strval($results['playtime_string']);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get ID3 video dimensions
|
|
*
|
|
* @param string $filepath
|
|
* @return array|null Containing 'width' and 'height'
|
|
*/
|
|
public static function getId3VideoDimensions(string $filepath): ?array
|
|
{
|
|
$getID3 = new getID3();
|
|
|
|
$results = $getID3->analyze($filepath);
|
|
|
|
if (array_key_exists('error', $results)) {
|
|
return null;
|
|
}
|
|
if (isset($results['video']['resolution_x']) and isset($results['video']['resolution_y'])) {
|
|
return [
|
|
'width' => \intval($results['video']['resolution_x']),
|
|
'height' => \intval($results['video']['resolution_y'])
|
|
];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* resolution in pixels per centimeter
|
|
*
|
|
* @param string $filepath
|
|
* @return array|null Containing 'resolutionX', 'resolutionY', 'width' and 'height'
|
|
*/
|
|
public static function getImageDimensions(string $filepath): ?array
|
|
{
|
|
$ext = \pathinfo($filepath, \PATHINFO_EXTENSION);
|
|
try {
|
|
$im = new Imagick($filepath);
|
|
if (
|
|
in_array($ext, [
|
|
MediaExtension::pdf->value,
|
|
MediaExtension::ai->value,
|
|
MediaExtension::psd->value,
|
|
MediaExtension::gif->value
|
|
])
|
|
) {
|
|
$im->setIteratorIndex(0);
|
|
}
|
|
|
|
$r = $im->getImageResolution();
|
|
$u = $im->getImageUnits();
|
|
|
|
// Force image resolution to pixel per centimeters.
|
|
if ($u == Imagick::RESOLUTION_PIXELSPERINCH) {
|
|
$r['x'] = (int)round($r['x'] / 2.54);
|
|
$r['y'] = (int)round($r['y'] / 2.54);
|
|
$im->setImageUnits(Imagick::RESOLUTION_PIXELSPERCENTIMETER);
|
|
$im->setImageResolution($r['x'], $r['y']);
|
|
|
|
// Note that the number type is double again.
|
|
$r = $im->getImageResolution();
|
|
}
|
|
|
|
$imageprops = $im->getImageGeometry();
|
|
$im->destroy();
|
|
return [
|
|
'resolutionX' => \intval($r['x']),
|
|
'resolutionY' => \intval($r['y']),
|
|
'width' => \intval($imageprops['width']),
|
|
'height' => \intval($imageprops['height'])
|
|
];
|
|
} catch (ImagickException $e) {
|
|
report($e);
|
|
} //end try
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Sanitize File name for uploaded files
|
|
*
|
|
* @param string $filename The original uploaded client file name.
|
|
* @param boolean $beautify Beautify the filename.
|
|
* @return string The sanitized file name.
|
|
*/
|
|
public static function sanitizeFileName(string $filename, bool $beautify = true): string
|
|
{
|
|
// * Sanitize filename
|
|
// phpcs:disable Generic.Files.LineLength.TooLong
|
|
$filename = preg_replace(
|
|
'~
|
|
[<>:"/\\\|?*]| # file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
|
|
[\x00-\x1F]| # control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
|
|
[\x7F\xA0\xAD]| # non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
|
|
[#\[\]@!$&\'()+,;=]| # URI reserved https://tools.ietf.org/html/rfc3986#section-2.2
|
|
[{}^\~`] # URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
|
|
~x',
|
|
'-',
|
|
$filename
|
|
);
|
|
// phpcs:enable
|
|
// * Avoids '.' '..' or '.hiddenFiles' .
|
|
$filename = Str::of($filename)->ltrim('.-');
|
|
// * Optional beautification
|
|
if ($beautify) {
|
|
$filename = static::beautifyFilename($filename);
|
|
}
|
|
// * Maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
|
|
/** @var string */
|
|
$extension = pathinfo($filename, \PATHINFO_EXTENSION);
|
|
/** @var string */
|
|
$filename = pathinfo($filename, \PATHINFO_FILENAME);
|
|
|
|
$encoding = mb_detect_encoding($filename);
|
|
$encoding = $encoding ? $encoding : null;
|
|
return \mb_strcut(
|
|
$filename,
|
|
0,
|
|
255 - (!empty($extension) ? strlen($extension) + 1 : 0),
|
|
$encoding
|
|
) . (!empty($extension) ? ".$extension" : '');
|
|
}
|
|
|
|
/**
|
|
* Beautify a filename
|
|
*
|
|
* @param string $filename
|
|
* @return string
|
|
*/
|
|
private static function beautifyFilename(string $filename): string
|
|
{
|
|
// Reduce consecutive characters.
|
|
$filename = preg_replace([
|
|
// * "file name.zip" becomes 'file-name.zip'
|
|
'/ +/',
|
|
// * "file___name.zip" becomes 'file-name.zip'
|
|
'/_+/',
|
|
// * "file---name.zip" becomes 'file-name.zip'
|
|
'/-+/'
|
|
], '-', $filename);
|
|
$filename = preg_replace([
|
|
// * "file--.--.-.--name.zip" becomes "file.name.zip"
|
|
'/-*\.-*/',
|
|
// * "file...name..zip" becomes "file.name.zip"
|
|
'/\.{2,}/'
|
|
], '.', $filename);
|
|
// Lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625 .
|
|
$filename = mb_strtolower($filename, mb_detect_encoding($filename));
|
|
// * ".file-name.-" becomes "file-name"
|
|
$filename = trim($filename, '.-');
|
|
return $filename;
|
|
}
|
|
|
|
/**
|
|
* Convert file size to human readable string
|
|
*
|
|
* @param mixed $octet
|
|
* @param integer $precision
|
|
* @return string
|
|
*/
|
|
public static function formatBytes(mixed $octet, int $precision = 2): string
|
|
{
|
|
// * Array contenant les differents unités
|
|
$unite = ['octet', 'Kio', 'Mio', 'Gio'];
|
|
|
|
$octet = \floatval($octet);
|
|
|
|
$Kio = 1024;
|
|
$Mio = 1024 * $Kio;
|
|
$Gio = 1024 * $Mio;
|
|
|
|
switch (true) {
|
|
// * octet
|
|
case $octet < $Kio:
|
|
return $octet . $unite[0];
|
|
// * kio
|
|
case $octet < $Mio:
|
|
return $octet . $unite[1];
|
|
// * Mio
|
|
case $octet < $Gio:
|
|
return \round($octet / $Mio, $precision) . $unite[2];
|
|
// * Gio
|
|
default:
|
|
// * Gio
|
|
return \round($octet / $Gio, $precision) . $unite[3];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* * Register CSP report URI
|
|
*
|
|
* Put this function inside RouteServiceProvider,
|
|
* and call it in RouteServiceProvider::boot
|
|
*
|
|
* ! Use this in conjonction with kwaadpepper/exception-handler
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function cspReportRoute()
|
|
{
|
|
// * CSP REPORT URI, Please add /csp-report to VerifyCsrfToken $except middleware
|
|
\Illuminate\Support\Facades\Route::post('/csp-report', function () {
|
|
$isCspRequest = request()->header('Content-Type') === 'application/csp-report';
|
|
if (!$isCspRequest or !request()->json('csp-report') or !is_array(request()->json('csp-report'))) {
|
|
abort(401);
|
|
}
|
|
// * Flatten if needed
|
|
$cspReport = collect(request()->json('csp-report'))
|
|
->flatMap(function ($v, $k) {
|
|
return [$k => is_array($v) ? collect($v)->flatten()->implode(', ') : $v];
|
|
})->all();
|
|
// * Filter array keys
|
|
$cspReport = collect(array_intersect_key($cspReport, [
|
|
'blocked-uri' => '', 'document-uri' => '', 'original-policy' => '',
|
|
'referrer' => '', 'violated-directive' => ''
|
|
]));
|
|
report(new \Illuminate\Http\Client\HttpClientException(sprintf(
|
|
"CSP REPORT for %s : \n %s",
|
|
$cspReport->get('document-uri'),
|
|
$cspReport->implode("\n")
|
|
)));
|
|
})->middleware('throttle:5,2')
|
|
->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class)
|
|
->name('cspReportUri');
|
|
}
|
|
}
|