ldc-dam/app/Lib/ToolboxHelper.php

256 lines
8.5 KiB
PHP
Raw Normal View History

<?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');
}
}