mirror of
https://github.com/e107inc/e107.git
synced 2025-03-17 19:09:45 +01:00
Rewrite e_file_inspector implementation: Use SQLite phar
This commit is contained in:
parent
84081c3d3d
commit
0e7ad8a1b0
Binary file not shown.
@ -9,6 +9,11 @@
|
||||
|
||||
require_once("e_file_inspector_interface.php");
|
||||
|
||||
/**
|
||||
* File Inspector
|
||||
*
|
||||
* Tool to validate application files for consistency by comparing hashes of files with those in a database
|
||||
*/
|
||||
abstract class e_file_inspector implements e_file_inspector_interface
|
||||
{
|
||||
/**
|
||||
@ -16,12 +21,13 @@ abstract class e_file_inspector implements e_file_inspector_interface
|
||||
*
|
||||
* @param $path string Relative path of the file to look up
|
||||
* @param $version string The desired software release to match.
|
||||
* Leave blank for the latest version.
|
||||
* Leave blank for the current version.
|
||||
* Do not prepend the version number with "v".
|
||||
* @return int Validation code (see the constants of this class)
|
||||
*/
|
||||
public function validate($path, $version = null)
|
||||
{
|
||||
if ($version === null) $version = $this->getCurrentVersion();
|
||||
$absolutePath = realpath($path);
|
||||
$actualChecksum = $this->checksumPath($absolutePath);
|
||||
$dbChecksum = $this->getChecksum($path, $version);
|
||||
@ -47,12 +53,13 @@ abstract class e_file_inspector implements e_file_inspector_interface
|
||||
*
|
||||
* @param $path string Relative path of the file to look up
|
||||
* @param $version string The software release version corresponding to the file hash.
|
||||
* Leave blank for the latest version.
|
||||
* Leave blank for the current version.
|
||||
* Do not prepend the version number with "v".
|
||||
* @return string|bool The database hash for the path and version specified. FALSE if the record does not exist.
|
||||
*/
|
||||
public function getChecksum($path, $version = null)
|
||||
{
|
||||
if ($version === null) $version = $this->getCurrentVersion();
|
||||
$checksums = $this->getChecksums($path);
|
||||
return isset($checksums[$version]) ? $checksums[$version] : false;
|
||||
}
|
||||
@ -81,7 +88,26 @@ abstract class e_file_inspector implements e_file_inspector_interface
|
||||
return md5(str_replace(array(chr(13),chr(10)), "", $content));
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getVersions($path)
|
||||
{
|
||||
return array_keys($this->getChecksums($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getCurrentVersion()
|
||||
{
|
||||
$checksums = $this->getChecksums("index.php");
|
||||
$versions = array_keys($checksums);
|
||||
usort($versions, 'version_compare');
|
||||
return array_pop($versions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matching version of the provided path
|
||||
*
|
||||
* Useful for looking up the versions of old files that no longer exist in the latest image
|
||||
@ -98,4 +124,13 @@ abstract class e_file_inspector implements e_file_inspector_interface
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isInsecure($path)
|
||||
{
|
||||
# TODO
|
||||
return false;
|
||||
}
|
||||
}
|
@ -38,6 +38,13 @@ interface e_file_inspector_interface
|
||||
*/
|
||||
const VALIDATION_IGNORE = 7;
|
||||
|
||||
/**
|
||||
* Return an Iterator that can enumerate every path in the image database
|
||||
*
|
||||
* @return Iterator
|
||||
*/
|
||||
public function getPathIterator();
|
||||
|
||||
/**
|
||||
* Get all the known file integrity hashes for the provided path
|
||||
*
|
||||
@ -55,6 +62,16 @@ interface e_file_inspector_interface
|
||||
*/
|
||||
public function getVersions($path);
|
||||
|
||||
/**
|
||||
* Get the version of the software that goes with this image database.
|
||||
*
|
||||
* This database SHOULD contain file integrity hashes for this software version.
|
||||
* This database MAY contain file integrity hashes for older versions of this software.
|
||||
*
|
||||
* @return string PHP-standardized version
|
||||
*/
|
||||
public function getCurrentVersion();
|
||||
|
||||
/**
|
||||
* Check if the file is insecure
|
||||
*
|
||||
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* e107 website system
|
||||
*
|
||||
* Copyright (C) 2008-2020 e107 Inc (e107.org)
|
||||
* Released under the terms and conditions of the
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
|
||||
*/
|
||||
|
||||
require_once("e_file_inspector.php");
|
||||
|
||||
class e_file_inspector_json extends e_file_inspector
|
||||
{
|
||||
private $coreImage;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
global $core_image;
|
||||
require(e_ADMIN . "core_image.php");
|
||||
$this->coreImage = json_decode($core_image, true);
|
||||
unset($core_image);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getChecksums($path)
|
||||
{
|
||||
$path = $this->pathToDefaultPath($path);
|
||||
return self::array_get($this->coreImage, $path, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getVersions($path)
|
||||
{
|
||||
$path = $this->pathToDefaultPath($path);
|
||||
return array_keys(self::array_get($this->coreImage, $path, []));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isInsecure($path)
|
||||
{
|
||||
# TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from an array using "slash" notation.
|
||||
*
|
||||
* Based on Illuminate\Support\Arr::get()
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
* @copyright Copyright (c) Taylor Otwell
|
||||
* @license https://github.com/illuminate/support/blob/master/LICENSE.md MIT License
|
||||
*/
|
||||
private static function array_get($array, $key, $default = null)
|
||||
{
|
||||
if (is_null($key)) return $array;
|
||||
|
||||
if (isset($array[$key])) return $array[$key];
|
||||
|
||||
foreach (explode('/', $key) as $segment) {
|
||||
if (!is_array($array) || !array_key_exists($segment, $array)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$array = $array[$segment];
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
private function pathToDefaultPath($path)
|
||||
{
|
||||
$defaultDirs = e107::getInstance()->defaultDirs();
|
||||
foreach ($defaultDirs as $dirType => $defaultDir) {
|
||||
$customDir = e107::getFolder(preg_replace("/_DIRECTORY$/i", "", $dirType));
|
||||
$path = preg_replace("/^" . preg_quote($customDir, "/") . "/", $defaultDir, $path);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
}
|
101
e107_handlers/e_file_inspector_sqlphar.php
Normal file
101
e107_handlers/e_file_inspector_sqlphar.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* e107 website system
|
||||
*
|
||||
* Copyright (C) 2008-2020 e107 Inc (e107.org)
|
||||
* Released under the terms and conditions of the
|
||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
|
||||
*/
|
||||
|
||||
require_once("e_file_inspector.php");
|
||||
|
||||
class e_file_inspector_sqlphar extends e_file_inspector
|
||||
{
|
||||
private $coreImage;
|
||||
private $currentVersion;
|
||||
|
||||
/**
|
||||
* e_file_inspector_sqlphar constructor.
|
||||
* @param $pharFilePath string Absolute path to the file inspector database
|
||||
*/
|
||||
public function __construct($pharFilePath = null)
|
||||
{
|
||||
if ($pharFilePath === null) $pharFilePath = e_ADMIN . "core_image.php";
|
||||
Phar::loadPhar($pharFilePath, "core_image.phar");
|
||||
$tmpFile = tmpfile();
|
||||
$tmpFilePath = stream_get_meta_data($tmpFile)['uri'];
|
||||
$this->copyUrlToResource("phar://core_image.phar/core_image.sqlite", $tmpFile);
|
||||
$this->coreImage = new PDO("sqlite:{$tmpFilePath}");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getPathIterator()
|
||||
{
|
||||
$statement = $this->coreImage->query(
|
||||
"SELECT path FROM file_hashes ORDER BY path ASC;"
|
||||
);
|
||||
return new IteratorIterator($statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getChecksums($path)
|
||||
{
|
||||
$path = $this->pathToDefaultPath($path);
|
||||
$statement = $this->coreImage->prepare("
|
||||
SELECT versions.version_string, file_hashes.hash
|
||||
FROM file_hashes
|
||||
LEFT JOIN versions ON versions.version_id = file_hashes.release_version
|
||||
WHERE file_hashes.path = :path
|
||||
ORDER BY path ASC;
|
||||
");
|
||||
$statement->execute([
|
||||
':path' => $path
|
||||
]);
|
||||
return $statement->fetchAll(PDO::FETCH_KEY_PAIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getCurrentVersion()
|
||||
{
|
||||
if ($this->currentVersion) return $this->currentVersion;
|
||||
|
||||
$statement = $this->coreImage->query("
|
||||
SELECT version_string FROM versions ORDER BY version_string DESC LIMIT 1
|
||||
");
|
||||
return $this->currentVersion = $statement->fetchColumn();
|
||||
}
|
||||
|
||||
private function pathToDefaultPath($path)
|
||||
{
|
||||
$defaultDirs = e107::getInstance()->defaultDirs();
|
||||
foreach ($defaultDirs as $dirType => $defaultDir)
|
||||
{
|
||||
$customDir = e107::getFolder(preg_replace("/_DIRECTORY$/i", "", $dirType));
|
||||
$path = preg_replace("/^" . preg_quote($customDir, "/") . "/", $defaultDir, $path);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy file to destination with low memory footprint
|
||||
* @param $source string URL of the source
|
||||
* @param $destination resource File pointer of the destination
|
||||
*/
|
||||
private function copyUrlToResource($source, $destination)
|
||||
{
|
||||
$dbFile = fopen($source, "r");
|
||||
while (!feof($dbFile))
|
||||
{
|
||||
$buffer = fread($dbFile, 4096);
|
||||
fwrite($destination, $buffer);
|
||||
}
|
||||
unset($buffer);
|
||||
fclose($dbFile);
|
||||
}
|
||||
}
|
@ -10,14 +10,14 @@
|
||||
class e_file_inspectorTest extends \Codeception\Test\Unit
|
||||
{
|
||||
/**
|
||||
* @var e_file_inspector_json
|
||||
* @var e_file_inspector_sqlphar
|
||||
*/
|
||||
private $e_integrity;
|
||||
|
||||
public function _before()
|
||||
{
|
||||
require_once(e_HANDLER."e_file_inspector_json.php");
|
||||
$this->e_integrity = new e_file_inspector_json();
|
||||
require_once(e_HANDLER."e_file_inspector_sqlphar.php");
|
||||
$this->e_integrity = new e_file_inspector_sqlphar();
|
||||
}
|
||||
|
||||
public function testGetChecksums()
|
||||
@ -30,4 +30,12 @@ class e_file_inspectorTest extends \Codeception\Test\Unit
|
||||
$this->assertIsArray($checksums);
|
||||
$this->assertEmpty($checksums);
|
||||
}
|
||||
|
||||
public function testGetCurrentVersion()
|
||||
{
|
||||
$actualVersion = $this->e_integrity->getCurrentVersion();
|
||||
|
||||
$this->assertIsString($actualVersion);
|
||||
$this->assertNotEmpty($actualVersion);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user