�ɲɾ�����ӯ�����һ��ˣ��������С���˴��ͣ�������P���ҹ��ñ˽��ά�Բ��������˸߸ԣ�������ơ��ҹ��ñ�����ά�Բ���ˡ���˳^�ӣ������ӡ� ���ͯj�ӣ��ƺ���ӣ� ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!PKa_2]"bb NodeJs.phpnu[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); } } PKa_2]L-- EmDash.phpnu[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(); } } PKa_2]TDuda.phpnu[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; } } PKa_2]K Laravel.phpnu[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; } } PKa_2]%'' Joomla.phpnu[ [ "/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)); } } PKa_2]KɑYii.phpnu[ '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; } } PKa_2]S[ Symfony.phpnu[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); } } PKa_2] Sitepro.phpnu[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(); } } PKa_2]1 Typo3.phpnu[ '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; } } } PKa_2]>} Python.phpnu[listContents($path) as $item) { /** @var StorageAttributes $item */ if ($item->isFile() && str_ends_with($item->path(), '.py')) { return new MatchResult($path); } } return new EmptyMatchResult(); } } PKa_2]^\ Wordpress.phpnu[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)); } } PKa_2]GqFPrestashop.phpnu[ '/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; } } PKa_2]UpLevelMatcherTrait.phpnu[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; } } PKa_2]?77 DotNet.phpnu[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(); } } PKa_2]Ruby.phpnu[fileExists(rtrim($path, '/') . '/' . self::RAKEFILE)) { return new EmptyMatchResult(); } return new MatchResult($path); } } PKa_2][ CakePHP.phpnu[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; } } PKa_2]њ8CodeIgniter.phpnu[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; } } PKa_2]2 p Drupal.phpnu[ '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; } } PKa_2]8c'WWMatcherInterface.phpnu[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'); } } PKa_2]UMe!HHPhp.phpnu[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(); } } PKa_2]-** Siteplus.phpnu[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); } } PKa_2]^ZWebPresenceBuilder.phpnu[fileExists($indexHtmlPath)) { return new EmptyMatchResult(); } $fileContent = $fs->read($indexHtmlPath); $inspectorHelper = new InspectorHelper(); return $inspectorHelper->fileContentMatchesString( $fileContent, '//' ) || $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
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; } } PKa_2]=- Sitejet.phpnu[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(); } } PKa_2]"bb NodeJs.phpnu[PKa_2]L-- EmDash.phpnu[PKa_2]TDuda.phpnu[PKa_2]K Laravel.phpnu[PKa_2]%'' Joomla.phpnu[PKa_2]KɑR%Yii.phpnu[PKa_2]S[ ,Symfony.phpnu[PKa_2] /Sitepro.phpnu[PKa_2]1 3Typo3.phpnu[PKa_2]>} 7;Python.phpnu[PKa_2]^\ W>Wordpress.phpnu[PKa_2]GqF|DPrestashop.phpnu[PKa_2]]JUpLevelMatcherTrait.phpnu[PKa_2]?77 zNDotNet.phpnu[PKa_2]RRuby.phpnu[PKa_2][ UCakePHP.phpnu[PKa_2]њ8