1
0
mirror of https://github.com/e107inc/e107.git synced 2025-08-02 12:48:26 +02:00

Minimum viable rewrite of File Inspector frontend

This commit is contained in:
Nick Liu
2020-03-27 00:27:46 -05:00
parent 6f6556178f
commit 6095c94de3
7 changed files with 534 additions and 691 deletions

Binary file not shown.

View File

@@ -9,8 +9,6 @@
* Administration - File inspector
*
*/
ini_set('zlib.output_compression', 0);
header('Content-Encoding: none'); // turn off gzip.
ob_implicit_flush(true);
ob_end_flush();
@@ -24,34 +22,6 @@ if(!getperms('Y'))
exit;
}
$error_handler->debug = FALSE;
$DOCS_DIRECTORY = $HELP_DIRECTORY; // Give a sensible, albeit probably invalid, value
if(substr($HELP_DIRECTORY,-5,5) == 'help/')
{
$DOCS_DIRECTORY = substr($HELP_DIRECTORY,0,-5); // Whatever $HELP_DIRECTORY is set to, assume docs are in a subdirectory called 'help' off it
}
$maindirs = array(
'admin' => $ADMIN_DIRECTORY,
'files' => $FILES_DIRECTORY,
'images' => $IMAGES_DIRECTORY,
'themes' => $THEMES_DIRECTORY,
'plugins' => $PLUGINS_DIRECTORY,
'handlers' => $HANDLERS_DIRECTORY,
'languages' => $LANGUAGES_DIRECTORY,
'downloads' => $DOWNLOADS_DIRECTORY,
'docs' => $DOCS_DIRECTORY
);
foreach ($maindirs as $maindirs_key => $maindirs_value)
{
$coredir[$maindirs_key] = substr($maindirs_value, 0, -1);
}
require_once('core_image.php');
set_time_limit(18000);
$e_sub_cat = 'fileinspector';
@@ -65,13 +35,14 @@ if(isset($_GET['scan']))
//$css_file = file_exists(e_THEME.$pref['admintheme'].'/'.$pref['admincss']) ? e_THEME.$pref['admintheme'].'/'.$pref['admincss'] : e_THEME.$pref['admintheme'].'/'.$pref['admincss'];
// $fi = new file_inspector;
/** @var file_inspector $fi */
$fi = e107::getSingleton('file_inspector');
echo "<!DOCTYPE html>
<html>
<head>
<title>Results</title>
<script type='text/javascript' src='https://cdn.jsdelivr.net/jquery/2.1.4/jquery.min.js'></script>
<script type='text/javascript' src='https://cdn.jsdelivr.net/jquery/2.2.1/jquery.min.js'></script>
<link rel='stylesheet' media='all' property='stylesheet' type='text/css' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css' />
".$fi->headerCss()." ".headerjs()."
@@ -136,6 +107,9 @@ else
class file_inspector {
/** @var e_file_inspector */
private $coreImage;
private $coreImageVersion;
var $root_dir;
var $files = array();
@@ -167,6 +141,10 @@ class file_inspector {
'num' => 0,
'line' => 0
);
/**
* @var array
*/
private $glyph;
function setOptions($post)
{
@@ -238,10 +216,11 @@ class file_inspector {
$this->iconTag[$k] = $this->glyph[$k][0];
}
global $e107, $core_image;
$e107 = e107::getInstance();
$this->coreImage = e107::getFileInspector('core');
$this->coreImageVersion = $this->coreImage->getCurrentVersion();
//$this->totalFiles = count($core_image,COUNT_RECURSIVE);
$this->countFiles($core_image);
$this->countFiles();
$this->root_dir = $e107 -> file_path;
@@ -250,7 +229,7 @@ class file_inspector {
$this->root_dir = substr($this->root_dir, 0, -1);
}
if($_POST['core'] == 'fail')
if(isset($_POST['core']) && $_POST['core'] == 'fail')
{
$_POST['integrity'] = TRUE;
}
@@ -260,7 +239,7 @@ class file_inspector {
$_POST['regex'] = stripslashes($_POST['regex']);
}
if($_POST['regex'])
if(!empty($_POST['regex']))
{
if($_POST['core'] == 'fail')
{
@@ -280,19 +259,9 @@ class file_inspector {
// Find the Total number of core files before scanning begins.
function countFiles($array)
private function countFiles()
{
foreach($array as $k=>$val)
{
if(is_array($val))
{
$this->countFiles($val);
}
elseif($val)
{
$this->totalFiles++;
}
}
return $this->totalFiles = iterator_count($this->coreImage->getPathIterator($this->coreImageVersion));
}
@@ -545,385 +514,260 @@ class file_inspector {
return 'check';
}
// This function does the real work
// $list -
// $deprecated
// $level
// $dir
// &$tree_end
// &$parent_expand
function inspect($list, $deprecated, $level, $dir, &$tree_end = null, &$parent_expand = null)
/**
* @param $baseDir string Absolute path to the directory to inspect
* @return string HTML output of the validated directory structure
*/
protected function inspect($baseDir)
{
global $coredir;
$sub_text = '';
$langs = $this->langs;
$lang_short = $this->lang_short;
unset ($childOut);
$parent_expand = false;
if(substr($dir, -1) == '/')
{
$dir = substr($dir, 0, -1);
$this->inspect_existing($baseDir);
$this->inspect_missing(array_keys($this->files));
return $this->generateScanResultsHtml();
}
$dir_id = dechex(crc32($dir));
$this->files[$dir_id]['.']['level'] = $level;
$this->files[$dir_id]['.']['parent'] = $this->parent;
$this->files[$dir_id]['.']['file'] = $dir;
$directory = $level ? basename($dir) : SITENAME;
$level++;
private function inspect_existing($baseDir)
{
$absoluteBase = realpath($baseDir);
if (!is_dir($absoluteBase)) return;
$this->sendProgress(vartrue($this->count['core']['num']),$this->totalFiles,FR_LAN_1);
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($baseDir));
$index = 0;
foreach ($iterator as $file)
{
$this->sendProgress($index++, $this->totalFiles);
if ($file->isDir()) continue;
foreach ($list as $key => $value)
{
// $dir_icon = 'fileinspector'; // default as unknown
$this->parent = $dir_id;
$absolutePath = $file->getRealPath();
$relativePath = preg_replace("/^" . preg_quote($absoluteBase . "/", "/") . "/", "", $absolutePath);
// Entry is a subdirectory - recurse another level
if(is_array($value))
{
$path = $dir.'/'.$key;
$child_open = false;
$child_end = true;
$dir_icon = 'folder_check';
$sub_text .= $this->inspect($value, $deprecated[$key], $level, $path, $child_end, $child_expand);
$tree_end = false;
if (empty($relativePath) || $relativePath == $absolutePath) continue;
if($child_expand)
{
$parent_expand = true;
$last_expand = true;
}
}
else
{
$this->sendProgress(vartrue($this->count['core']['num']),$this->totalFiles,FR_LAN_1);
$path = $dir.'/'.$key;
$fid = strtolower($key);
$this->files[$dir_id][$fid]['file'] = ($_POST['type'] == 'tree') ? $key : $path;
// We're checking a file here
if(($this->files[$dir_id][$fid]['size'] = filesize($path)) !== false)
{
// Look at core files
if($this->opt('core') != 'none')
{
$this->count['core']['num']++;
$this->count['core']['size'] += $this->files[$dir_id][$fid]['size'];
// TODO Max out of Memory when used
if($_POST['regex']) // Developer prefs activated - search file contents according to regex
{
// Get contents of file
$file_content = file($path);
if(($this->files[$dir_id][$fid]['size'] = filesize($path)) !== FALSE)
{
// Search string found - add file to list
if($this->files[$dir_id][$fid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content))
{
$this->files[$dir_id][$fid]['file'] = ($_POST['type'] == 'tree') ? $key : $path;
$this->files[$dir_id][$fid]['icon'] = 'file_core';
$dir_icon = 'fileinspector';
$parent_expand = TRUE;
$this->results++;
}
// Search string not found - discard from list
else
{
unset($this->files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
$dir_icon = ($dir_icon == 'fileinspector') ? 'folder_unknown': $dir_icon ;
$this->files[$relativePath] = $this->coreImage->validate($relativePath);
$this->updateFileSizeCounter($absolutePath, $this->files[$relativePath]);
}
}
}
else
{
// Actually check file integrity
if($this->opt('integrity'))
{
switch ($this_action = $this->check_action($dir,$key))
{
case 'ignore' :
case 'check' :
if($this->checksum($path) != $value)
{
$this->count['fail']['num']++;
$this->count['fail']['size'] += $this->files[$dir_id][$fid]['size'];
$this->files[$dir_id][$fid]['icon'] = 'file_fail';
$dir_icon = 'folder_fail';
$parent_expand = TRUE;
}
else
{
$this->count['pass']['num']++;
$this->count['pass']['size'] += $this->files[$dir_id][$fid]['size'];
if($this->opt('core') != 'fail')
private function inspect_missing($existingPaths)
{
$this->files[$dir_id][$fid]['icon'] = 'file_check';
$dir_icon = ($dir_icon == 'folder_fail' || $dir_icon == 'folder_missing') ? $dir_icon : 'folder_check';
}
else
$dbIterator = $this->coreImage->getPathIterator($this->coreImageVersion);
$dbPaths = iterator_to_array($dbIterator);
$dbPaths = array_map(function ($defaultPath)
{
unset($this->files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
return $this->coreImage->defaultPathToCustomPath($defaultPath);
}, $dbPaths);
$missingPaths = array_diff($dbPaths, $existingPaths);
foreach ($missingPaths as $relativePath)
{
$this->files[$relativePath] = $this->coreImage->validate($relativePath);
}
}
private function updateFileSizeCounter($absolutePath, $validationCode)
{
$status = $this->getStatusForValidationCode($validationCode);
$category = $this->statusToLegacyCountCategory($status);
$fileSize = filesize($absolutePath);
$this->count[$category]['size'] += $fileSize;
if ($validationCode & e_file_inspector::VALIDATED_RELEVANCE &&
$validationCode & e_file_inspector::VALIDATED_PRESENCE)
$this->count['core']['size'] += $fileSize;
}
private function statusToLegacyCountCategory($status)
{
$category = $status;
switch ($status)
{
case 'check':
$category = 'pass';
break;
case 'uncalc' :
case 'nocalc' :
$this->count['uncalculable']['num']++;
$this->count['uncalculable']['size'] += $this->files[$dir_id][$fid]['size'];
if($this->opt('core') != 'fail')
{
$this->files[$dir_id][$fid]['icon'] = 'file_uncalc';
}
else
{
unset($this->files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
}
case 'uncalc':
$category = 'uncalculable';
break;
case 'old':
$category = 'deprecated';
break;
}
return $category;
}
// Just identify as core file
else
private function generateScanResultsHtml()
{
$this->files[$dir_id][$fid]['icon'] = 'file_core';
$nestedFiles = [];
foreach ($this->files as $relativePath => $validation)
{
self::array_set($nestedFiles, $relativePath, $validation);
}
return $this->generateDirectoryHtml([SITENAME => $nestedFiles]);
}
private function generateDirectoryHtml($tree, $level = 0, $parentPath = '')
{
$html = '';
$this->sortAscDirectoriesFirst($tree);
$hide = $level;
foreach ($tree as $fileName => $validationCode)
{
$relativePath = "$parentPath/$fileName";
$rowId = base64_encode($relativePath);
list($icon, $title) = $this->getGlyphForValidationCode($validationCode);
$html .= "<div class=\"d\" title=\"$title\" style=\"margin-left: " . ($level * 8) . "px\">";
$html .= "<span onclick=\"ec('$rowId')\">";
$html .= $this->getTreeActionImageForFile($tree, $fileName, $rowId, $hide);
$html .= "</span>&nbsp;<span onclick=\"sh('f_$rowId')\">" .
$icon.
"&nbsp;$fileName</span>";
if (is_array($validationCode))
{
$html .= "<div id=\"d_$rowId\" " . ($hide ? "style=\"display:none\"" : "") . ">";
$html .= $this->generateDirectoryHtml($validationCode, $level + 1, $relativePath);
$html .= "</div>";
}
$html .= "</div>";
}
return $html;
}
private function sortAscDirectoriesFirst(array &$tree)
{
return uksort($tree, function ($a, $b) use ($tree)
{
if (is_array($tree[$a]) && !is_array($tree[$b])) return -1;
elseif (!is_array($tree[$a]) && is_array($tree[$b])) return 1;
return $a > $b;
});
}
private function getTreeActionImageForFile($tree, $fileName, $id, $hide = false)
{
if (!is_array($tree[$fileName]))
{
$actionImage = 'blank';
$actionAlt = ' ';
}
elseif ($hide)
{
$actionImage = 'expand';
$actionAlt = '+';
}
else
{
unset ($this->files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
$actionImage = 'contract';
$actionAlt = '-';
}
return "<img id='e_$id' class='e' src='".e_IMAGE."fileinspector/$actionImage.png' alt='$actionAlt' width='15' />";
}
elseif($this->opt('missing'))
private function getGlyphForValidationCode($validationCodeOrArray)
{
switch ($this_action = $this->check_action($dir,$key))
if (is_array($validationCodeOrArray)) return $this->getWorstGlyphForFolder($validationCodeOrArray);
return $this->glyph['file_' . $this->getStatusForValidationCode($validationCodeOrArray)];
}
private function getStatusForValidationCode($validationCode)
{
case 'check' :
case 'uncalc' :
$this->count['missing']['num']++;
$this->files[$dir_id][$fid]['icon'] = 'file_missing';
$dir_icon = ($dir_icon == 'folder_fail') ? $dir_icon : 'folder_missing';
$parent_expand = TRUE;
break;
case 'ignore' :
case 'nocalc' :
// These files can be missing without error - delete from the list
unset ($this->files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
break;
}
}
if ($validationCode & e_file_inspector::VALIDATED)
return 'check';
if (!($validationCode & e_file_inspector::VALIDATED_RELEVANCE))
return 'unknown';
if (!($validationCode & e_file_inspector::VALIDATED_SECURITY))
return 'warning';
if (!($validationCode & e_file_inspector::VALIDATED_PRESENCE))
return 'missing';
if (!($validationCode & e_file_inspector::VALIDATED_DETERMINABLE))
return 'uncalc';
if (!($validationCode & e_file_inspector::VALIDATED_UPTODATE))
if ($validationCode & e_file_inspector::VALIDATED_HASH)
return 'old';
else
{
unset ($this->files[$dir_id][$fid]);
}
}
return 'fail';
return 'unknown';
}
if($this->opt('noncore') || $this->opt('oldcore'))
private function getStatusRank($status)
{
if(!$handle = opendir($dir.'/'))
switch ($status)
{
//e107::getMessage()->addInfo("Couldn't Open : ".$dir);
case 'uncalc':
return -2;
case 'unknown':
return -1;
case 'check':
return 0;
case 'missing':
return 1;
case 'old':
return 2;
case 'fail':
return 3;
case 'warning':
return 4;
}
return -1;
}
while (is_resource($handle) && false !== ($readdir = readdir($handle)))
private function getWorstGlyphForFolder($treeFolder)
{
// $prog_count = $this->count['unknown']['num'] + $this->count['deprecated']['num'];
// $this->sendProgress($prog_count,$this->totalFiles,FR_LAN_1);
if(!in_array($readdir,$this->excludeFiles) && (strpos('._', $readdir) === false))
$worstStatus = 'uncalc';
$worstStatusRank = -PHP_INT_MAX;
array_walk_recursive($treeFolder, function ($value) use (&$worstStatus, &$worstStatusRank)
{
if(is_dir($dir.'/'.$readdir))
$currentStatus = $this->getStatusForValidationCode($value);
$currentStatusRank = $this->getStatusRank($currentStatus);
if ($currentStatusRank > $worstStatusRank)
{
if(!isset($list[$readdir]) && ($level > 1 || $readdir == 'e107_install'))
{
$child_open = false;
$child_end = true;
$sub_text .= $this->inspect(array(), $deprecated[$readdir], $level, $dir.'/'.$readdir, $child_end, $child_expand);
$tree_end = false;
if($child_expand)
{
$parent_expand = true;
$last_expand = true;
$worstStatusRank = $currentStatusRank;
$worstStatus = $currentStatus;
}
}
}
else
{
if($this->opt('nolang') && !empty($langs) && !empty($lang_short)) // Hide Non-core Languages.
{
// PHP Lang files.
$lreg = "/[\/_](".implode("|",$langs).")/";
if(preg_match($lreg, $dir.'/'.$readdir))
{
continue;
});
return $this->glyph['folder_' . $worstStatus];
}
// TinyMce Lang files.
$lregs = "/[\/_](".implode("|",$lang_short).")_dlg\.js/";
if(preg_match($lregs, $dir.'/'.$readdir))
/**
* Set an array item to a given value using "slash" notation.
*
* If no key is given to the method, the entire array will be replaced.
*
* Based on Illuminate\Support\Arr::set()
*
* @param array $array
* @param string|null $key
* @param mixed $value
* @return array
* @copyright Copyright (c) Taylor Otwell
* @license https://github.com/illuminate/support/blob/master/LICENSE.md MIT License
*/
private static function array_set(&$array, $key, $value)
{
continue;
if (is_null($key))
{
return $array = $value;
}
// PhpMailer Lang Files.
$lregsm = "/[\/_]phpmailer\.lang-(".implode("|",$lang_short).")\.php/";
if(preg_match($lregsm, $dir.'/'.$readdir))
$keys = explode('/', $key);
while (count($keys) > 1)
{
continue;
}
$key = array_shift($keys);
// If the key doesn't exist at this depth, we will just create an empty array
// to hold the next value, allowing us to create the arrays to hold final
// values at the correct depth. Then we'll keep digging into the array.
if (!isset($array[$key]) || !is_array($array[$key]))
{
$array[$key] = [];
}
$aid = strtolower($readdir);
if(!isset($this->files[$dir_id][$aid]['file']) && !$known[$dir_id][$aid])
{
if($this->checkKnownSecurity($dir.'/'.$readdir) === false)
{
if(isset($deprecated[$readdir]))
{
if($this->opt('oldcore'))
{
$this->files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir;
$this->files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir);
$this->files[$dir_id][$aid]['icon'] = 'file_old';
$this->count['deprecated']['num']++;
$this->count['deprecated']['size'] += $this->files[$dir_id][$aid]['size'];
$dir_icon = 'folder_old';
}
}
else
{
if($this->opt('noncore'))
{
$this->files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir;
$this->files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir);
//echo "<br />dir: ".$dir.'/'.$readdir. " ( ".$this->files[$dir_id][$aid]['size'].")";
$this->files[$dir_id][$aid]['icon'] = 'file_unknown';
$this->count['unknown']['num']++;
$this->count['unknown']['size'] += $this->files[$dir_id][$aid]['size'];
}
}
}
else
{
$this->files[$dir_id][$aid]['file'] = ($_POST['type'] == 'tree') ? $readdir : $dir.'/'.$readdir;
$this->files[$dir_id][$aid]['size'] = filesize($dir.'/'.$readdir);
$this->files[$dir_id][$aid]['icon'] = 'file_warning';
$this->count['warning']['num']++;
$this->count['warning']['size'] += $this->files[$dir_id][$aid]['size'];
$this->count['deprecated']['num']++;
$this->count['deprecated']['size'] += $this->files[$dir_id][$aid]['size'];
$dir_icon = 'folder_warning';
$parent_expand = TRUE;
$array = &$array[$key];
}
$regexOpt = $this->opt('regex');
if(!empty($regexOpt))
{
$file_content = file($dir.'/'.$readdir);
if($this->files[$dir_id][$aid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content))
{
$dir_icon = 'fileinspector';
$parent_expand = TRUE;
$this->results++;
}
else
{
unset($this->files[$dir_id][$aid]);
$dir_icon = ($dir_icon == 'fileinspector') ? $dir_icon : 'folder';
}
}
else
{
if(isset($deprecated[$readdir]))
{
if($this->opt('oldcore'))
{
$dir_icon = ($dir_icon == 'folder_warning' || $dir_icon == 'folder_fail' || $dir_icon == 'folder_missing' ) ? $dir_icon : 'folder_old';
$parent_expand = TRUE;
}
}
else
{
if($this->opt('noncore'))
{
$dir_icon = ($dir_icon == 'folder_warning' || $dir_icon == 'folder_fail' || $dir_icon == 'folder_missing' || $dir_icon == 'folder_old' || $dir_icon == 'folder_old_dir') ? $dir_icon : 'folder_unknown';
$parent_expand = TRUE;
}
}
}
}
elseif($this->opt('core') == 'none')
{
unset($this->files[$dir_id][$aid]);
}
}
}
}
closedir($handle);
$array[array_shift($keys)] = $value;
}
$this->sendProgress($this->count['core']['num'],$this->totalFiles,FR_LAN_1);
$dir_icon = $dir_icon ? $dir_icon : 'folder_unknown';
// $icon = "<img src='".e_IMAGE."fileinspector/".$dir_icon."' class='i' alt='' />";
$icon = $this->iconTag[$dir_icon];
$tp = e107::getParser();
$imgBlank = $tp->toImage('{e_IMAGE}fileinspector/blank.png', array(
'alt' => '',
'legacy' => '{e_IMAGE}fileinspector/',
'w' => 9,
'h' => 9,
'class' => 'c',
));
$imgExpand = $tp->toImage('{e_IMAGE}fileinspector/expand.png', array(
'alt' => '',
'legacy' => '{e_IMAGE}fileinspector/',
'w' => 15,
'class' => 'e',
'id' => 'e_' . $dir_id,
));
$imgContract = $tp->toImage('{e_IMAGE}fileinspector/contract.png', array(
'alt' => '',
'legacy' => '{e_IMAGE}fileinspector/',
'w' => 15,
'class' => 'e',
'id' => 'e_' . $dir_id,
));
$hide = ($last_expand && $dir_icon != 'folder_core') ? "" : "style='display: none'";
$text = '<div class="d" title="' . $this->getDiz($dir_icon) . '" style="margin-left: ' . ($level * 8) . 'px">';
$text .= $tree_end ? $imgBlank : '<span onclick="ec(\'' . $dir_id . '\')">' . ($hide ? $imgExpand : $imgContract) . '</span>';
$text .= '&nbsp;<span onclick="sh(\'f_' . $dir_id . '\')">' . $icon . '&nbsp;' . $directory . '</span>';
$text .= $tree_end ? '' : '<div ' . $hide . ' id="d_' . $dir_id . '">' . $sub_text . '</div>';
$text .= '</div>';
$this->files[$dir_id]['.']['icon'] = $dir_icon;
return $text;
return $array;
}
private function checkKnownSecurity($path)
@@ -944,12 +788,53 @@ class file_inspector {
function scan_results()
{
global $core_image, $deprecated_image;
$ns = e107::getRender();
$this->count = [
'core' => [
'num' => 0,
'size' => 0,
],
'fail' => [
'num' => 0,
'size' => 0,
],
'pass' => [
'num' => 0,
'size' => 0,
],
'uncalculable' => [
'num' => 0,
'size' => 0,
],
'missing' => [
'num' => 0,
],
'deprecated' => [
'num' => 0,
'size' => 0,
],
'unknown' => [
'num' => 0,
'size' => 0,
],
'warning' => [
'num' => 0,
'size' => 0,
]
];
$scan_text = $this->inspect($this->root_dir);
$scan_text = $this->inspect($core_image, $deprecated_image, 0, $this->root_dir);
array_walk_recursive($this->files, function ($validationCode)
{
$status = $this->getStatusForValidationCode($validationCode);
$category = $this->statusToLegacyCountCategory($status);
$this->count[$category]['num']++;
$this->sendProgress($this->totalFiles,$this->totalFiles,' &nbsp; &nbsp; &nbsp;');
if ($validationCode & e_file_inspector::VALIDATED_RELEVANCE &&
$validationCode & e_file_inspector::VALIDATED_PRESENCE)
$this->count['core']['num']++;
});
$this->sendProgress($this->totalFiles, $this->totalFiles);
echo "<div style='display:block;height:30px'>&nbsp;</div>";
@@ -1046,16 +931,16 @@ class file_inspector {
$text .= "<tr><td style='padding-right: 4px' colspan='2'>
<ul><li>
<a href=\"javascript: expandit('i_corrupt')\">".FR_LAN_11."...</a><div style='display: none' id='i_corrupt'>
<a href=\"#\" onclick=\"expandit('i_corrupt')\">".FR_LAN_11."...</a><div style='display: none' id='i_corrupt'>
".FR_LAN_12."<br /><br /></div>
</li><li>
<a href=\"javascript: expandit('i_date')\">".FR_LAN_13."...</a><div style='display: none' id='i_date'>
<a href=\"#\" onclick=\"expandit('i_date')\">".FR_LAN_13."...</a><div style='display: none' id='i_date'>
".FR_LAN_14."<br /><br /></div>
</li><li>
<a href=\"javascript: expandit('i_edit')\">".FR_LAN_15."...</a><div style='display: none' id='i_edit'>
<a href=\"#\" onclick=\"expandit('i_edit')\">".FR_LAN_15."...</a><div style='display: none' id='i_edit'>
".FR_LAN_16."<br /><br /></div>
</li><li>
<a href=\"javascript: expandit('i_cvs')\">".FR_LAN_17."...</a><div style='display: none' id='i_cvs'>
<a href=\"#\" onclick=\"expandit('i_cvs')\">".FR_LAN_17."...</a><div style='display: none' id='i_cvs'>
".FR_LAN_18."<br /><br /></div>
</li></ul>
</td></tr>";
@@ -1088,9 +973,6 @@ class file_inspector {
foreach ($this->files as $dir_id => $fid)
{
// $this->sendProgress($cnt,$this->totalFiles,$path);
ksort($fid);
$text .= ($this->opt('type') == 'tree') ? "<table class='t' style='display: none' id='f_".$dir_id."'>" : "";
$initial = FALSE;
@@ -1354,7 +1236,7 @@ class file_inspector {
}
function sendProgress($rand,$total,$diz)
function sendProgress($rand,$total)
{
if($this->progress_units <40 && ($rand != $total))
{
@@ -1491,29 +1373,27 @@ class file_inspector {
$e_js->renderJs('inline_css', false, 'css', false);
echo "\n<!-- footer_inline_css -->\n";
/*
echo "<!-- Theme css -->\n";
if(strpos(e_SELF.'?'.e_QUERY, 'menus.php?configure') === FALSE && isset($pref['admincss']) && $pref['admincss'] && file_exists(THEME.$pref['admincss'])) {
$css_file = file_exists(THEME.'admin_'.$pref['admincss']) ? THEME_ABS.'admin_'.$pref['admincss'] : THEME_ABS.$pref['admincss'];
echo "<link rel='stylesheet' href='".$css_file."' type='text/css' />\n";
} elseif(isset($pref['themecss']) && $pref['themecss'] && file_exists(THEME.$pref['themecss']))
$text = "
<style type='text/css'>
<!--\n";
if (vartrue($_POST['regex']))
{
$css_file = file_exists(THEME.'admin_'.$pref['themecss']) ? THEME_ABS.'admin_'.$pref['themecss'] : THEME_ABS.$pref['themecss'];
echo "<link rel='stylesheet' href='".$css_file."' type='text/css' />\n";
$text .= ".f { padding: 1px 0px 1px 8px; vertical-align: bottom; width: 90% }\n";
}
else
{
$css_file = file_exists(THEME.'admin_style.css') ? THEME_ABS.'admin_style.css' : THEME_ABS.'style.css';
echo "<link rel='stylesheet' href='".$css_file."' type='text/css' />\n";
$text .= ".f { padding: 1px 0px 1px 8px; vertical-align: bottom; width: 90%; white-space: nowrap }\n";
}
if(!isset($no_core_css) || !$no_core_css) {
echo "<link rel='stylesheet' href='".e_WEB_CSS."e107.css' type='text/css' />\n";
}
* */
$text .= ".d { margin: 2px 0px 1px 8px; cursor: default; white-space: nowrap }
.s { padding: 1px 8px 1px 0px; vertical-align: bottom; width: 10%; white-space: nowrap }
.t { margin-top: 1px; width: 100%; border-collapse: collapse; border-spacing: 0px }
.w { padding: 1px 0px 1px 8px; vertical-align: bottom; width: 90% }
.i { width: 16px; height: 16px }
.e { width: 9px; height: 9px }
i.fa-folder-open-o, i.fa-times-circle-o { cursor:pointer }
-->
</style>\n";
echo $text;
}
}
@@ -1558,82 +1438,15 @@ require_once(e_ADMIN.'footer.php');
function headerjs()
{
/*$c = e_IMAGE_ABS . 'fileinspector/contract.png';
$e = e_IMAGE_ABS . 'fileinspector/expand.png';
$text = '<script type="text/javascript">
function ec(element) {
$("#d_"+element).stop().animate({"height": "toggle"}, { duration: 500 });
var $img = $("#e_"+element);
if($img.attr("src") == "' . $e . '") {
$img.attr("src", "' . $c . '");
} else {
$img.attr("src", "' . $e . '");
}
}
function sh(element) {
$("#"+element).stop().animate({"height": "toggle"}, { duration: 500 });
}
</script>';*/
/*
* // Start of rework
e107::js('footer-inline', "
c = new Image();
c = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/contract.png';
e = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/expand.png';
function ec(ecid) {
icon = $('#e_' + ecid).src;
if(icon == e) {
$('#e_' + ecid).src = c;
} else {
$('#e_' + ecid).src = e;
}
div = $('#d_' + ecid).style;
if(div.display == 'none')
{
div.display = '';
}
else
{
div.display = 'none';
}
}
var hideid = 'initial';
function sh(showid)
{
if(hideid != showid)
{
show = $('#'+showid).style;
hide = $('#'+hideid).style;
show.display = '';
hide.display = 'none';
hideid = showid;
}
}
");*/
global $e107;
$text = "<script type='text/javascript'>
e107::js('footer', '{e_WEB}/js/core/all.jquery.js', 'jquery', 1);
$text = e107::getJs()->renderJs('footer', 1, true, true);
$text .= "<script type='text/javascript'>
<!--
c = new Image(); c = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/contract.png';
e = '".SITEURLBASE.e_IMAGE_ABS."fileinspector/expand.png';
function ec(ecid) {
icon = document.getElementById('e_' + ecid).src;
if(icon == e) {
if(icon.indexOf('expand.png') !== -1) {
document.getElementById('e_' + ecid).src = c;
} else {
document.getElementById('e_' + ecid).src = e;
@@ -1658,24 +1471,6 @@ function sh(showid) {
//-->
</script>";
$text .= "
<style type='text/css'>
<!--\n";
if(vartrue($_POST['regex'])) {
$text .= ".f { padding: 1px 0px 1px 8px; vertical-align: bottom; width: 90% }\n";
} else {
$text .= ".f { padding: 1px 0px 1px 8px; vertical-align: bottom; width: 90%; white-space: nowrap }\n";
}
$text .= ".d { margin: 2px 0px 1px 8px; cursor: default; white-space: nowrap }
.s { padding: 1px 8px 1px 0px; vertical-align: bottom; width: 10%; white-space: nowrap }
.t { margin-top: 1px; width: 100%; border-collapse: collapse; border-spacing: 0px }
.w { padding: 1px 0px 1px 8px; vertical-align: bottom; width: 90% }
.i { width: 16px; height: 16px }
.e { width: 9px; height: 9px }
i.fa-folder-open-o, i.fa-times-circle-o { cursor:pointer }
-->
</style>\n";
return $text;
}

View File

@@ -193,7 +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' => '{e_HANDLER}e_file_inspector_json_phar.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',
@@ -1609,9 +1609,9 @@ class e107
*
* @return e_file_inspector
*/
public static function getFileInspector()
public static function getFileInspector($type = 'core')
{
return self::getSingleton('e_file_inspector');
return self::getObject('e_file_inspector_json_phar', e_ADMIN . "core_image.php");
}
/**

View File

@@ -22,6 +22,7 @@ abstract class e_file_inspector implements e_file_inspector_interface
protected $defaultDirsCache;
protected $customDirsCache;
private $undeterminable = array();
/**
* e_file_inspector constructor
@@ -32,6 +33,16 @@ abstract class e_file_inspector implements e_file_inspector_interface
{
$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",
]
);
}
/**
@@ -165,14 +176,14 @@ abstract class e_file_inspector implements e_file_inspector_interface
return false;
}
protected function pathToDefaultPath($path)
/**
* Convert a custom site path to a default path
* @param string $path Custom path
* @return string
*/
public function customPathToDefaultPath($path)
{
if (!$this->customDirsCache)
{
$this->defaultDirsCache = e107::getInstance()->defaultDirs();
$customDirs = e107::getInstance()->e107_dirs ? e107::getInstance()->e107_dirs : [];
$this->customDirsCache = array_diff_assoc($customDirs, $this->defaultDirsCache);
}
if (!is_array($this->customDirsCache)) $this->populateDirsCache();
foreach ($this->customDirsCache as $dirType => $customDir)
{
if (!isset($this->defaultDirsCache[$dirType])) continue;
@@ -186,6 +197,22 @@ abstract class e_file_inspector implements e_file_inspector_interface
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;
@@ -206,6 +233,13 @@ abstract class e_file_inspector implements e_file_inspector_interface
*/
private function isDeterminable($absolutePath)
{
return is_file($absolutePath) && is_readable($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);
}
}

View File

@@ -56,7 +56,7 @@ class e_file_inspector_json extends e_file_inspector
*/
public function getChecksums($path)
{
$path = $this->pathToDefaultPath($path);
$path = $this->customPathToDefaultPath($path);
return isset($this->coreImage[$path]) ? $this->coreImage[$path] : [];
}

View File

@@ -62,7 +62,7 @@ class e_file_inspector_sqlphar extends e_file_inspector
*/
public function getChecksums($path)
{
$path = $this->pathToDefaultPath($path);
$path = $this->customPathToDefaultPath($path);
$statement = $this->coreImage->prepare("
SELECT versions.version_string, file_hashes.hash
FROM file_hashes

View File

@@ -64,17 +64,12 @@ class e_file_inspectorTest extends \Codeception\Test\Unit
$this->assertEquals(0, $result & e_file_inspector::VALIDATED_PRESENCE);
}
/**
* TODO: Create a stable interface for pathToDefaultPath()
* @throws ReflectionException
*/
public function testPathToDefaultPath()
public function testCustomPathToDefaultPath()
{
/** @var e_file_inspector $object */
$object = $this->make('e_file_inspector');
$class = new ReflectionClass(get_class($object));
$method = $class->getMethod('pathToDefaultPath');
$method->setAccessible(true);
$method->invoke($object, 'populate_cache');
$object->customPathToDefaultPath('populate_cache');
$member = $class->getProperty('customDirsCache');
$member->setAccessible(true);
$customDirs = $member->getValue($object);
@@ -83,7 +78,26 @@ class e_file_inspectorTest extends \Codeception\Test\Unit
$input = "e963_admin/index.php";
$expected = "e107_admin/index.php";
$actual = $method->invoke($object, $input);
$actual = $object->customPathToDefaultPath($input);
$this->assertEquals($expected, $actual);
}
public function testDefaultPathToCustomPath()
{
/** @var e_file_inspector $object */
$object = $this->make('e_file_inspector');
$class = new ReflectionClass(get_class($object));
$object->customPathToDefaultPath('populate_cache');
$member = $class->getProperty('customDirsCache');
$member->setAccessible(true);
$customDirs = $member->getValue($object);
$customDirs['ADMIN_DIRECTORY'] = 'e963_admin/';
$member->setValue($object, $customDirs);
$input = "e107_admin/index.php";
$expected = "e963_admin/index.php";
$actual = $object->defaultPathToCustomPath($input);
$this->assertEquals($expected, $actual);
}