mirror of
https://github.com/e107inc/e107.git
synced 2025-08-23 22:53:01 +02:00
Merge pull request #4114 from e107inc/build-release
Automated Release Builds
This commit is contained in:
@@ -193,6 +193,7 @@ class e107
|
||||
'e_bb_base' => '{e_HANDLER}bbcode_handler.php',
|
||||
'e_customfields' => '{e_HANDLER}e_customfields_class.php',
|
||||
'e_file' => '{e_HANDLER}file_class.php',
|
||||
'e_file_inspector_json_phar' => '{e_HANDLER}e_file_inspector_json_phar.php',
|
||||
'e_form' => '{e_HANDLER}form_handler.php',
|
||||
'e_jshelper' => '{e_HANDLER}js_helper.php',
|
||||
'e_media' => '{e_HANDLER}media_class.php',
|
||||
@@ -1601,6 +1602,18 @@ class e107
|
||||
return self::getObject('e_file', null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new file inspector object
|
||||
*
|
||||
* Note: Only the core file inspector is supported right now.
|
||||
*
|
||||
* @return e_file_inspector
|
||||
*/
|
||||
public static function getFileInspector($type = 'core')
|
||||
{
|
||||
return self::getObject('e_file_inspector_json_phar', e_ADMIN . "core_image.php");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve form handler singleton or new fresh object
|
||||
*
|
||||
|
301
e107_handlers/e_file_inspector.php
Normal file
301
e107_handlers/e_file_inspector.php
Normal file
@@ -0,0 +1,301 @@
|
||||
<?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_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
|
||||
{
|
||||
protected $database;
|
||||
protected $currentVersion;
|
||||
private $validatedBitmask;
|
||||
|
||||
protected $defaultDirsCache;
|
||||
protected $customDirsCache;
|
||||
private $undeterminable = array();
|
||||
|
||||
// FIXME: Better place for the insecure file list
|
||||
public $insecureFiles = [
|
||||
e_ADMIN . "ad_links.php",
|
||||
e_PLUGIN . "tinymce4/e_meta.php",
|
||||
e_THEME . "bootstrap3/css/bootstrap_dark.css",
|
||||
e_PLUGIN . "search_menu/languages/English.php",
|
||||
e_LANGUAGEDIR . e_LANGUAGE . "/lan_parser_functions.php",
|
||||
e_LANGUAGEDIR . e_LANGUAGE . "/admin/help/theme.php",
|
||||
e_HANDLER . "np_class.php",
|
||||
e_CORE . "shortcodes/single/user_extended.sc",
|
||||
e_ADMIN . "download.php",
|
||||
e_PLUGIN . "banner/config.php",
|
||||
e_PLUGIN . "forum/newforumposts_menu_config.php",
|
||||
e_PLUGIN . "forum/e_latest.php",
|
||||
e_PLUGIN . "forum/e_status.php",
|
||||
e_PLUGIN . "forum/forum_post_shortcodes.php",
|
||||
e_PLUGIN . "forum/forum_shortcodes.php",
|
||||
e_PLUGIN . "forum/forum_update_check.php",
|
||||
e_PLUGIN . "online_extended_menu/online_extended_menu.php",
|
||||
e_PLUGIN . "online_extended_menu/images/user.png",
|
||||
e_PLUGIN . "online_extended_menu/languages/English.php",
|
||||
e_PLUGIN . "pm/sendpm.sc",
|
||||
e_PLUGIN . "pm/shortcodes/",
|
||||
e_PLUGIN . "social/e_header.php",
|
||||
];
|
||||
|
||||
private $existingInsecureFiles = array();
|
||||
private $existingInsecureDirectories = array();
|
||||
|
||||
/**
|
||||
* e_file_inspector constructor
|
||||
* @param string $database The database from which integrity data may be read or to which integrity data may be
|
||||
* written. This should be an URL or absolute file path for most implementations.
|
||||
*/
|
||||
public function __construct($database)
|
||||
{
|
||||
$this->database = $database;
|
||||
$this->loadDatabase();
|
||||
|
||||
$appRoot = e107::getInstance()->file_path;
|
||||
$this->undeterminable = array_map(function ($path)
|
||||
{
|
||||
return realpath($path) ? realpath($path) : $path;
|
||||
}, [
|
||||
$appRoot . "e107_config.php",
|
||||
$appRoot . e107::getFolder('admin') . "core_image.php",
|
||||
]
|
||||
);
|
||||
$this->existingInsecureFiles = array_filter($this->insecureFiles, function ($path)
|
||||
{
|
||||
return is_file($path);
|
||||
});
|
||||
$this->existingInsecureFiles = array_map('realpath', $this->existingInsecureFiles);
|
||||
$this->existingInsecureDirectories = array_filter($this->insecureFiles, function ($path)
|
||||
{
|
||||
return is_dir($path);
|
||||
});
|
||||
$this->existingInsecureDirectories = array_map('realpath', $this->existingInsecureDirectories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the provided database for reading or writing
|
||||
*
|
||||
* Should tolerate a non-existent database and try to create it if a write operation is executed.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function loadDatabase();
|
||||
|
||||
/**
|
||||
* Check the integrity of the provided path
|
||||
*
|
||||
* @param $path string Relative path of the file to look up
|
||||
* @param $version string The desired software release to match.
|
||||
* 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();
|
||||
|
||||
$bits = 0x0;
|
||||
$absolutePath = $this->relativePathToAbsolutePath($path);
|
||||
$dbChecksums = $this->getChecksums($path);
|
||||
$dbChecksum = $this->getChecksum($path, $version);
|
||||
$actualChecksum = !empty($dbChecksums) ? $this->checksumPath($absolutePath) : null;
|
||||
|
||||
if (!empty($dbChecksums)) $bits |= self::VALIDATED_PATH_KNOWN;
|
||||
if ($dbChecksum !== false) $bits |= self::VALIDATED_PATH_VERSION;
|
||||
if (file_exists($absolutePath)) $bits |= self::VALIDATED_FILE_EXISTS;
|
||||
if (!$this->isInsecure($path)) $bits |= self::VALIDATED_FILE_SECURITY;
|
||||
if ($this->isDeterminable($absolutePath)) $bits |= self::VALIDATED_HASH_CALCULABLE;
|
||||
if ($actualChecksum === $dbChecksum) $bits |= self::VALIDATED_HASH_CURRENT;
|
||||
|
||||
foreach ($dbChecksums as $dbChecksum)
|
||||
{
|
||||
if ($dbChecksum === $actualChecksum) $bits |= self::VALIDATED_HASH_EXISTS;
|
||||
}
|
||||
|
||||
if ($bits + self::VALIDATED === $this->getValidatedBitmask()) $bits |= self::VALIDATED;
|
||||
|
||||
return $bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file integrity hash for the provided path and version
|
||||
*
|
||||
* @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 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the hash of a path to compare with the hash database
|
||||
*
|
||||
* @param $absolutePath string Absolute path of the file to hash
|
||||
* @return string|bool The actual hash for the path. FALSE if the hash was incalculable.
|
||||
*/
|
||||
public function checksumPath($absolutePath)
|
||||
{
|
||||
if (!$this->isDeterminable($absolutePath)) return false;
|
||||
|
||||
return $this->checksum(file_get_contents($absolutePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the hash of a string, which would be used to compare with the hash database
|
||||
*
|
||||
* @param $content string Full content to hash
|
||||
* @return string
|
||||
*/
|
||||
public function checksum($content)
|
||||
{
|
||||
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()
|
||||
{
|
||||
if ($this->currentVersion) return $this->currentVersion;
|
||||
|
||||
$checksums = $this->getChecksums("index.php");
|
||||
$versions = array_keys($checksums);
|
||||
usort($versions, 'version_compare');
|
||||
return $this->currentVersion = 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
|
||||
*
|
||||
* @param $path string Relative path of the file to look up
|
||||
* @return string|bool PHP-standardized version of the file. FALSE if there is no match.
|
||||
*/
|
||||
public function getVersion($path)
|
||||
{
|
||||
$actualChecksum = $this->checksumPath($path);
|
||||
foreach ($this->getChecksums($path) as $dbVersion => $dbChecksum)
|
||||
{
|
||||
if ($actualChecksum === $dbChecksum) return $dbVersion;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function isInsecure($path)
|
||||
{
|
||||
$absolutePath = $this->relativePathToAbsolutePath($path);
|
||||
if (in_array($absolutePath, $this->existingInsecureFiles)) return true;
|
||||
foreach ($this->existingInsecureDirectories as $existingInsecureDirectory)
|
||||
{
|
||||
$existingInsecureDirectory .= '/';
|
||||
if (substr($absolutePath, 0, strlen($existingInsecureDirectory)) === $existingInsecureDirectory) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a custom site path to a default path
|
||||
* @param string $path Custom path
|
||||
* @return string
|
||||
*/
|
||||
public function customPathToDefaultPath($path)
|
||||
{
|
||||
if (!is_array($this->customDirsCache)) $this->populateDirsCache();
|
||||
foreach ($this->customDirsCache as $dirType => $customDir)
|
||||
{
|
||||
if (!isset($this->defaultDirsCache[$dirType])) continue;
|
||||
|
||||
$defaultDir = $this->defaultDirsCache[$dirType];
|
||||
if ($customDir === $defaultDir) continue;
|
||||
|
||||
if (substr($path, 0, strlen($customDir)) === $customDir)
|
||||
$path = $defaultDir . substr($path, strlen($customDir));
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function defaultPathToCustomPath($path)
|
||||
{
|
||||
if (!is_array($this->customDirsCache)) $this->populateDirsCache();
|
||||
foreach ($this->customDirsCache as $dirType => $customDir)
|
||||
{
|
||||
if (!isset($this->defaultDirsCache[$dirType])) continue;
|
||||
|
||||
$defaultDir = $this->defaultDirsCache[$dirType];
|
||||
if ($customDir === $defaultDir) continue;
|
||||
|
||||
if (substr($path, 0, strlen($defaultDir)) === $defaultDir)
|
||||
$path = $customDir . substr($path, strlen($defaultDir));
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
private function getValidatedBitmask()
|
||||
{
|
||||
if ($this->validatedBitmask !== null) return $this->validatedBitmask;
|
||||
$constants = (new ReflectionClass(self::class))->getConstants();
|
||||
$validated_constants = array_filter($constants, function ($key)
|
||||
{
|
||||
$str = 'VALIDATED_';
|
||||
return substr($key, 0, strlen($str)) === $str;
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
$this->validatedBitmask = (max($validated_constants) << 0x1) - 0x1;
|
||||
return $this->validatedBitmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $absolutePath
|
||||
* @return bool
|
||||
*/
|
||||
private function isDeterminable($absolutePath)
|
||||
{
|
||||
return is_file($absolutePath) && is_readable($absolutePath) && !in_array($absolutePath, $this->undeterminable);
|
||||
}
|
||||
|
||||
protected function populateDirsCache()
|
||||
{
|
||||
$this->defaultDirsCache = e107::getInstance()->defaultDirs();
|
||||
$customDirs = e107::getInstance()->e107_dirs ? e107::getInstance()->e107_dirs : [];
|
||||
$this->customDirsCache = array_diff_assoc($customDirs, $this->defaultDirsCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return false|string
|
||||
*/
|
||||
private function relativePathToAbsolutePath($path)
|
||||
{
|
||||
return realpath(e_BASE . $path);
|
||||
}
|
||||
}
|
95
e107_handlers/e_file_inspector_interface.php
Normal file
95
e107_handlers/e_file_inspector_interface.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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)
|
||||
*/
|
||||
|
||||
interface e_file_inspector_interface
|
||||
{
|
||||
/**
|
||||
* TRUE: All validations pass for the provided file.
|
||||
* FALSE: One or more validations failed for the provided file.
|
||||
*/
|
||||
const VALIDATED = 1 << 0;
|
||||
/**
|
||||
* TRUE: The file path is known in this database, regardless of version.
|
||||
* FALSE: The file path is not in this database.
|
||||
*/
|
||||
const VALIDATED_PATH_KNOWN = 1 << 1;
|
||||
/**
|
||||
* TRUE: The file path and specified version have a hash in this database.
|
||||
* FALSE: There is no hash for the file path and specified version.
|
||||
*/
|
||||
const VALIDATED_PATH_VERSION = 1 << 2;
|
||||
/**
|
||||
* TRUE: The file exists.
|
||||
* FALSE: The file doesn't exist.
|
||||
*/
|
||||
const VALIDATED_FILE_EXISTS = 1 << 3;
|
||||
/**
|
||||
* TRUE: The file's hash matches any known version.
|
||||
* FALSE: The file's hash does not match any known versions.
|
||||
*/
|
||||
const VALIDATED_HASH_EXISTS = 1 << 4;
|
||||
/**
|
||||
* TRUE: The file's hash matches the specified version.
|
||||
* FALSE: The file's hash matches a newer or older version than the one specified.
|
||||
*/
|
||||
const VALIDATED_HASH_CURRENT = 1 << 5;
|
||||
/**
|
||||
* TRUE: The file hash is calculable.
|
||||
* FALSE: The file hash is not calculable (e.g. the core image itself, a user config file, a nonexistent file).
|
||||
*/
|
||||
const VALIDATED_HASH_CALCULABLE = 1 << 6;
|
||||
/**
|
||||
* TRUE: The file is not known to be insecure.
|
||||
* FALSE: The file should be deleted due to security concerns.
|
||||
*/
|
||||
const VALIDATED_FILE_SECURITY = 1 << 7;
|
||||
|
||||
/**
|
||||
* Return an Iterator that can enumerate every path in the image database
|
||||
*
|
||||
* @param $version string|null Provide a PHP-standardized version to limit the paths to that version
|
||||
* @return Iterator
|
||||
*/
|
||||
public function getPathIterator($version = null);
|
||||
|
||||
/**
|
||||
* Get all the known file integrity hashes for the provided path
|
||||
*
|
||||
* @param $path string Relative path of the file to look up
|
||||
* @return array Associative array where the keys are the PHP-standardized versions and the values are the checksums
|
||||
* for those versions.
|
||||
*/
|
||||
public function getChecksums($path);
|
||||
|
||||
/**
|
||||
* List of versions of the provided path for which the database has hashes
|
||||
*
|
||||
* @param $path string Relative path of the file to look up
|
||||
* @return array PHP-standardized versions. Empty if there are none.
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @param $path string Relative path of the file to look up
|
||||
* @return bool TRUE if the file should be deleted due to known security flaws; FALSE otherwise
|
||||
*/
|
||||
public function isInsecure($path);
|
||||
}
|
99
e107_handlers/e_file_inspector_json.php
Normal file
99
e107_handlers/e_file_inspector_json.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?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
|
||||
{
|
||||
protected $coreImage;
|
||||
|
||||
/**
|
||||
* @param $jsonFilePath string Absolute path to the file inspector database
|
||||
*/
|
||||
public function __construct($jsonFilePath = null)
|
||||
{
|
||||
parent::__construct($jsonFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function loadDatabase()
|
||||
{
|
||||
global $core_image;
|
||||
@include($this->database);
|
||||
$this->coreImage = json_decode($core_image, true);
|
||||
if (!is_array($this->coreImage)) $this->coreImage = [];
|
||||
$this->coreImage = self::array_slash($this->coreImage);
|
||||
if (!$this->coreImage) $this->coreImage = [];
|
||||
unset($core_image);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getPathIterator($version = null)
|
||||
{
|
||||
$result = $this->coreImage;
|
||||
if (!empty($version))
|
||||
{
|
||||
$result = array_filter($result, function ($value) use ($version)
|
||||
{
|
||||
return array_key_exists($version, $value);
|
||||
});
|
||||
}
|
||||
return new ArrayIterator(array_keys($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getChecksums($path)
|
||||
{
|
||||
$path = $this->customPathToDefaultPath($path);
|
||||
return isset($this->coreImage[$path]) ? $this->coreImage[$path] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten a multi-dimensional associative array with slashes.
|
||||
* Excludes the second-to-last level of depth from flattening.
|
||||
* Also removes the leading "v" from all version keys.
|
||||
*
|
||||
* Based on Illuminate\Support\Arr::dot()
|
||||
*
|
||||
* @param array $array
|
||||
* @param string $prepend
|
||||
* @return array
|
||||
* @copyright Copyright (c) Taylor Otwell
|
||||
* @license https://github.com/illuminate/support/blob/master/LICENSE.md MIT License
|
||||
*/
|
||||
protected static function array_slash($array, $prepend = '')
|
||||
{
|
||||
$results = array();
|
||||
|
||||
foreach ($array as $key => $value)
|
||||
{
|
||||
if (is_array($value) && is_array(reset($value)))
|
||||
{
|
||||
$results = array_merge($results, self::array_slash($value, $prepend . $key . '/'));
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($value as $versionWithV => $checksum)
|
||||
{
|
||||
$value[ltrim($versionWithV, 'v')] = $checksum;
|
||||
unset($value[$versionWithV]);
|
||||
}
|
||||
$results[$prepend . $key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
53
e107_handlers/e_file_inspector_json_phar.php
Normal file
53
e107_handlers/e_file_inspector_json_phar.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?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_json.php");
|
||||
|
||||
class e_file_inspector_json_phar extends e_file_inspector_json
|
||||
{
|
||||
/**
|
||||
* @param $jsonPharFilePath string Absolute path to the file inspector database
|
||||
*/
|
||||
public function __construct($jsonPharFilePath = null)
|
||||
{
|
||||
parent::__construct($jsonPharFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function loadDatabase()
|
||||
{
|
||||
Phar::loadPhar($this->database, "core_image.phar");
|
||||
$tmpFile = tmpfile();
|
||||
$tmpFilePath = stream_get_meta_data($tmpFile)['uri'];
|
||||
$this->copyUrlToResource("phar://core_image.phar/core_image.json", $tmpFile);
|
||||
$this->coreImage = json_decode(file_get_contents($tmpFilePath), true);
|
||||
if (!is_array($this->coreImage)) $this->coreImage = [];
|
||||
$this->coreImage = self::array_slash($this->coreImage);
|
||||
if (!$this->coreImage) $this->coreImage = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
108
e107_handlers/e_file_inspector_sqlphar.php
Normal file
108
e107_handlers/e_file_inspector_sqlphar.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @param $pharFilePath string Absolute path to the file inspector database
|
||||
*/
|
||||
public function __construct($pharFilePath = null)
|
||||
{
|
||||
parent::__construct($pharFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function loadDatabase()
|
||||
{
|
||||
Phar::loadPhar($this->database, "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($version = null)
|
||||
{
|
||||
$addVersionWhere = "";
|
||||
$inputParameters = [];
|
||||
if (!empty($version))
|
||||
{
|
||||
$addVersionWhere = "WHERE versions.version_string = ?";
|
||||
$inputParameters[] = $version;
|
||||
}
|
||||
$statement = $this->coreImage->prepare("
|
||||
SELECT path
|
||||
FROM file_hashes
|
||||
LEFT JOIN versions ON versions.version_id = file_hashes.release_version
|
||||
$addVersionWhere
|
||||
ORDER BY path ASC;
|
||||
");
|
||||
$statement->setFetchMode(PDO::FETCH_COLUMN, 0);
|
||||
$statement->execute($inputParameters);
|
||||
return new IteratorIterator($statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getChecksums($path)
|
||||
{
|
||||
$path = $this->customPathToDefaultPath($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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user