chore(tests): UT for Image

Signed-off-by: Rubén D <nuxsmin@syspass.org>
This commit is contained in:
Rubén D
2024-04-28 10:24:01 +02:00
parent e1dcf74dda
commit ce7d02f5e5
31 changed files with 385 additions and 310 deletions

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -26,7 +26,7 @@ use Psr\Container\ContainerInterface;
use SP\Domain\Core\Bootstrap\BootstrapInterface;
use SP\Domain\Core\Bootstrap\ModuleInterface;
use SP\Modules\Api\Bootstrap;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use function SP\processException;
@@ -34,7 +34,7 @@ const APP_ROOT = __DIR__;
const APP_MODULE = 'api';
try {
$dic = FileUtil::require(FileUtil::buildPath(APP_ROOT, 'lib', 'Base.php'), ContainerInterface::class);
$dic = FileSystemUtil::require(FileSystemUtil::buildPath(APP_ROOT, 'lib', 'Base.php'), ContainerInterface::class);
Bootstrap::run($dic->get(BootstrapInterface::class), $dic->get(ModuleInterface::class));
} catch (Throwable $e) {

View File

@@ -38,11 +38,11 @@ use SP\Domain\Account\Ports\PublicLinkService;
use SP\Domain\Account\Services\PublicLink;
use SP\Domain\Core\Acl\AclActionsInterface;
use SP\Domain\Core\Crypt\VaultInterface;
use SP\Domain\Image\Ports\ImageService;
use SP\Http\Uri;
use SP\Mvc\Controller\WebControllerHelper;
use SP\Util\ErrorUtil;
use SP\Util\ImageUtil;
use SP\Util\ImageUtilInterface;
use SP\Util\Image;
use SP\Util\Serde;
/**
@@ -52,15 +52,15 @@ final class ViewLinkController extends AccountControllerBase
{
private AccountService $accountService;
private ThemeIcons $icons;
private PublicLink $publicLinkService;
private ImageUtil $imageUtil;
private PublicLink $publicLinkService;
private Image $imageUtil;
public function __construct(
Application $application,
WebControllerHelper $webControllerHelper,
AccountService $accountService,
PublicLinkService $publicLinkService,
ImageUtilInterface $imageUtil
ImageService $imageUtil
) {
parent::__construct(
$application,

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -31,7 +31,7 @@ use SP\Core\Events\EventMessage;
use SP\Domain\Core\Exceptions\SPException;
use SP\Http\JsonMessage;
use SP\Modules\Web\Controllers\Traits\JsonTrait;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
/**
* Class ViewController
@@ -61,7 +61,7 @@ final class ViewController extends AccountFileBase
$this->view->addTemplate('file', 'itemshow');
if (FileUtil::isImage($fileData)) {
if (FileSystemUtil::isImage($fileData)) {
$this->view->assign('data', chunk_split(base64_encode($fileData->getContent())));
$this->view->assign('fileData', $fileData);
$this->view->assign('isImage', 1);

View File

@@ -39,12 +39,12 @@ use SP\Domain\Core\Acl\AclInterface;
use SP\Domain\Core\Exceptions\FileNotFoundException;
use SP\Domain\Crypt\Ports\MasterPassService;
use SP\Domain\Http\RequestInterface;
use SP\Domain\Image\Ports\ImageService;
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Modules\Web\Controllers\Helpers\HelperBase;
use SP\Modules\Web\Controllers\Helpers\HelperException;
use SP\Mvc\View\TemplateInterface;
use SP\Util\ImageUtil;
use SP\Util\ImageUtilInterface;
use SP\Util\Image;
/**
* Class AccountPasswordHelper
@@ -53,16 +53,16 @@ use SP\Util\ImageUtilInterface;
*/
final class AccountPasswordHelper extends HelperBase
{
private Acl $acl;
private ImageUtil $imageUtil;
private Acl $acl;
private Image $imageUtil;
private MasterPassService $masterPassService;
public function __construct(
Application $application,
TemplateInterface $template,
RequestInterface $request,
AclInterface $acl,
ImageUtilInterface $imageUtil,
Application $application,
TemplateInterface $template,
RequestInterface $request,
AclInterface $acl,
ImageService $imageUtil,
MasterPassService $masterPassService
) {
parent::__construct($application, $template, $request);

View File

@@ -40,7 +40,7 @@ use SP\Html\DataGrid\Action\DataGridAction;
use SP\Http\Uri;
use SP\Mvc\View\TemplateInterface;
use SP\Plugin\PluginManager;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use SP\Util\VersionUtil;
use function SP\__;
@@ -171,7 +171,7 @@ final class LayoutHelper extends HelperBase
$jsUriTheme = new Uri($baseUrl);
$jsUriTheme->addParams(
[
'b' => FileUtil::buildPath($this->theme->getPath(), 'js'),
'b' => FileSystemUtil::buildPath($this->theme->getPath(), 'js'),
'f' => implode(',', $themeInfo['js'])
]
);
@@ -207,7 +207,7 @@ final class LayoutHelper extends HelperBase
$cssUriTheme = new Uri($baseUrl);
$cssUriTheme->addParams(
[
'b' => FileUtil::buildPath($this->theme->getPath(), 'css'),
'b' => FileSystemUtil::buildPath($this->theme->getPath(), 'css'),
'f' => implode(',', $themeInfo['css'])
]
);
@@ -228,7 +228,7 @@ final class LayoutHelper extends HelperBase
if (count($jsResources) > 0) {
$jsUriPlugin = new Uri($baseUrl);
$jsUriPlugin->addParams([
'b' => FileUtil::buildPath($base, 'js'),
'b' => FileSystemUtil::buildPath($base, 'js'),
'f' => implode(',', $jsResources)
]);
@@ -239,7 +239,7 @@ final class LayoutHelper extends HelperBase
$cssUriPlugin = new Uri($baseUrl);
$cssUriPlugin->addParams(
[
'b' => FileUtil::buildPath($base, 'css'),
'b' => FileSystemUtil::buildPath($base, 'css'),
'f' => implode(',', $cssResources)
]
);

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -26,7 +26,7 @@ namespace SP\Modules\Web\Controllers\Resource;
use SP\Http\Request as HttpRequest;
use SP\Infrastructure\File\FileHandler;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
/**
* Class CssController
@@ -57,11 +57,11 @@ final class CssController extends ResourceBase
->addFiles($files)
->getMinified();
} else {
$files = $this->buildFiles(FileUtil::buildPath(PUBLIC_PATH, 'vendor', 'css'), self::CSS_MIN_FILES);
$files = $this->buildFiles(FileSystemUtil::buildPath(PUBLIC_PATH, 'vendor', 'css'), self::CSS_MIN_FILES);
$this->minify->builder()
->addFiles($files, false)
->addFile(new FileHandler(FileUtil::buildPath(PUBLIC_PATH, 'css', 'fonts.min.css')), false)
->addFile(new FileHandler(FileSystemUtil::buildPath(PUBLIC_PATH, 'css', 'fonts.min.css')), false)
->getMinified();
}
}
@@ -77,7 +77,7 @@ final class CssController extends ResourceBase
$base = $insecure ? HttpRequest::getSecureAppPath($base) : $base;
return array_map(
fn(string $file) => new FileHandler(FileUtil::buildPath($base, $file)),
fn(string $file) => new FileHandler(FileSystemUtil::buildPath($base, $file)),
$files
);
}

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -26,7 +26,7 @@ namespace SP\Modules\Web\Controllers\Resource;
use SP\Http\Request as HttpRequest;
use SP\Infrastructure\File\FileHandler;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
/**
* Class JsController
@@ -80,14 +80,17 @@ final class JsController extends ResourceBase
$this->minify
->builder()
->addFiles(
$this->buildFiles(FileUtil::buildPath(PUBLIC_PATH, 'vendor', 'js'), self::JS_MIN_FILES),
$this->buildFiles(FileSystemUtil::buildPath(PUBLIC_PATH, 'vendor', 'js'), self::JS_MIN_FILES),
false
)
->getMinified();
} elseif ($group === 1) {
$this->minify
->builder()
->addFiles($this->buildFiles(FileUtil::buildPath(PUBLIC_PATH, 'js'), self::JS_APP_MIN_FILES), false)
->addFiles(
$this->buildFiles(FileSystemUtil::buildPath(PUBLIC_PATH, 'js'), self::JS_APP_MIN_FILES),
false
)
->getMinified();
}
}
@@ -104,7 +107,7 @@ final class JsController extends ResourceBase
$base = $insecure ? HttpRequest::getSecureAppPath($base) : $base;
return array_map(
fn(string $file) => new FileHandler(FileUtil::buildPath($base, $file)),
fn(string $file) => new FileHandler(FileSystemUtil::buildPath($base, $file)),
$files
);
}

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -24,7 +24,7 @@
use Psr\Container\ContainerInterface;
use SP\Domain\Core\Bootstrap\ModuleInterface;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use function SP\logger;
use function SP\processException;
@@ -33,7 +33,7 @@ const APP_ROOT = __DIR__;
const APP_MODULE = 'cli';
try {
$dic = FileUtil::require(FileUtil::buildPath(APP_ROOT, 'lib', 'Base.php'), ContainerInterface::class);
$dic = FileSystemUtil::require(FileSystemUtil::buildPath(APP_ROOT, 'lib', 'Base.php'), ContainerInterface::class);
logger('------------');
logger('Boostrap:cli');

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -26,7 +26,7 @@ use Psr\Container\ContainerInterface;
use SP\Domain\Core\Bootstrap\BootstrapInterface;
use SP\Domain\Core\Bootstrap\ModuleInterface;
use SP\Modules\Web\Bootstrap;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use function SP\processException;
@@ -34,7 +34,7 @@ const APP_ROOT = __DIR__;
const APP_MODULE = 'web';
try {
$dic = FileUtil::require(FileUtil::buildPath(APP_ROOT, 'lib', 'Base.php'), ContainerInterface::class);
$dic = FileSystemUtil::require(FileSystemUtil::buildPath(APP_ROOT, 'lib', 'Base.php'), ContainerInterface::class);
Bootstrap::run($dic->get(BootstrapInterface::class), $dic->get(ModuleInterface::class));
} catch (Throwable $e) {

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -26,7 +26,7 @@ namespace SP;
use Exception;
use SP\Domain\Core\Exceptions\SPException;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use Throwable;
/**
@@ -252,7 +252,7 @@ function initModule(string $module): array
logger(sprintf('Initializing module: %s', $module));
try {
$definitions = FileUtil::require(FileUtil::buildPath(MODULES_PATH, $module, 'module.php'));
$definitions = FileSystemUtil::require(FileSystemUtil::buildPath(MODULES_PATH, $module, 'module.php'));
if (is_array($definitions)) {
return $definitions;

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -31,7 +31,7 @@ use SP\Domain\Core\UI\ThemeContextInterface;
use SP\Domain\Core\UI\ThemeIconsInterface;
use SP\Domain\Core\UI\ThemeInterface;
use SP\Infrastructure\File\FileException;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use function SP\processException;
@@ -70,8 +70,8 @@ final class Theme implements ThemeInterface
while (false !== ($themeDir = $directory->read())) {
if (is_dir($themeDir) && $themeDir !== '.' && $themeDir !== '..') {
try {
$themeInfo = FileUtil::require(
FileUtil::buildPath($this->themeContext->getViewsPath(), $themeDir, 'index.php')
$themeInfo = FileSystemUtil::require(
FileSystemUtil::buildPath($this->themeContext->getViewsPath(), $themeDir, 'index.php')
);
if (is_array($themeInfo) && isset($themeInfo['name'])) {
@@ -107,7 +107,9 @@ final class Theme implements ThemeInterface
public function getInfo(): array
{
try {
$themeInfo = FileUtil::require(FileUtil::buildPath($this->themeContext->getFullPath(), 'index.php'));
$themeInfo = FileSystemUtil::require(
FileSystemUtil::buildPath($this->themeContext->getFullPath(), 'index.php')
);
if (is_array($themeInfo)) {
return $themeInfo;

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -26,7 +26,7 @@ namespace SP\Core\UI;
use Directory;
use SP\Domain\Core\UI\ThemeContextInterface;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
/**
* Class ThemeContext
@@ -45,9 +45,9 @@ final class ThemeContext implements ThemeContextInterface
private readonly string $module,
private readonly string $name
) {
$this->fullPath = FileUtil::buildPath($basePath, $name);
$this->path = FileUtil::buildPath(str_replace(APP_ROOT, '', $basePath), $name);
$this->viewsPath = FileUtil::buildPath($this->fullPath, 'views');
$this->fullPath = FileSystemUtil::buildPath($basePath, $name);
$this->path = FileSystemUtil::buildPath(str_replace(APP_ROOT, '', $basePath), $name);
$this->viewsPath = FileSystemUtil::buildPath($this->fullPath, 'views');
$this->uri = sprintf(
'%s/app/modules/%s/themes/%s',
$baseUri,

View File

@@ -33,7 +33,7 @@ use SP\Domain\Storage\Ports\FileCacheService;
use SP\Html\Assets\FontIcon;
use SP\Html\Assets\IconInterface;
use SP\Infrastructure\File\FileException;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use function SP\logger;
use function SP\processException;
@@ -73,8 +73,8 @@ final class ThemeIcons implements ThemeIconsInterface
// logger('Loaded icons cache', 'INFO');
}
$icons = FileUtil::require(
FileUtil::buildPath($themeContext->getFullPath(), 'inc', 'Icons.php'),
$icons = FileSystemUtil::require(
FileSystemUtil::buildPath($themeContext->getFullPath(), 'inc', 'Icons.php'),
ThemeIconsInterface::class
);

View File

@@ -36,10 +36,10 @@ use SP\Domain\Core\Exceptions\ConstraintException;
use SP\Domain\Core\Exceptions\InvalidImageException;
use SP\Domain\Core\Exceptions\QueryException;
use SP\Domain\Core\Exceptions\SPException;
use SP\Domain\Image\Ports\ImageService;
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Infrastructure\Database\QueryResult;
use SP\Util\FileUtil;
use SP\Util\ImageUtilInterface;
use SP\Util\FileSystemUtil;
use function SP\__u;
@@ -52,7 +52,7 @@ final class AccountFile extends Service implements AccountFileService
public function __construct(
Application $application,
private readonly AccountFileRepository $accountFileRepository,
private readonly ImageUtilInterface $imageUtil
private readonly ImageService $imageUtil
) {
parent::__construct($application);
}
@@ -69,7 +69,7 @@ final class AccountFile extends Service implements AccountFileService
*/
public function create(File $itemData): int
{
if (FileUtil::isImage($itemData)) {
if (FileSystemUtil::isImage($itemData)) {
$itemData->setThumb($this->imageUtil->createThumbnail($itemData->getContent()));
} else {
$itemData->setThumb('no_thumb');

View File

@@ -33,7 +33,7 @@ use SP\Domain\File\Ports\DirectoryHandlerService;
use SP\Domain\File\Ports\FileHandlerInterface;
use SP\Infrastructure\File\ArchiveHandler;
use SP\Infrastructure\File\FileHandler;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
/**
* BackupFileHelper
@@ -73,7 +73,7 @@ final class BackupFileHelper implements BackupFileHelperService
string $hash,
bool $compressed = false
): string {
$file = sprintf('%s_app-%s', FileUtil::buildPath($path, AppInfoInterface::APP_NAME), $hash);
$file = sprintf('%s_app-%s', FileSystemUtil::buildPath($path, AppInfoInterface::APP_NAME), $hash);
if ($compressed) {
return $file . ArchiveHandler::COMPRESS_EXTENSION;
@@ -87,7 +87,7 @@ final class BackupFileHelper implements BackupFileHelperService
string $hash,
bool $compressed = false
): string {
$file = sprintf('%s_db-%s', FileUtil::buildPath($path, AppInfoInterface::APP_NAME), $hash);
$file = sprintf('%s_db-%s', FileSystemUtil::buildPath($path, AppInfoInterface::APP_NAME), $hash);
if ($compressed) {
return $file . ArchiveHandler::COMPRESS_EXTENSION;

View File

@@ -46,7 +46,7 @@ use SP\Domain\Export\Ports\XmlTagExportService;
use SP\Domain\File\Ports\DirectoryHandlerService;
use SP\Infrastructure\File\ArchiveHandler;
use SP\Infrastructure\File\FileException;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use SP\Util\VersionUtil;
use function SP\__u;
@@ -116,7 +116,7 @@ final class XmlExport extends Service implements XmlExportService
private static function deleteExportFiles(string $path): void
{
$path = FileUtil::buildPath($path, AppInfoInterface::APP_NAME);
$path = FileSystemUtil::buildPath($path, AppInfoInterface::APP_NAME);
array_map(
static fn($file) => @unlink($file),

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -22,30 +22,30 @@
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Util;
namespace SP\Domain\Image\Ports;
use SP\Domain\Core\Exceptions\InvalidImageException;
/**
* Class ImageUtil para la manipulación de imágenes
*
* @package SP
* Interface ImageService
*/
interface ImageUtilInterface
interface ImageService
{
/**
* Crear miniatura de una imagen
* Build a thumbnail form an image
*
* @param string $image A raw image
* @return string A base64 encode image string
* @throws InvalidImageException
*/
public function createThumbnail(string $image): string;
/**
* Convertir un texto a imagen
* Convert a test into an image
*
* @param string $text
* @param string $text
*
* @return bool|string
* @return false|string
*/
public function convertText(string $text): bool|string;
}

View File

@@ -31,8 +31,8 @@ use SP\Domain\File\Ports\FileHandlerInterface;
use SP\Domain\Task\Ports\TaskInterface;
use SP\Infrastructure\File\FileException;
use SP\Infrastructure\File\FileHandler;
use SP\Util\FileSystemUtil;
use SP\Util\Serde;
use SP\Util\Util;
use function SP\logger;
use function SP\processException;
@@ -73,7 +73,7 @@ final class Task implements TaskInterface
*/
private function checkFile(): bool
{
$tempDir = Util::getTempDir();
$tempDir = FileSystemUtil::getTempDir();
if ($tempDir !== false) {
$this->fileOut = new FileHandler(

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -25,12 +25,13 @@
namespace SP\Domain\Task\Services;
use Closure;
use JsonException;
use SP\Domain\Common\Services\Service;
use SP\Domain\Common\Services\ServiceException;
use SP\Domain\Task\Ports\TaskServiceInterface;
use SP\Infrastructure\File\FileException;
use SP\Infrastructure\File\FileHandler;
use SP\Util\Util;
use SP\Util\FileSystemUtil;
/**
* Class TaskService
@@ -57,13 +58,13 @@ final class TaskService extends Service implements TaskServiceInterface
/**
* Track task status
*
* @throws \JsonException
* @throws \SP\Domain\Common\Services\ServiceException
* @throws JsonException
* @throws ServiceException
*/
public function trackStatus(string $taskId, Closure $messagePusher): void
{
$this->taskId = $taskId;
$this->taskDirectory = Util::getTempDir();
$this->taskDirectory = FileSystemUtil::getTempDir();
$this->messagePusher = $messagePusher;
if ($this->taskDirectory === false || !$this->getLock()) {
@@ -146,7 +147,7 @@ final class TaskService extends Service implements TaskServiceInterface
/**
* Read a task status and send it back to the browser (messagePusher)
*
* @throws \JsonException
* @throws JsonException
*/
private function readTaskStatus(): void
{

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -33,7 +33,7 @@ use SP\Domain\Core\Exceptions\SPException;
use SP\Domain\Html\Header;
use SP\Domain\Http\Method;
use SP\Domain\Http\RequestInterface;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use SP\Util\Filter;
use SP\Util\Util;
@@ -110,7 +110,7 @@ class Request implements RequestInterface
return '';
}
$realPath = realpath(FileUtil::buildPath($base, $path));
$realPath = realpath(FileSystemUtil::buildPath($base, $path));
if ($realPath === false || !str_starts_with($realPath, $base)) {
return '';

View File

@@ -35,7 +35,7 @@ use SP\Domain\User\Ports\UserGroupService;
use SP\Domain\User\Ports\UserProfileService;
use SP\Providers\EventsTrait;
use SP\Providers\Provider;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use function SP\__u;
use function SP\logger;
@@ -132,7 +132,7 @@ final class AclHandler extends Provider implements EventReceiver
logger(sprintf('Clearing ACL for user ID: %d', $userId));
try {
if (FileUtil::rmdirRecursive(AccountAcl::ACL_PATH . $userId) === false) {
if (FileSystemUtil::rmdirRecursive(AccountAcl::ACL_PATH . $userId) === false) {
logger(sprintf('Unable to delete %s directory', AccountAcl::ACL_PATH . $userId));
return false;

View File

@@ -30,7 +30,7 @@ namespace SP\Util;
final class Checks
{
private const MIN_PHP_VERSION = 80200;
private const MAX_PHP_VERSION = 80300;
private const MAX_PHP_VERSION = 80400;
/**
* Comprobar si sysPass se ejecuta en W$indows.

View File

@@ -36,11 +36,9 @@ use function SP\__;
use function SP\__u;
/**
* Class FileUtil
*
* @package SP\Util
* Class FilesystemUtil
*/
class FileUtil
class FileSystemUtil
{
private const IMAGE_MIME = [
'image/jpeg',
@@ -85,17 +83,6 @@ class FileUtil
return in_array(strtolower($fileData->getType()), self::IMAGE_MIME, true);
}
/**
* Return a well-formed path
*
* @param string ...$parts
* @return string
*/
public static function buildPath(string ...$parts): string
{
return implode(DIRECTORY_SEPARATOR, $parts);
}
/**
* @template T
* @param string $file
@@ -119,4 +106,47 @@ class FileUtil
throw new FileException(sprintf(__('File not found: %s'), $file));
}
}
/**
* Comprueba y devuelve un directorio temporal válido
*
* @return bool|string
*/
public static function getTempDir(): bool|string
{
$sysTmp = sys_get_temp_dir();
$checkDir = static function ($dir) {
$path = FileSystemUtil::buildPath($dir, 'syspass.test');
if (file_exists($path)) {
return $dir;
}
if (is_dir($dir) || mkdir($dir) || is_dir($dir)) {
if (touch($path)) {
return $dir;
}
}
return false;
};
if ($checkDir(TMP_PATH)) {
return TMP_PATH;
}
return $checkDir($sysTmp);
}
/**
* Return a well-formed path
*
* @param string ...$parts
* @return string
*/
public static function buildPath(string ...$parts): string
{
return implode(DIRECTORY_SEPARATOR, $parts);
}
}

View File

@@ -4,7 +4,7 @@
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
@@ -29,8 +29,6 @@ use SP\Domain\Http\RequestInterface;
/**
* Class HttpUtil
*
* @package SP\Util
*/
final class HttpUtil
{

120
lib/SP/Util/Image.php Normal file
View File

@@ -0,0 +1,120 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Util;
use GdImage;
use SP\Domain\Core\Exceptions\InvalidImageException;
use SP\Domain\Core\Exceptions\SPException;
use SP\Domain\Core\PhpExtensionCheckerService;
use SP\Domain\Image\Ports\ImageService;
use SP\Infrastructure\File\FileHandler;
use function SP\__u;
use function SP\processException;
/**
* Class Image
*/
final class Image implements ImageService
{
private const IMAGE_WIDTH = 48;
private const IMAGE_FONT = PUBLIC_PATH . '/vendor/fonts/NotoSans-Regular-webfont.ttf';
private const TMP_PREFFIX = 'syspass';
public function __construct(PhpExtensionCheckerService $checker)
{
$checker->checkCurl(true);
}
/**
* @inheritDoc
* @throws InvalidImageException
* @throws SPException
*/
public function createThumbnail(string $image): string
{
$im = @imagecreatefromstring($image);
if ($im === false) {
throw InvalidImageException::error(__u('Invalid image'));
}
$width = imagesx($im) ?: self::IMAGE_WIDTH;
$height = imagesy($im) ?: self::IMAGE_WIDTH;
$newHeight = floor($height * (self::IMAGE_WIDTH / $width));
if (($tempImage = imagecreatetruecolor(self::IMAGE_WIDTH, $newHeight)) === false
|| !imagecopyresized($tempImage, $im, 0, 0, 0, 0, self::IMAGE_WIDTH, $newHeight, $width, $height)
) {
throw SPException::error(__u('Unable to create image'));
}
return $this->createPngImage($tempImage);
}
/**
* @throws SPException
*/
private function createPngImage(GdImage $gdImage): string
{
if (($tmpFile = tempnam(TMP_PATH, self::TMP_PREFFIX)) !== false
&& imagepng($gdImage, $tmpFile)
) {
$file = new FileHandler($tmpFile);
$out = base64_encode($file->readToString());
$file->delete();
return $out;
}
throw SPException::error(__u('Unable to create image'));
}
/**
* @inheritDoc
*/
public function convertText(string $text): false|string
{
try {
$width = strlen($text) * 10;
if (($im = @imagecreatetruecolor($width, 30)) === false
|| ($bgColor = imagecolorallocate($im, 245, 245, 245)) === false
|| ($fgColor = imagecolorallocate($im, 128, 128, 128)) === false
|| !imagefilledrectangle($im, 0, 0, $width, 30, $bgColor) ||
!imagefttext($im, 10, 0, 10, 20, $fgColor, self::IMAGE_FONT, $text)
) {
throw SPException::error(__u('Unable to create image'));
}
return $this->createPngImage($im);
} catch (SPException $e) {
processException($e);
return false;
}
}
}

View File

@@ -1,140 +0,0 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2023, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SP\Util;
use SP\Core\PhpExtensionChecker;
use SP\Domain\Core\Exceptions\InvalidImageException;
use function SP\__u;
defined('APP_ROOT') || die();
/**
* Class ImageUtil para la manipulación de imágenes
*
* @package SP
*/
final class ImageUtil implements ImageUtilInterface
{
/**
* @param PhpExtensionChecker $checker
*/
public function __construct(PhpExtensionChecker $checker)
{
$checker->checkCurl(true);
}
/**
* Crear miniatura de una imagen
*
* @throws InvalidImageException
*/
public function createThumbnail(string $image): string
{
$im = @imagecreatefromstring($image);
if ($im === false) {
throw new InvalidImageException(__u('Invalid image'));
}
$width = imagesx($im);
$height = imagesy($im);
// Calcular el tamaño de la miniatura
$new_width = 48;
$new_height = floor($height * ($new_width / $width));
// Crear nueva imagen
$imTmp = imagecreatetruecolor($new_width, $new_height);
// Redimensionar la imagen
imagecopyresized(
$imTmp,
$im,
0,
0,
0,
0,
$new_width,
$new_height,
$width,
$height
);
// Devolver la imagen
ob_start();
imagepng($imTmp);
$thumbnail = ob_get_clean();
imagedestroy($imTmp);
imagedestroy($im);
return base64_encode($thumbnail);
}
/**
* Convertir un texto a imagen
*
* @param string $text
*
* @return bool|string
*/
public function convertText(string $text): bool|string
{
$width = strlen($text) * 10;
$im = @imagecreatetruecolor($width, 30);
if ($im === false) {
return false;
}
// Colores de la imagen
$bgColor = imagecolorallocate($im, 245, 245, 245);
// $shadowColor = imagecolorallocate($im, 128, 128, 128);
$fgColor = imagecolorallocate($im, 128, 128, 128);
imagefilledrectangle($im, 0, 0, $width, 30, $bgColor);
// Ruta de la fuente
$font = PUBLIC_PATH.'/vendor/fonts/NotoSans-Regular-webfont.ttf';
// Sombra
// imagettftext($im, 14, 0, 13, 23, $shadowColor, $font, $text);
// Crear el texto
imagettftext($im, 10, 0, 10, 20, $fgColor, $font, $text);
// Devolver la imagen
ob_start();
imagepng($im);
$image = ob_get_clean();
imagedestroy($im);
return base64_encode($image);
}
}

View File

@@ -24,7 +24,6 @@
namespace SP\Util;
use Defuse\Crypto\Core;
use Defuse\Crypto\Encoding;
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;

View File

@@ -36,38 +36,6 @@ use function SP\logger;
*/
final class Util
{
/**
* Comprueba y devuelve un directorio temporal válido
*
* @return bool|string
*/
public static function getTempDir(): bool|string
{
$sysTmp = sys_get_temp_dir();
$checkDir = static function ($dir) {
$file = 'syspass.test';
if (file_exists($dir . DIRECTORY_SEPARATOR . $file)) {
return $dir;
}
if (is_dir($dir) || mkdir($dir) || is_dir($dir)) {
if (touch($dir . DIRECTORY_SEPARATOR . $file)) {
return $dir;
}
}
return false;
};
if ($checkDir(TMP_PATH)) {
return TMP_PATH;
}
return $checkDir($sysTmp);
}
/**
* Realiza el proceso de logout.
*

View File

@@ -34,9 +34,9 @@ use SP\Domain\Common\Services\ServiceException;
use SP\Domain\Core\Exceptions\ConstraintException;
use SP\Domain\Core\Exceptions\InvalidImageException;
use SP\Domain\Core\Exceptions\QueryException;
use SP\Domain\Image\Ports\ImageService;
use SP\Infrastructure\Common\Repositories\NoSuchItemException;
use SP\Infrastructure\Database\QueryResult;
use SP\Util\ImageUtilInterface;
use SPT\Generators\FileDataGenerator;
use SPT\Generators\ItemSearchDataGenerator;
use SPT\UnitaryTestCase;
@@ -50,7 +50,7 @@ class AccountFileTest extends UnitaryTestCase
{
private MockObject|AccountFileRepository $accountFileRepository;
private ImageUtilInterface|MockObject $imageUtil;
private ImageService|MockObject $imageUtil;
private AccountFile $accountFile;
/**
@@ -242,7 +242,7 @@ class AccountFileTest extends UnitaryTestCase
parent::setUp();
$this->accountFileRepository = $this->createMock(AccountFileRepository::class);
$this->imageUtil = $this->createMock(ImageUtilInterface::class);
$this->imageUtil = $this->createMock(ImageService::class);
$this->accountFile =
new AccountFile($this->application, $this->accountFileRepository, $this->imageUtil);

View File

@@ -0,0 +1,93 @@
<?php
/*
* sysPass
*
* @author nuxsmin
* @link https://syspass.org
* @copyright 2012-2024, Rubén Domínguez nuxsmin@$syspass.org
*
* This file is part of sysPass.
*
* sysPass is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* sysPass is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with sysPass. If not, see <http://www.gnu.org/licenses/>.
*/
namespace SPT\Util;
use GdImage;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\MockObject\Exception;
use PHPUnit\Framework\TestCase;
use SP\Domain\Core\Exceptions\InvalidImageException;
use SP\Domain\Core\Exceptions\SPException;
use SP\Util\Image;
use SPT\Stubs\PhpExtensionCheckerStub;
/**
* Class ImageTest
*/
#[Group('unitary')]
class ImageTest extends TestCase
{
private Image $imageUtil;
/**
* @throws InvalidImageException
* @throws SPException
*/
public function testCreateThumbnail()
{
$image = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
. 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
. 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
. '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$out = $this->imageUtil->createThumbnail(base64_decode($image));
$this->assertTrue(imagecreatefromstring(base64_decode($out)) instanceof GdImage);
}
/**
* @throws InvalidImageException
* @throws SPException
*/
public function testCreateThumbnailWithException()
{
$this->expectException(InvalidImageException::class);
$this->expectExceptionMessage('Invalid image');
$this->imageUtil->createThumbnail('');
}
public function testConvertText()
{
$out = $this->imageUtil->convertText('test');
$this->assertTrue(imagecreatefromstring(base64_decode($out)) instanceof GdImage);
}
/**
* @throws Exception
*/
protected function setUp(): void
{
parent::setUp();
$phpExtensionCheckerService = $this->createMock(PhpExtensionCheckerStub::class);
$phpExtensionCheckerService->expects($this->once())
->method('checkCurl')
->with(true);
$this->imageUtil = new Image($phpExtensionCheckerService);
}
}

View File

@@ -36,7 +36,7 @@ use SP\Domain\User\Dtos\UserDataDto;
use SP\Domain\User\Models\ProfileData;
use SP\Infrastructure\Database\DatabaseConnectionData;
use SP\Infrastructure\Database\MysqlHandler;
use SP\Util\FileUtil;
use SP\Util\FileSystemUtil;
use function SP\logger;
use function SP\processException;
@@ -46,34 +46,35 @@ define('IS_TESTING', true);
define('APP_ROOT', dirname(__DIR__, 2));
define('TEST_ROOT', dirname(__DIR__));
const APP_DEFINITIONS_FILE = APP_ROOT.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'Definitions.php';
const APP_DEFINITIONS_FILE = APP_ROOT . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'Definitions.php';
define('RESOURCE_PATH', TEST_ROOT.DIRECTORY_SEPARATOR.'res');
define('CONFIG_PATH', RESOURCE_PATH.DIRECTORY_SEPARATOR.'config');
define('CONFIG_FILE', CONFIG_PATH.DIRECTORY_SEPARATOR.'config.xml');
define('ACTIONS_FILE', CONFIG_PATH.DIRECTORY_SEPARATOR.'actions.xml');
define('LOCALES_PATH', APP_ROOT.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'locales');
define('MODULES_PATH', APP_ROOT.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'modules');
define('SQL_PATH', APP_ROOT.DIRECTORY_SEPARATOR.'schemas');
define('CACHE_PATH', RESOURCE_PATH.DIRECTORY_SEPARATOR.'cache');
define('TMP_PATH', TEST_ROOT.DIRECTORY_SEPARATOR.'tmp');
define('RESOURCE_PATH', TEST_ROOT . DIRECTORY_SEPARATOR . 'res');
define('CONFIG_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'config');
define('CONFIG_FILE', CONFIG_PATH . DIRECTORY_SEPARATOR . 'config.xml');
define('ACTIONS_FILE', CONFIG_PATH . DIRECTORY_SEPARATOR . 'actions.xml');
define('LOCALES_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'locales');
define('MODULES_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'modules');
define('SQL_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'schemas');
define('CACHE_PATH', RESOURCE_PATH . DIRECTORY_SEPARATOR . 'cache');
define('TMP_PATH', TEST_ROOT . DIRECTORY_SEPARATOR . 'tmp');
define('PUBLIC_PATH', APP_ROOT . DIRECTORY_SEPARATOR . 'public');
define('BACKUP_PATH', TMP_PATH);
define('PLUGINS_PATH', TMP_PATH);
define('XML_SCHEMA', APP_ROOT.DIRECTORY_SEPARATOR.'schemas'.DIRECTORY_SEPARATOR.'syspass.xsd');
define('LOG_FILE', TMP_PATH.DIRECTORY_SEPARATOR.'test.log');
define('XML_SCHEMA', APP_ROOT . DIRECTORY_SEPARATOR . 'schemas' . DIRECTORY_SEPARATOR . 'syspass.xsd');
define('LOG_FILE', TMP_PATH . DIRECTORY_SEPARATOR . 'test.log');
define('FIXTURE_FILES', [
RESOURCE_PATH.DIRECTORY_SEPARATOR.'datasets'.DIRECTORY_SEPARATOR.'truncate.sql',
RESOURCE_PATH.DIRECTORY_SEPARATOR.'datasets'.DIRECTORY_SEPARATOR.'syspass.sql',
RESOURCE_PATH . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'truncate.sql',
RESOURCE_PATH . DIRECTORY_SEPARATOR . 'datasets' . DIRECTORY_SEPARATOR . 'syspass.sql',
]);
define('SELF_IP_ADDRESS', getRealIpAddress());
define('SELF_HOSTNAME', gethostbyaddr(SELF_IP_ADDRESS));
require_once APP_ROOT.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'autoload.php';
require_once APP_ROOT.DIRECTORY_SEPARATOR.'lib'.DIRECTORY_SEPARATOR.'BaseFunctions.php';
require_once APP_ROOT . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
require_once APP_ROOT . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'BaseFunctions.php';
logger('APP_ROOT='.APP_ROOT);
logger('TEST_ROOT='.TEST_ROOT);
logger('SELF_IP_ADDRESS='.SELF_IP_ADDRESS);
logger('APP_ROOT=' . APP_ROOT);
logger('TEST_ROOT=' . TEST_ROOT);
logger('SELF_IP_ADDRESS=' . SELF_IP_ADDRESS);
// Setup directories
try {
@@ -86,7 +87,7 @@ try {
if (is_dir(CONFIG_PATH)
&& decoct(fileperms(CONFIG_PATH) & 0777) !== '750'
) {
print 'Setting permissions for '.CONFIG_PATH.PHP_EOL;
print 'Setting permissions for ' . CONFIG_PATH . PHP_EOL;
chmod(CONFIG_PATH, 0750);
}
@@ -157,12 +158,12 @@ function getDbHandler(?DatabaseConnectionData $connectionData = null): MysqlHand
function getResource(string $dir, string $file): string
{
return file_get_contents(RESOURCE_PATH.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.$file) ?: '';
return file_get_contents(RESOURCE_PATH . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $file) ?: '';
}
function saveResource(string $dir, string $file, string $data): bool|int
{
return file_put_contents(RESOURCE_PATH.DIRECTORY_SEPARATOR.$dir.DIRECTORY_SEPARATOR.$file, $data);
return file_put_contents(RESOURCE_PATH . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR . $file, $data);
}
/**
@@ -171,12 +172,12 @@ function saveResource(string $dir, string $file, string $data): bool|int
function recreateDir(string $dir): void
{
if (is_dir($dir)) {
logger('Deleting '.$dir);
logger('Deleting ' . $dir);
FileUtil::rmdirRecursive($dir);
FileSystemUtil::rmdirRecursive($dir);
}
logger('Creating '.$dir);
logger('Creating ' . $dir);
if (!mkdir($dir) && !is_dir($dir)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $dir));