HEX
Server: Apache
System: Linux vmi318001.contaboserver.net 6.8.0-117-generic #117-Ubuntu SMP PREEMPT_DYNAMIC Tue May 5 19:26:24 UTC 2026 x86_64
User: boxelikax (1004)
PHP: 8.2.33
Disabled: NONE
Upload Files
File: /home/boxelikax/public_html/demoltec.com/Matchers.zip
PK!�]UMe!HHPhp.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use League\Flysystem\StorageAttributes;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Php as MatchResult;

class Php implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        try {
            $list = $fs->listContents($path);
            foreach ($list as $item) {
                /** @var StorageAttributes $item */
                if ($item->isFile() && str_ends_with($item->path(), '.php')) {
                    return new MatchResult($path);
                }

                if ($item->isDir() && $item->path() === ltrim(rtrim($path, '/') . '/src', '/')) {
                    return $this->match($fs, rtrim($path, '/') . '/src');
                }
            }
        } catch (FilesystemException) {
            // skip dir if it is inaccessible
        }

        return new EmptyMatchResult();
    }
}
PK!�]G�qF��Prestashop.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Prestashop as MatchResult;

class Prestashop implements MatcherInterface
{
    protected const VERSIONS = [
        [
            'filename' => '/config/settings.inc.php',
            'regexp' => '/define\\(\'_PS_VERSION_\', \'(.+)\'\\)/',
        ],
    ];

    /**
     * @throws FilesystemException
     */
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        foreach (self::VERSIONS as $version) {
            $versionFile = rtrim($path, '/') . '/' . $version['filename'];

            if (!$fs->fileExists($versionFile)) {
                continue;
            }

            return new MatchResult($path, $this->getVersion($version, $fs, $versionFile));
        }

        return new EmptyMatchResult();
    }

    public function getVersion(array $version, Filesystem $fs, string $versionFile): ?string
    {
        $result = null;
        try {
            if (preg_match($version['regexp'], $fs->read($versionFile), $matches) && count($matches) > 1) {
                $result = $matches[1];
            }
        } catch (FilesystemException) {
            // ignore filesystem extensions
        }
        return $result;
    }
}
PK!�]��-**Siteplus.phpnu�[���<?php

declare(strict_types=1);

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\Helper\InspectorHelper;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Siteplus as MatchResult;

class Siteplus implements MatcherInterface
{
    private const PUBLISH_DIR_PATH = '/bundle/publish';

    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $rTrimPath = rtrim($path, '/');

        $inspectorHelper = new InspectorHelper();

        if (!$inspectorHelper->fileContainsString($fs, $rTrimPath . '/index.html', 'edit.site')) {
            return new EmptyMatchResult();
        }

        if (!$fs->directoryExists($rTrimPath . self::PUBLISH_DIR_PATH)) {
            return new EmptyMatchResult();
        }

        $publishDirList = $fs->listContents($rTrimPath . self::PUBLISH_DIR_PATH, false);

        // do not check if the item is a directory as on the server when the files a copied the type of the
        // directory is determined as 'file'.
        // By default, there should be just 1 directory in the publish directory
        $versionDirPath = $publishDirList->toArray()[0]['path'] ?? null;

        if ($versionDirPath === null) {
            return new EmptyMatchResult();
        }

        return $inspectorHelper->fileContainsString($fs, $versionDirPath . '/bundle.js', 'siteplus')
            ? new MatchResult($rTrimPath, $this->getSiteplusVersion($versionDirPath))
            : new EmptyMatchResult();
    }

    private function getSiteplusVersion(string $versionDirPath): string
    {
        // get the last part of the path
        $versionDirPathParts = explode('/', $versionDirPath);
        return end($versionDirPathParts);
    }
}
PK!�]T�����Duda.phpnu�[���<?php

declare(strict_types=1);

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\Helper\InspectorHelper;
use Plesk\Wappspector\MatchResult\Duda as MatchResult;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class Duda implements MatcherInterface
{
    private const CSS_FILES = [
        '/Style/desktop.css',
        '/Style/mobile.css',
        '/Style/tablet.css',
    ];

    private const RUNTIME_JS_FILE = '/Scripts/runtime.js';

    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $rTrimPath = rtrim($path, '/');

        $cssFile = $this->getCssFile($fs, $rTrimPath);

        $inspectorHelper = new InspectorHelper();

        if ($cssFile !== null) {
            $cssFileContent = $fs->read($rTrimPath . $cssFile);
            if (
                $inspectorHelper->fileContentContainsString($cssFileContent, 'dmDudaonePreviewBody') ||
                $inspectorHelper->fileContentContainsString($cssFileContent, 'dudaSnipcartProductGalleryId')
            ) {
                return new MatchResult($path);
            }
        }

        if (!$fs->fileExists($rTrimPath . self::RUNTIME_JS_FILE)) {
            return new EmptyMatchResult();
        }

        return $inspectorHelper->fileContainsString($fs, $rTrimPath . self::RUNTIME_JS_FILE, 'duda')
            ? new MatchResult($path)
            : new EmptyMatchResult();
    }

    private function getCssFile(Filesystem $fs, string $path): ?string
    {
        foreach (self::CSS_FILES as $cssFile) {
            if ($fs->fileExists($path . $cssFile)) {
                return $cssFile;
            }
        }

        return null;
    }
}
PK!�]Kɑ���Yii.phpnu�[���<?php

declare(strict_types=1);


namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Yii as MatchResult;

class Yii implements MatcherInterface
{
    private const VERSIONS = [
        [
            'file' => 'yii',
            'versionFile' => '/vendor/yiisoft/yii2/BaseYii.php',
            'versionRegexp' => '/public static function getVersion\(\)\s*\{\s*return \'([^\']+)\';\s*}/',
        ],
        [
            'file' => 'framework/yiic',
            'versionFile' => '/framework/YiiBase.php',
            'versionRegexp' => '/public static function getVersion\(\)\s*\{\s*return \'([^\']+)\';\s*}/',
        ],
    ];

    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $path = rtrim($path, '/');

        foreach (self::VERSIONS as $version) {
            if (!$fs->fileExists($path . '/' . $version['file'])) {
                continue;
            }
            return new MatchResult($path, $this->detectVersion($fs, $path, $version));
        }

        return new EmptyMatchResult();
    }

    private function detectVersion(Filesystem $fs, string $path, array $versionInfo): ?string
    {
        $version = null;

        $yii2VersionFile = $path . $versionInfo['versionFile'];
        if ($fs->fileExists($yii2VersionFile)) {
            preg_match($versionInfo['versionRegexp'], $fs->read($yii2VersionFile), $matches);

            if (isset($matches[1])) {
                $version = $matches[1];
            }
        }

        return $version;
    }
}
PK!�]S[���Symfony.phpnu�[���<?php

declare(strict_types=1);


namespace Plesk\Wappspector\Matchers;

use JsonException;
use League\Flysystem\Filesystem;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Symfony as MatchResult;

class Symfony implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $symfonyLockFile = rtrim($path, '/') . '/symfony.lock';

        if (!$fs->fileExists($symfonyLockFile)) {
            return new EmptyMatchResult();
        }

        $json = [];
        try {
            $json = json_decode($fs->read($symfonyLockFile), true, 512, JSON_THROW_ON_ERROR);
        } catch (JsonException) {
            // ignore symfony.lock errors
        }

        return new MatchResult($path, $json["symfony/framework-bundle"]["version"] ?? null);
    }
}
PK!�][��CakePHP.phpnu�[���<?php

declare(strict_types=1);


namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\MatchResult\CakePHP as MatchResult;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class CakePHP implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $path = rtrim($path, '/');
        if (!$fs->fileExists($path . '/bin/cake')) {
            return new EmptyMatchResult();
        }

        $version = $this->detectVersion($fs, $path);

        return new MatchResult($path, $version);
    }

    private function detectVersion(Filesystem $fs, string $path): ?string
    {
        $version = null;

        $versionFile = $path . '/vendor/cakephp/cakephp/VERSION.txt';
        if ($fs->fileExists($versionFile)) {
            $versionData = explode("\n", trim($fs->read($versionFile)));
            $version = trim(array_pop($versionData));
        }

        return $version;
    }
}
PK!�]�1��	Typo3.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Typo3 as MatchResult;

class Typo3 implements MatcherInterface
{
    /**
     * Version detection information for TYPO3 CMS 4.x and 6.x
     */
    protected const VERSIONS = [
        [
            'filename' => 'typo3/sysext/core/Classes/Information/Typo3Version.php',
            'regexp' => '/VERSION = \'(.*?)\'/',
        ],
        [
            'filename' => 'typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php',
            'regexp' => '/define\\(\'TYPO3_version\', \'(.*?)\'\\)/',
        ],
        [
            'filename' => 't3lib/config_default.php',
            'regexp' => '/TYPO_VERSION = \'(.*?)\'/',
        ],
    ];

    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        foreach (self::VERSIONS as $version) {
            $versionFile = rtrim($path, '/') . '/' . $version['filename'];

            if (!$fs->fileExists($versionFile)) {
                continue;
            }

            if ($version = $this->detectVersion($version['regexp'], $versionFile, $fs)) {
                return new MatchResult($path, $version);
            }
        }

        return new EmptyMatchResult();
    }

    public function detectVersion(string $regexPattern, string $versionFile, Filesystem $fs): ?string
    {
        try {
            preg_match($regexPattern, $fs->read($versionFile), $matches);
            return count($matches) > 1 ? $matches[1] : null;
        } catch (FilesystemException) {
            // ignore file reading problem
            return null;
        }
    }
}
PK!�]=-���Sitejet.phpnu�[���<?php

declare(strict_types=1);

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\Helper\InspectorHelper;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Sitejet as MatchResult;

class Sitejet implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $indexHtmlPath = rtrim($path, '/') . '/index.html';
        if (!$fs->fileExists($indexHtmlPath)) {
            return new EmptyMatchResult();
        }

        $fileContent = $fs->read($indexHtmlPath);

        $inspectorHelper = new InspectorHelper();

        return $inspectorHelper->fileContentContainsString($fileContent, 'ed-element')
               && $inspectorHelper->fileContentContainsString($fileContent, 'webcard.apiHost=')
            ? new MatchResult($path)
            : new EmptyMatchResult();
    }
}
PK!�]L���--
EmDash.phpnu�[���<?php
declare(strict_types=1);
namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\MatchResult\EmDash as MatchResult;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class EmDash implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $packageJsonPath = rtrim($path, '/') . '/package.json';
        if (!$fs->fileExists($packageJsonPath)) {
            return new EmptyMatchResult();
        }

        $json = json_decode($fs->read($packageJsonPath), true);

        return is_array($json) && (isset($json['emdash']) || isset($json['dependencies']['emdash']))
            ? new MatchResult($path)
            : new EmptyMatchResult();
    }
}
PK!�]���"bb
NodeJs.phpnu�[���<?php

declare(strict_types=1);


namespace Plesk\Wappspector\Matchers;

use JsonException;
use League\Flysystem\Filesystem;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\NodeJs as MatchResult;

class NodeJs implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $packageFile = rtrim($path, '/') . '/package.json';

        if (!$fs->fileExists($packageFile)) {
            return new EmptyMatchResult();
        }

        $json = [];
        try {
            $json = json_decode($fs->read($packageFile), true, 512, JSON_THROW_ON_ERROR);
        } catch (JsonException) {
            // ignore package.json errors
        }

        return new MatchResult($path, null, $json['name'] ?? null);
    }
}
PK!�]�>}��
Python.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\StorageAttributes;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Python as MatchResult;

class Python implements MatcherInterface
{
    use UpLevelMatcherTrait;

    protected function doMatch(Filesystem $fs, string $path): MatchResultInterface
    {
        foreach ($fs->listContents($path) as $item) {
            /** @var StorageAttributes $item */
            if ($item->isFile() && str_ends_with($item->path(), '.py')) {
                return new MatchResult($path);
            }
        }

        return new EmptyMatchResult();
    }
}
PK!�]�њ8��CodeIgniter.phpnu�[���<?php

declare(strict_types=1);


namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\CodeIgniter as MatchResult;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class CodeIgniter implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $path = rtrim($path, '/');
        if (!$fs->fileExists($path . '/spark')) {
            return new EmptyMatchResult();
        }

        return new MatchResult($path, $this->detectVersion($fs, $path));
    }

    /**
     * @throws FilesystemException
     */
    private function detectVersion(Filesystem $fs, string $path): ?string
    {
        $versionFile = $path . '/vendor/codeigniter4/framework/system/CodeIgniter.php';
        if (!$fs->fileExists($versionFile)) {
            return null;
        }
        preg_match("/CI_VERSION\\s*=\\s*'([^']+)'/", $fs->read($versionFile), $matches);

        if ($matches !== []) {
            return $matches[1];
        }

        return null;
    }
}
PK!�]#�u[[Composer.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use JsonException;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\Composer as MatchResult;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class Composer implements MatcherInterface
{
    use UpLevelMatcherTrait;

    private function getPath(string $path): string
    {
        return rtrim($path, '/') . '/composer.json';
    }

    /**
     * @throws FilesystemException
     */
    protected function doMatch(Filesystem $fs, string $path): MatchResultInterface
    {
        $composerJsonFile = $this->getPath($path);
        if (!$fs->fileExists($composerJsonFile)) {
            return new EmptyMatchResult();
        }

        $json = [];
        try {
            $json = json_decode($fs->read($composerJsonFile), true, 512, JSON_THROW_ON_ERROR);
        } catch (JsonException) {
            // ignore composer.json errors
        }

        return new MatchResult($path, $json['version'] ?? 'dev', $json['name'] ?? 'unknown');
    }
}
PK!�]����Sitepro.phpnu�[���<?php

declare(strict_types=1);

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\Helper\InspectorHelper;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Sitepro as MatchResult;

class Sitepro implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $rTrimPath = rtrim($path, '/');
        $siteproFolderPath =  $rTrimPath . '/sitepro';
        if (!$fs->directoryExists($siteproFolderPath)) {
            return new EmptyMatchResult();
        }

        $inspectorHelper = new InspectorHelper();

        return $inspectorHelper->fileContainsString($fs, $rTrimPath . '/web.config', 'sitepro')
               || $inspectorHelper->fileContainsString($fs, $rTrimPath . '/.htaccess', 'sitepro')
            ? new MatchResult($path)
            : new EmptyMatchResult();
    }
}
PK!�]��K��Laravel.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use JsonException;
use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\Laravel as MatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class Laravel implements MatcherInterface
{
    use UpLevelMatcherTrait;

    private const VERSION_FILE = 'vendor/laravel/framework/src/Illuminate/Foundation/Application.php';
    private const COMPOSER_JSON = 'composer.json';
    private const ARTISAN = 'artisan';

    /**
     * @throws FilesystemException
     */
    protected function doMatch(Filesystem $fs, string $path): MatchResultInterface
    {
        $path = rtrim($path, '/');
        if (!$fs->fileExists($path . '/' . self::ARTISAN)) {
            return new EmptyMatchResult();
        }

        return new MatchResult($path, $this->detectVersion($path, $fs));
    }

    private function detectVersion(string $path, Filesystem $fs): ?string
    {
        $result = null;
        $versionFile = $path . '/' . self::VERSION_FILE;
        if ($fs->fileExists($versionFile)) {
            preg_match("/VERSION\\s*=\\s*'([^']+)'/", $fs->read($versionFile), $matches);
            if ($matches !== []) {
                $result = $matches[1];
            }
        } else {
            $composerJsonFile = $path . '/' . self::COMPOSER_JSON;
            if ($fs->fileExists($composerJsonFile)) {
                try {
                    $json = json_decode($fs->read($composerJsonFile), true, 512, JSON_THROW_ON_ERROR);
                    if ($laravelPackage = $json['require']['laravel/framework'] ?? null) {
                        $result = str_replace('^', '', $laravelPackage);
                    }
                } catch (JsonException) {
                    // ignore composer.json errors
                }
            }
        }

        return $result;
    }
}
PK!�]�����UpLevelMatcherTrait.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

trait UpLevelMatcherTrait
{
    abstract protected function doMatch(Filesystem $fs, string $path): MatchResultInterface;

    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $matcher = $this->safeScanDir($fs, $path);
        if ($matcher instanceof EmptyMatchResult) {
            $matcher = $this->safeScanDir($fs, rtrim($path) . '/../');
        }
        return $matcher;
    }

    private function safeScanDir(Filesystem $fs, string $path): MatchResultInterface
    {
        try {
            $result = $this->doMatch($fs, $path);
        } catch (FilesystemException) {
            // skip dir if it is inaccessible
            $result = new EmptyMatchResult();
        }

        return $result;
    }
}
PK!�]����Ruby.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Ruby as MatchResult;

class Ruby implements MatcherInterface
{
    use UpLevelMatcherTrait;

    private const RAKEFILE = 'Rakefile';

    /**
     * @throws FilesystemException
     */
    protected function doMatch(Filesystem $fs, string $path): MatchResultInterface
    {
        if (!$fs->fileExists(rtrim($path, '/') . '/' . self::RAKEFILE)) {
            return new EmptyMatchResult();
        }

        return new MatchResult($path);
    }
}
PK!�]�^�\��
Wordpress.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\Wordpress as MatchResult;

class Wordpress implements MatcherInterface
{
    private const VERSION_FILE = 'wp-includes/version.php';

    /**
     * @throws FilesystemException
     */
    private function detectVersion(Filesystem $fs, string $path): ?string
    {
        $versionFile = rtrim($path, '/') . '/' . self::VERSION_FILE;
        preg_match("/\\\$wp_version\\s*=\\s*'([^']+)'/", $fs->read($versionFile), $matches);

        if ($matches !== []) {
            return $matches[1];
        }

        return null;
    }

    /**
     * @throws FilesystemException
     */
    private function isWordpress(Filesystem $fs, string $path): bool
    {
        $versionFile = rtrim($path, '/') . '/' . self::VERSION_FILE;

        if (!$fs->fileExists($versionFile)) {
            return false;
        }

        $fileContents = $fs->read($versionFile);

        return stripos($fileContents, '$wp_version =') !== false;
    }

    /**
     * @throws FilesystemException
     */
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        if (!$this->isWordpress($fs, $path)) {
            return new EmptyMatchResult();
        }

        return new MatchResult($path, $this->detectVersion($fs, $path));
    }
}
PK!�]2 p��
Drupal.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\Drupal as MatchResult;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class Drupal implements MatcherInterface
{
    /**
     * Drupal has changed the way how the version number is stored multiple times, so we need this comprehensive array
     */
    private const VERSIONS = [
        [
            'file' => 'modules/system/system.info',
            'regex' => "/version\\s*=\\s*\"(\\d\\.[^']+)\"[\\s\\S]*project\\s*=\\s*\"drupal\"/",
        ],
        [
            'file' => 'core/modules/system/system.info.yml',
            'regex' => "/version:\\s*'(\\d+\\.[^']+)'[\\s\\S]*project:\\s*'drupal'/",
        ],
    ];

    /**
     * @throws FilesystemException
     */
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        // Iterate through version patterns
        foreach (self::VERSIONS as $version) {
            $versionFile = rtrim($path, '/') . '/' . $version['file'];

            if (!$fs->fileExists($versionFile)) {
                continue;
            }

            $version = $this->detectVersion($version['regex'], $versionFile, $fs);
            return new MatchResult($path, $version);
        }

        return new EmptyMatchResult();
    }

    private function detectVersion(string $regexPattern, string $versionFile, Filesystem $fs): ?string
    {
        preg_match($regexPattern, $fs->read($versionFile), $matches);

        return count($matches) ? $matches[1] : null;
    }
}
PK!�]?��77
DotNet.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use League\Flysystem\StorageAttributes;
use Plesk\Wappspector\MatchResult\DotNet as MatchResult;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class DotNet implements MatcherInterface
{
    use UpLevelMatcherTrait;

    private const HEX_SIGNATURE = '4d5a';

    /**
     * @throws FilesystemException
     */
    public function doMatch(Filesystem $fs, string $path): MatchResultInterface
    {
        foreach ($fs->listContents($path) as $item) {
            /** @var StorageAttributes $item */
            if (!$item->isFile() || !str_ends_with($item->path(), '.dll')) {
                continue;
            }

            $handle = $fs->readStream($item->path());
            $hex = bin2hex(fread($handle, 4));
            if (str_contains($hex, self::HEX_SIGNATURE)) {
                return new MatchResult($path);
            }
        }

        return new EmptyMatchResult();
    }
}
PK!�]%��''
Joomla.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use League\Flysystem\FilesystemException;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\Joomla as MatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

class Joomla implements MatcherInterface
{
    private const CONFIG_FILE = 'configuration.php';

    /**
     * Joomla has changed the way how the version number is stored multiple times, so we need this comprehensive array
     */
    private const VERSION = [
        "files" => [
            "/includes/version.php",
            "/libraries/joomla/version.php",
            "/libraries/cms/version/version.php",
            "/libraries/src/Version.php",
        ],
        "regex_release" => "/\\\$?RELEASE\s*=\s*'([\d.]+)';/",
        "regex_devlevel" => "/\\\$?DEV_LEVEL\s*=\s*'([^']+)';/",
        "regex_major" => "/\\\$?MAJOR_VERSION\s*=\s*([\d.]+);/",
        "regex_minor" => "/\\\$?MINOR_VERSION\s*=\s*([\d.]+);/",
        "regex_patch" => "/\\\$?PATCH_VERSION\s*=\s*([\d.]+);/",
    ];

    /**
     * @throws FilesystemException
     */
    private function isJoomla(Filesystem $fs, string $path): bool
    {
        $configFile = rtrim($path, '/') . '/' . self::CONFIG_FILE;

        if (!$fs->fileExists($configFile)) {
            return false;
        }

        $configContents = $fs->read($configFile);

        if (
            stripos($configContents, 'JConfig') === false
            && stripos($configContents, 'mosConfig') === false
        ) {
            return false;
        }

        // False positive "Akeeba Backup Installer"
        if (stripos($configContents, 'class ABIConfiguration') !== false) {
            return false;
        }

        // False positive mock file in unit test folder
        if (stripos($configContents, 'Joomla.UnitTest') !== false) {
            return false;
        }

        // False positive mock file in unit test folder
        return stripos($configContents, "Joomla\Framework\Test") === false;
    }

    /**
     * @throws FilesystemException
     */
    private function detectVersion(Filesystem $fs, string $path): ?string
    {
        // Iterate through version files
        foreach (self::VERSION['files'] as $file) {
            $versionFile = rtrim($path, '/') . '/' . $file;

            if (!$fs->fileExists($versionFile)) {
                continue;
            }

            $fileContents = $fs->read($versionFile);

            preg_match(self::VERSION['regex_major'], $fileContents, $major);
            preg_match(self::VERSION['regex_minor'], $fileContents, $minor);
            preg_match(self::VERSION['regex_patch'], $fileContents, $patch);

            if (count($major) && count($minor) && count($patch)) {
                return $major[1] . '.' . $minor[1] . '.' . $patch[1];
            }

            if (count($major) && count($minor)) {
                return $major[1] . '.' . $minor[1] . 'x';
            }

            if ($major !== []) {
                return $major[1] . '.x.x';
            }

            // Legacy handling for all version < 3.8.0
            preg_match(self::VERSION['regex_release'], $fileContents, $release);
            preg_match(self::VERSION['regex_devlevel'], $fileContents, $devlevel);

            if (count($release) && count($devlevel)) {
                return $release[1] . '.' . $devlevel[1];
            }

            if ($release !== []) {
                return $release[1] . '.x';
            }
        }

        return null;
    }

    /**
     * @throws FilesystemException
     */
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        if (!$this->isJoomla($fs, $path)) {
            return new EmptyMatchResult();
        }

        return new MatchResult($path, $this->detectVersion($fs, $path));
    }
}
PK!�]8c�'WWMatcherInterface.phpnu�[���<?php

namespace Plesk\Wappspector\Matchers;

use League\Flysystem\Filesystem;
use Plesk\Wappspector\MatchResult\MatchResultInterface;

interface MatcherInterface
{
    /**
     * Checks filesystem by provided path and returns the list of found objects.
     */
    public function match(Filesystem $fs, string $path): MatchResultInterface;
}
PK!�]^��Z��WebPresenceBuilder.phpnu�[���<?php

declare(strict_types=1);

namespace Plesk\Wappspector\Matchers;

use DOMDocument;
use DOMXPath;
use League\Flysystem\Filesystem;
use Plesk\Wappspector\Helper\InspectorHelper;
use Plesk\Wappspector\MatchResult\EmptyMatchResult;
use Plesk\Wappspector\MatchResult\MatchResultInterface;
use Plesk\Wappspector\MatchResult\WebPresenceBuilder as MatchResult;
use Throwable;

class WebPresenceBuilder implements MatcherInterface
{
    public function match(Filesystem $fs, string $path): MatchResultInterface
    {
        $indexHtmlPath = rtrim($path, '/') . '/index.html';
        if (!$fs->fileExists($indexHtmlPath)) {
            return new EmptyMatchResult();
        }

        $fileContent = $fs->read($indexHtmlPath);

        $inspectorHelper = new InspectorHelper();

        return $inspectorHelper->fileContentMatchesString(
            $fileContent,
            '/<meta name="generator" content="Web Presence Builder.*">/'
        ) || $this->fileContainsDOMStructure($fileContent)
            ? new MatchResult($path)
            : new EmptyMatchResult();
    }

    private function fileContainsDOMStructure(string $fileContent): bool
    {
        $dom = new DOMDocument();
        try {
            libxml_use_internal_errors(true);
            $domIsLoaded = $dom->loadHTML($fileContent);
            libxml_clear_errors();
        } catch (Throwable) {
            return false;
        }

        if ($domIsLoaded === false) {
            return false;
        }

        $xpath = new DOMXPath($dom);

        // Find the <div> with id="page"
        $pageDiv = $xpath->query("//div[@id='page']");

        if ($pageDiv->length === 0) {
            return false;
        }

        $pageNode = $pageDiv->item(0);

        // Check for direct children with the required IDs
        $watermarkDiv = $xpath->query("./div[@id='watermark']", $pageNode);
        $layoutDiv = $xpath->query("./div[@id='layout']", $pageNode);

        return $watermarkDiv->length > 0 && $layoutDiv->length > 0;
    }
}
PK!�]UMe!HHPhp.phpnu�[���PK!�]G�qF��Prestashop.phpnu�[���PK!�]��-**`
Siteplus.phpnu�[���PK!�]T������Duda.phpnu�[���PK!�]Kɑ����Yii.phpnu�[���PK!�]S[����Symfony.phpnu�[���PK!�][��j#CakePHP.phpnu�[���PK!�]�1��	�'Typo3.phpnu�[���PK!�]=-���/Sitejet.phpnu�[���PK!�]L���--
3EmDash.phpnu�[���PK!�]���"bb
w6NodeJs.phpnu�[���PK!�]�>}��
:Python.phpnu�[���PK!�]�њ8��3=CodeIgniter.phpnu�[���PK!�]#�u[[�AComposer.phpnu�[���PK!�]�����FSitepro.phpnu�[���PK!�]��K���JLaravel.phpnu�[���PK!�]�����xRUpLevelMatcherTrait.phpnu�[���PK!�]�����VRuby.phpnu�[���PK!�]�^�\��
�YWordpress.phpnu�[���PK!�]2 p��
�_Drupal.phpnu�[���PK!�]?��77
vfDotNet.phpnu�[���PK!�]%��''
�jJoomla.phpnu�[���PK!�]8c�'WWHzMatcherInterface.phpnu�[���PK!�]^��Z���{WebPresenceBuilder.phpnu�[���PK	�