generated from jric11/baseProject
Initial commit
This commit is contained in:
+257
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Byte.php
|
||||
*
|
||||
* @since 2015-07-28
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2015-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*
|
||||
* This file is part of tc-lib-file software library.
|
||||
*/
|
||||
|
||||
namespace Com\Tecnick\File;
|
||||
|
||||
use RangeException;
|
||||
|
||||
/**
|
||||
* Com\Tecnick\File\Byte
|
||||
*
|
||||
* Function to read byte-level data
|
||||
*
|
||||
* @since 2015-07-28
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2015-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*/
|
||||
readonly class Byte
|
||||
{
|
||||
/**
|
||||
* Length of the binary string in bytes.
|
||||
*/
|
||||
private int $length;
|
||||
|
||||
/**
|
||||
* Initialize a new string to be processed.
|
||||
*
|
||||
* Values are read in place via \ord() + bitwise math: no per-read unpack()
|
||||
* call and no byte-table copy, so memory stays at the size of the string.
|
||||
*
|
||||
* The read methods are deliberately inlined (each repeats the bounds check
|
||||
* and the \ord()/shift sequence) rather than sharing private helpers: every
|
||||
* userland call in PHP carries real frame-setup overhead and is not inlined
|
||||
* by the engine in the interpreter, so the duplication is a measurable speed
|
||||
* win on the hot read path.
|
||||
*
|
||||
* @param string $str String (binary) from where to extract values
|
||||
*/
|
||||
public function __construct(
|
||||
/**
|
||||
* Binary string to process
|
||||
*/
|
||||
protected string $str,
|
||||
) {
|
||||
$this->length = \strlen($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw for a read that failed its bounds check.
|
||||
*
|
||||
* Kept as a separate method so the cold error path does not bloat the
|
||||
* inlined read methods; it is never reached on a successful read.
|
||||
*
|
||||
* @param int $offset Read start position.
|
||||
* @param int $length Number of bytes requested.
|
||||
*
|
||||
* @throws RangeException always.
|
||||
*/
|
||||
private function throwOutOfBounds(int $offset, int $length): never
|
||||
{
|
||||
throw new RangeException(
|
||||
"Out-of-bounds read at offset {$offset} (length {$length}, string length {$this->length})",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get BYTE from string (8-bit unsigned integer).
|
||||
*
|
||||
* @param int $offset Point from where to read the data.
|
||||
*
|
||||
* @return int 8 bit value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getByte(int $offset): int
|
||||
{
|
||||
if ($offset < 0 || $offset >= $this->length) {
|
||||
$this->throwOutOfBounds($offset, 1);
|
||||
}
|
||||
|
||||
return \ord($this->str[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get USHORT from string (Big Endian 16-bit unsigned integer).
|
||||
*
|
||||
* @param int $offset Point from where to read the data
|
||||
*
|
||||
* @return int 16 bit value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getUShort(int $offset): int
|
||||
{
|
||||
if ($offset < 0 || $offset > ($this->length - 2)) {
|
||||
$this->throwOutOfBounds($offset, 2);
|
||||
}
|
||||
|
||||
return (\ord($this->str[$offset]) << 8) | \ord($this->str[$offset + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SHORT from string (Big Endian 16-bit signed integer).
|
||||
*
|
||||
* @param int $offset Point from where to read the data.
|
||||
*
|
||||
* @return int 16 bit value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getShort(int $offset): int
|
||||
{
|
||||
if ($offset < 0 || $offset > ($this->length - 2)) {
|
||||
$this->throwOutOfBounds($offset, 2);
|
||||
}
|
||||
|
||||
// The uint16 value
|
||||
$val = (\ord($this->str[$offset]) << 8) | \ord($this->str[$offset + 1]);
|
||||
|
||||
// Convert unsigned 16-bit to signed (two's complement)
|
||||
return ($val ^ 0x8000) - 0x8000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get UFWORD from string (Big Endian 16-bit unsigned integer).
|
||||
* Alias for getUShort().
|
||||
*
|
||||
* @param int $offset Point from where to read the data.
|
||||
*
|
||||
* @return int 16 bit value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getUFWord(int $offset): int
|
||||
{
|
||||
if ($offset < 0 || $offset > ($this->length - 2)) {
|
||||
$this->throwOutOfBounds($offset, 2);
|
||||
}
|
||||
|
||||
return (\ord($this->str[$offset]) << 8) | \ord($this->str[$offset + 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get FWORD from string (Big Endian 16-bit signed integer).
|
||||
* Alias for getShort().
|
||||
*
|
||||
* @param int $offset Point from where to read the data.
|
||||
*
|
||||
* @return int 16 bit value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getFWord(int $offset): int
|
||||
{
|
||||
if ($offset < 0 || $offset > ($this->length - 2)) {
|
||||
$this->throwOutOfBounds($offset, 2);
|
||||
}
|
||||
|
||||
// The uint16 value
|
||||
$val = (\ord($this->str[$offset]) << 8) | \ord($this->str[$offset + 1]);
|
||||
|
||||
// Convert unsigned 16-bit to signed (two's complement)
|
||||
return ($val ^ 0x8000) - 0x8000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ULONG from string (Big Endian 32-bit unsigned integer).
|
||||
*
|
||||
* @param int $offset Point from where to read the data
|
||||
*
|
||||
* @return int 32 bit value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getULong(int $offset): int
|
||||
{
|
||||
if ($offset < 0 || $offset > ($this->length - 4)) {
|
||||
$this->throwOutOfBounds($offset, 4);
|
||||
}
|
||||
|
||||
return (
|
||||
(\ord($this->str[$offset]) << 24)
|
||||
| (\ord($this->str[$offset + 1]) << 16)
|
||||
| (\ord($this->str[$offset + 2]) << 8)
|
||||
| \ord($this->str[$offset + 3])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LONG from string (Big Endian 32-bit signed integer).
|
||||
*
|
||||
* @param int $offset Point from where to read the data
|
||||
*
|
||||
* @return int 32 bit value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getLong(int $offset): int
|
||||
{
|
||||
if ($offset < 0 || $offset > ($this->length - 4)) {
|
||||
$this->throwOutOfBounds($offset, 4);
|
||||
}
|
||||
|
||||
// The uint32 value
|
||||
$val =
|
||||
(\ord($this->str[$offset]) << 24)
|
||||
| (\ord($this->str[$offset + 1]) << 16)
|
||||
| (\ord($this->str[$offset + 2]) << 8)
|
||||
| \ord($this->str[$offset + 3]);
|
||||
|
||||
// Convert unsigned 32-bit to signed (two's complement)
|
||||
return ($val ^ 0x8000_0000) - 0x8000_0000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get FIXED from string (Big Endian 32-bit signed fixed-point number (16.16)).
|
||||
*
|
||||
* A fixed-point 16.16 number is the signed int16 integer part plus the
|
||||
* unsigned 16-bit fractional part divided by 65536 = (1 << 16).
|
||||
*
|
||||
* @param int $offset Point from where to read the data.
|
||||
*
|
||||
* @return float Fixed-point value
|
||||
*
|
||||
* @throws RangeException if the requested read is out of bounds.
|
||||
*/
|
||||
public function getFixed(int $offset): float
|
||||
{
|
||||
if ($offset < 0 || $offset > ($this->length - 4)) {
|
||||
$this->throwOutOfBounds($offset, 4);
|
||||
}
|
||||
|
||||
// The int16 integer part
|
||||
$int16 = (((\ord($this->str[$offset]) << 8) | \ord($this->str[$offset + 1])) ^ 0x8000) - 0x8000;
|
||||
|
||||
// Add the uint16 fractional part
|
||||
return $int16 + (((\ord($this->str[$offset + 2]) << 8) | \ord($this->str[$offset + 3])) / 65_536.0);
|
||||
}
|
||||
}
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Cache.php
|
||||
*
|
||||
* @since 2011-05-23
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2011-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*
|
||||
* This file is part of tc-lib-file software library.
|
||||
*/
|
||||
|
||||
namespace Com\Tecnick\File;
|
||||
|
||||
/**
|
||||
* Com\Tecnick\File\Cache
|
||||
*
|
||||
* File caching system with per-instance path and prefix.
|
||||
* Each Cache instance maintains its own cache directory path and file prefix.
|
||||
*
|
||||
* @since 2011-05-23
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2011-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*/
|
||||
class Cache
|
||||
{
|
||||
/**
|
||||
* Pattern matching characters that are not allowed in cache filename tokens
|
||||
* (prefix, type, key). Stripping them keeps generated names valid on every
|
||||
* platform (notably Windows) and prevents glob metacharacters from reaching
|
||||
* delete()/deleteOlderThan(). getNewFileName() and delete() must use the
|
||||
* same pattern so the prefix-based glob matches the files actually created.
|
||||
*/
|
||||
private const SAFE_NAME_PATTERN = '/[^a-zA-Z0-9_\-]/';
|
||||
|
||||
/**
|
||||
* Cache path (per-instance)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $path = '';
|
||||
|
||||
/**
|
||||
* File prefix (per-instance)
|
||||
*/
|
||||
protected string $prefix;
|
||||
|
||||
/**
|
||||
* Set the file prefix (common name)
|
||||
*
|
||||
* @param ?string $prefix Common prefix to be used for all cache files
|
||||
*/
|
||||
public function __construct(?string $prefix = null)
|
||||
{
|
||||
$this->defineSystemCachePath();
|
||||
$this->setCachePath();
|
||||
$prefix ??= \rtrim(
|
||||
\base64_encode(\pack('H*', \md5(\uniqid((string) \mt_rand(0, \mt_getrandmax()), true)))),
|
||||
'=',
|
||||
);
|
||||
|
||||
$safePrefix = \preg_replace(self::SAFE_NAME_PATTERN, '', \strtr($prefix, '+/', '-_')) ?? '';
|
||||
$this->prefix = '_' . $safePrefix . '_';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache directory path
|
||||
*/
|
||||
public function getCachePath(): string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default cache directory path
|
||||
*
|
||||
* @param ?string $path Cache directory path; if null use the K_PATH_CACHE value
|
||||
*/
|
||||
public function setCachePath(?string $path = null): void
|
||||
{
|
||||
if ($path === null || \str_contains($path, '://') || !\is_writable($path)) {
|
||||
// Normalize the fallback too: K_PATH_CACHE may be supplied by the host
|
||||
// application without a trailing separator, and getNewFileName()/delete()
|
||||
// concatenate $this->path directly. Without normalization the generated
|
||||
// file would escape the cache directory (e.g. ".../cachedir" + "_pfx_..."
|
||||
// lands next to the directory instead of inside it).
|
||||
$this->path = $this->normalizePath((string) \constant('K_PATH_CACHE'));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->path = $this->normalizePath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file prefix
|
||||
*/
|
||||
public function getFilePrefix(): string
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a temporary filename for caching files.
|
||||
* Throws an exception when tempnam() fails, consistent with the rest of the library.
|
||||
*
|
||||
* @param string $type Type of file
|
||||
* @param string $key File key (used to retrieve file from cache)
|
||||
*
|
||||
* @return string Temporary filename
|
||||
*
|
||||
* @throws \Com\Tecnick\File\Exception when a temporary file cannot be created.
|
||||
*/
|
||||
public function getNewFileName(string $type = 'tmp', string $key = '0'): string
|
||||
{
|
||||
// Sanitize so the generated name matches the patterns used by delete()
|
||||
// and contains no characters that are invalid in Windows filenames.
|
||||
$safeType = \preg_replace(self::SAFE_NAME_PATTERN, '', $type) ?? '';
|
||||
$safeKey = \preg_replace(self::SAFE_NAME_PATTERN, '', $key) ?? '';
|
||||
|
||||
// tempnam() atomically creates a unique, private file, but on Windows it
|
||||
// keeps only the first three characters of the prefix. Create the file
|
||||
// with tempnam(), then rename it to a name carrying the full prefix so
|
||||
// the prefix-based glob in delete()/deleteOlderThan() works on every
|
||||
// platform. The rename preserves tempnam()'s restrictive permissions.
|
||||
$file = \tempnam($this->path, $this->prefix);
|
||||
if ($file === false) {
|
||||
throw new Exception('unable to create a temporary file in: ' . $this->path);
|
||||
}
|
||||
|
||||
$unique = \str_replace('.', '', \uniqid('', true));
|
||||
$target = $this->path . $this->prefix . $safeType . '_' . $safeKey . '_' . $unique;
|
||||
|
||||
$renamed = $this->withoutFsWarnings(static fn(): bool => \rename($file, $target));
|
||||
|
||||
return $renamed ? $target : $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cached files
|
||||
*
|
||||
* @param ?string $type Type of files to delete
|
||||
* @param ?string $key Specific file key to delete
|
||||
*/
|
||||
public function delete(?string $type = null, ?string $key = null): void
|
||||
{
|
||||
$safeType = $type !== null ? \preg_replace(self::SAFE_NAME_PATTERN, '', $type) : null;
|
||||
$safeKey = $key !== null ? \preg_replace(self::SAFE_NAME_PATTERN, '', $key) : null;
|
||||
|
||||
$path = $this->path . $this->prefix;
|
||||
if ($safeType !== null) {
|
||||
$path .= $safeType . '_';
|
||||
if ($safeKey !== null) {
|
||||
$path .= $safeKey . '_';
|
||||
}
|
||||
}
|
||||
|
||||
$path .= '*';
|
||||
$files = \glob($path);
|
||||
if ($files === [] || $files === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Suppress warnings: a file may vanish (concurrent cleanup, external
|
||||
// process) between glob() and unlink(); such races are non-fatal.
|
||||
$this->withoutFsWarnings(static function () use ($files): void {
|
||||
foreach ($files as $file) {
|
||||
\unlink($file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cache files older than the given number of seconds.
|
||||
*
|
||||
* @param int $seconds Maximum age in seconds; files whose mtime is older are removed.
|
||||
*/
|
||||
public function deleteOlderThan(int $seconds): void
|
||||
{
|
||||
$pattern = $this->path . $this->prefix . '*';
|
||||
$files = \glob($pattern);
|
||||
if ($files === [] || $files === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cutoff = \time() - $seconds;
|
||||
|
||||
// Suppress warnings: filemtime()/unlink() may fail if a file disappears
|
||||
// between glob() and the call (concurrent cleanup); such races are non-fatal.
|
||||
$this->withoutFsWarnings(static function () use ($files, $cutoff): void {
|
||||
foreach ($files as $file) {
|
||||
$mtime = \filemtime($file);
|
||||
if ($mtime !== false && $mtime < $cutoff) {
|
||||
\unlink($file);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a callable while suppressing expected filesystem warnings.
|
||||
*
|
||||
* The cache helpers race against other processes and against files that may
|
||||
* vanish between glob() and the operation; those calls already signal failure
|
||||
* via their return values, so the raw PHP warnings only add noise.
|
||||
*
|
||||
* @template T
|
||||
*
|
||||
* @param callable():T $callback
|
||||
*
|
||||
* @return T
|
||||
*/
|
||||
private function withoutFsWarnings(callable $callback): mixed
|
||||
{
|
||||
\set_error_handler(static fn(): bool => true, E_WARNING);
|
||||
|
||||
try {
|
||||
return $callback();
|
||||
} finally {
|
||||
\restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the K_PATH_CACHE constant (if not set) to the default system directory for temporary files
|
||||
*/
|
||||
protected function defineSystemCachePath(): void
|
||||
{
|
||||
if (\defined('K_PATH_CACHE')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$kPathCache = \ini_get('upload_tmp_dir');
|
||||
if ($kPathCache === false || $kPathCache === '') {
|
||||
$kPathCache = \sys_get_temp_dir();
|
||||
}
|
||||
\define('K_PATH_CACHE', $this->normalizePath($kPathCache));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize cache path
|
||||
*
|
||||
* @param string $path Path to normalize
|
||||
*/
|
||||
protected function normalizePath(string $path): string
|
||||
{
|
||||
$rpath = \realpath($path);
|
||||
if ($rpath === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!\str_ends_with($rpath, \DIRECTORY_SEPARATOR)) {
|
||||
$rpath .= \DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
return $rpath;
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Dir.php
|
||||
*
|
||||
* @since 2015-07-28
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2015-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*
|
||||
* This file is part of tc-lib-file software library.
|
||||
*/
|
||||
|
||||
namespace Com\Tecnick\File;
|
||||
|
||||
/**
|
||||
* Com\Tecnick\File\Dir
|
||||
*
|
||||
* Function to handle directories
|
||||
*
|
||||
* @since 2015-07-28
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2015-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*/
|
||||
class Dir
|
||||
{
|
||||
/**
|
||||
* Returns the full path of a parent directory
|
||||
*
|
||||
* @param string $name Name of the parent folder to search
|
||||
* @param string $dir Starting directory
|
||||
*
|
||||
* @return string Directory name
|
||||
*/
|
||||
public function findParentDir(string $name, string $dir = __DIR__): string
|
||||
{
|
||||
$allowedBases = $this->getOpenBasedirPaths();
|
||||
|
||||
while ($dir !== '') {
|
||||
if ($dir === \dirname($dir)) {
|
||||
$dir = '';
|
||||
}
|
||||
|
||||
$candidate = $dir . DIRECTORY_SEPARATOR . $name;
|
||||
if ($this->isPathAllowed($candidate, $allowedBases) && \is_writable($candidate)) {
|
||||
$dir = $candidate;
|
||||
break;
|
||||
}
|
||||
|
||||
$dir = \dirname($dir);
|
||||
}
|
||||
|
||||
if (\substr($dir, -1) !== DIRECTORY_SEPARATOR) {
|
||||
$dir .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
return $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of directories allowed by the active open_basedir restriction.
|
||||
*
|
||||
* An empty array means that no restriction is in effect.
|
||||
*
|
||||
* @return array<string> Allowed base directories without trailing separator.
|
||||
*/
|
||||
private function getOpenBasedirPaths(): array
|
||||
{
|
||||
$openBasedir = \ini_get('open_basedir');
|
||||
if ($openBasedir === false || $openBasedir === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$paths = [];
|
||||
foreach (\explode(PATH_SEPARATOR, $openBasedir) as $path) {
|
||||
$path = \rtrim($path, '/\\');
|
||||
if ($path !== '') {
|
||||
$paths[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the given path can be safely probed under the active open_basedir restriction.
|
||||
*
|
||||
* Probing a path outside the allowed list raises an open_basedir E_WARNING (which can
|
||||
* corrupt the output stream or be promoted to an exception by the application error handler),
|
||||
* so such paths must be skipped. When no restriction is in effect every path is allowed.
|
||||
*
|
||||
* @param string $path Path to check.
|
||||
* @param array<string> $allowedBases Allowed base directories (empty when unrestricted).
|
||||
*/
|
||||
private function isPathAllowed(string $path, array $allowedBases): bool
|
||||
{
|
||||
if ($allowedBases === []) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($allowedBases as $base) {
|
||||
if ($path === $base || \str_starts_with($path, $base . DIRECTORY_SEPARATOR)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Exception.php
|
||||
*
|
||||
* @since 2015-07-28
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2015-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*
|
||||
* This file is part of tc-lib-file software library.
|
||||
*/
|
||||
|
||||
namespace Com\Tecnick\File;
|
||||
|
||||
/**
|
||||
* Com\Tecnick\File\Exception
|
||||
*
|
||||
* Custom Exception class
|
||||
*
|
||||
* @since 2015-07-28
|
||||
* @category Library
|
||||
* @package File
|
||||
* @author Nicola Asuni <info@tecnick.com>
|
||||
* @copyright 2015-2026 Nicola Asuni - Tecnick.com LTD
|
||||
* @license https://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE)
|
||||
* @link https://github.com/tecnickcom/tc-lib-file
|
||||
*/
|
||||
class Exception extends \Exception {}
|
||||
+1187
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user