array( 'controller' => 'fileinspector_ui', 'path' => null, 'ui' => 'fileinspector_form_ui', 'uipath' => null ), ); protected $adminMenu = array( 'main/setup' => array('caption'=> LAN_CONFIGURE, 'perm' => 'P'), // 'main/run' => array('caption'=> FR_LAN_2, 'perm' => 'P'), ); protected $adminMenuAliases = array( 'main/edit' => 'main/list' ); protected $menuTitle = FC_LAN_1; protected $adminMenuIcon = 'e-fileinspector-24'; function init() { if(!empty($_GET['viewerror'])) { $file = e107::getSession()->get('fileinspector_error_log_'. $_GET['viewerror']); if(!empty($file)) { $contents = file_get_contents(e_BASE.$file); echo "
".$contents."
"; } exit; } if(!empty($_GET['action']) && $_GET['action'] === 'begin') { /** @var file_inspector $fi */ $fi = e107::getSingleton('file_inspector'); $fi->scan_results(); exit(); } } } class fileinspector_ui extends e_admin_ui { protected $pluginTitle = FC_LAN_1; protected $pluginName = 'core'; protected $eventName = 'fileinspector'; protected $table = ''; protected $pid = ''; protected $perPage = 10; protected $batchDelete = true; protected $batchCopy = true; // protected $sortField = 'somefield_order'; // protected $orderStep = 10; // protected $tabs = array('Tabl 1','Tab 2'); // Use 'tab'=>0 OR 'tab'=>1 in the $fields below to enable. protected $listQry = ""; // Example Custom Query. LEFT JOINS allowed. Should be without any Order or Limit. protected $listOrder = ''; protected $fields = array (); protected $fieldpref = array(); protected $prefs = array(); protected $fi; public function init() { // } public function SetupPage() { /** @var file_inspector */ $fi =e107::getSingleton('file_inspector'); return $fi->scan_config(); } public function RunPage() { $this->addTitle(LAN_CONFIGURE); $this->addTitle(LAN_RUN); $frm = $this->getUI(); unset($_GET['mode'],$_GET['action']); $source = e_SELF."?mode=main&action=begin&".http_build_query($_GET); $target = '#results-container'; $interval = 500; $text = $frm->open('runit'); $text .= $frm->progressBar('inspector-progress', 0); // $text .= ''; $text .= ' '.FR_LAN_33.''; $text .= ' '.LAN_CANCEL.''; $text .= $frm->close(); $text .= "
"; return $text; } } class fileinspector_form_ui extends e_admin_form_ui { } new fileinspector_admin(); require_once(e_ADMIN."auth.php"); e107::getAdminUI()->runPage(); require_once(e_ADMIN."footer.php"); class file_inspector { const SCAN_ID_PREFIX = 'e107-file-inspector-scan-'; /** @var e_file_inspector */ private $coreImage; private $coreImageVersion; private $root_dir; private $files = array(); private $fileSizes = array(); private $count = array(); /** @deprecated What's this? */ var $results = 0; private $totalFiles = 0; private $progress_units = 0; private $progressPercentage = 0; private $langs = array(); private $lang_short = array(); private $iconTag = array(); private $options = array( 'core' => '', 'type' => 'tree', 'missing' => 0, 'noncore' => 9, 'oldcore' => 0, 'integrity' => 1, 'regex' => 0, 'mod' => '', 'num' => 0, 'line' => 0, 'scan' => null // progress identifier ); /** * @var array */ private $glyph; function setOptions($post) { foreach($this->options as $k=>$v) { if(isset($post[$k])) { $this->options[$k] = $post[$k]; } } } function __construct() { $lng = e107::getLanguage(); $langs = $lng->installed(); $this->setOptions($_GET); $lang_short = array(); foreach($langs as $k=>$val) { if($val == "English") // Core release language, so ignore it. { unset($langs[$k]); continue; } $lang_short[] = $lng->convert($val); } $this->langs = $langs; $this->lang_short = $lang_short; $this->glyph = array( 'folder_close' => array(''), 'folder_up' => array(''), 'folder_root' => array(''), 'warning' => array(''), 'info' => array(''), 'fileinspector' => array(''), 'folder' => array(''), 'folder_check' => array('', FC_LAN_24 ), 'folder_fail' => array('', FC_LAN_25 ), 'folder_uncalc' => array('', FC_LAN_24 ), 'folder_missing' => array('', FC_LAN_26 ), 'folder_warning' => array(''), 'folder_old' => array('', FC_LAN_27 ), 'folder_old_dir' => array(''), 'folder_unknown' => array('', FC_LAN_28 ), 'file_check' => array('', FC_LAN_29), 'file_core' => array('', FC_LAN_30), 'file_fail' => array('', FC_LAN_31 ), 'file_missing' => array('', FC_LAN_32 ), 'file_old' => array('', FC_LAN_33 ), 'file_uncalc' => array('', FC_LAN_34 ), 'file_warning' => array('', FC_LAN_35 ), 'file_unknown' => array('', FC_LAN_36 ), ); foreach($this->glyph as $k=>$v) { $this->iconTag[$k] = $this->glyph[$k][0]; } $e107 = e107::getInstance(); $this->coreImage = e107::getFileInspector('core'); $this->coreImageVersion = $this->coreImage->getCurrentVersion(); $this->root_dir = $e107 -> file_path; if(substr($this->root_dir, -1) == '/') { $this->root_dir = substr($this->root_dir, 0, -1); } if(isset($_POST['core']) && $_POST['core'] == 'integrity_fail_only') { $_POST['integrity'] = TRUE; } if(MAGIC_QUOTES_GPC && vartrue($_POST['regex'])) { $_POST['regex'] = stripslashes($_POST['regex']); } if(!empty($_POST['regex'])) { if($_POST['core'] == 'fail') { $_POST['core'] = 'all'; } $_POST['missing'] = 0; $_POST['integrity'] = 0; } self::pruneOldProgressFiles(); } private function opt($key) { return $this->options[$key]; } // Find the Total number of core files before scanning begins. private function countFiles() { return $this->totalFiles = iterator_count($this->coreImage->getPathIterator($this->coreImageVersion)); } function getLegend() { return $this->glyph; } function renderHelp() { $text = ""; foreach($this->iconTag as $k=>$v) { $text .= ""; } $text .= "
".$v."".$k."
"; return $text; // echo $text; } public function scan_config() { $frm = e107::getForm(); $pref = e107::pref('core'); if($_GET['mode'] == 'run') { return; } $tab = array(); $head = "
"; $text = " "; /* $text .= " ";*/ $coreOpts = array('integrity_fail_only'=>FC_LAN_6, 'all'=>LAN_ALL, 'none'=> LAN_NONE); $text .= ""; $dispOpt = array('tree'=>FC_LAN_15, 'list'=>LAN_LIST); $text .= ""; $text .= ""; $text .= ""; $text .= ""; /* $text .= ""; */ $text .= "
".LAN_OPTIONS."
".LAN_SHOW." ".FC_LAN_5.": ".$frm->select('core',$coreOpts,varset($_POST['core']))."
".FC_LAN_14.": ".$frm->select('type', $dispOpt, varset($_POST['type']))."
".LAN_SHOW." ".FC_LAN_13.": ".LAN_YES."   ".LAN_NO."  
".LAN_SHOW." ".FC_LAN_7.": ".LAN_YES."   ".LAN_NO."  
".LAN_SHOW." ".FC_LAN_21.": ".LAN_YES."   ".LAN_NO."  
".FC_LAN_8.": ".LAN_YES."   ".LAN_NO."  
"; $tab['basic'] = array('caption'=>LAN_OPTIONS, 'text'=>$text); if($pref['developer']) { $text2 = ""; /* $text2 .= "";*/ $text2 .= ""; $text2 .= ""; $text2 .= ""; $text2 .= "
".FC_LAN_17."
".FC_LAN_18.": ##
".FC_LAN_19.":
".FC_LAN_20.":
"; $tab['advanced'] = array('caption'=>FC_LAN_17, 'text'=>$text2); } $tabText = e107::getForm()->tabs($tab); $foot = "
".$frm->admin_button('scan', md5(time()), 'other', LAN_GO). $frm->hidden('mode','main'). $frm->hidden('action','run')."
"; $text = $head.$tabText.$foot; return $text; // $ns->tablerender(FC_LAN_1, $text); } /** * @param $baseDir string Absolute path to the directory to inspect */ protected function inspect($baseDir) { $this->progress_units = 0; $this->totalFiles = 1; $this->sendProgress(0); $this->totalFiles = iterator_count(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($baseDir))) * 2; $this->inspect_existing($baseDir); $this->inspect_missing(array_keys($this->files)); } private function inspect_existing($baseDir) { $absoluteBase = realpath($baseDir); if (!is_dir($absoluteBase)) return; $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $baseDir, FilesystemIterator::SKIP_DOTS ) ); foreach ($iterator as $file) { $this->sendProgress(1); if ($file->isDir()) continue; $absolutePath = $file->getRealPath(); $relativePath = preg_replace("/^" . preg_quote($absoluteBase . "/", "/") . "/", "", $absolutePath); if (empty($relativePath) || $relativePath == $absolutePath) continue; $this->files[$relativePath] = $this->coreImage->validate($relativePath); $this->fileSizes[$relativePath] = filesize($absolutePath); $this->updateFileSizeCounter($absolutePath, $this->files[$relativePath]); } } private function inspect_missing($existingPaths) { $dbIterator = $this->coreImage->getPathIterator($this->coreImageVersion); $dbPaths = iterator_to_array($dbIterator); $dbPaths = array_map(function ($defaultPath) { 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 = e_file_inspector::getStatusForValidationCode($validationCode); $category = $this->statusToLegacyCountCategory($status); $fileSize = filesize($absolutePath); $this->count[$category]['size'] += $fileSize; if ($validationCode & e_file_inspector::VALIDATED_PATH_VERSION && $validationCode & e_file_inspector::VALIDATED_FILE_EXISTS) $this->count['core']['size'] += $fileSize; } private function statusToLegacyCountCategory($status) { $category = $status; switch ($status) { case 'check': $category = 'pass'; break; case 'uncalc': $category = 'uncalculable'; break; case 'old': $category = 'deprecated'; break; } return $category; } /** * @return string HTML output of the validated directory structure */ private function generateScanResultsHtml() { $nestedFiles = []; foreach ($this->files as $relativePath => $validation) { if ($this->displayAllowed($validation)) self::array_set($nestedFiles, $relativePath, $validation); } return $this->generateDirectoryHtml([SITENAME => $nestedFiles]); } private function renderFileName($tree, $fileName, $relativePath,$rowId) { if($fileName === 'error_log') { $hash = md5($relativePath); e107::getSession()->set('fileinspector_error_log_'. $hash, $relativePath); return "".$fileName.""; } if (!is_array($tree[$fileName])) { return $fileName; } return "".$fileName.""; } private function generateDirectoryHtml($tree, $level = 0, $parentPath = '') { $html = ''; $this->sortAscDirectoriesFirst($tree); $hide = $level; foreach ($tree as $fileName => $validationCode) { $this->sendProgress(1); $relativePath = ltrim("$parentPath/$fileName", '/'); if ($level === 0) $relativePath = ''; $rowId = str_replace(" ", "%20", $relativePath); list($icon, $title) = $this->getGlyphForValidationCode($validationCode); $html .= "
"; $html .= ""; $html .= $this->getTreeActionImageForFile($tree, $fileName, $rowId, $hide); $html .= " " . $icon. " ".$this->renderFileName($tree, $fileName,$relativePath, $rowId).""; if (is_array($validationCode)) { $html .= "
"; $html .= $this->generateDirectoryHtml($validationCode, $level + 1, $relativePath); $html .= "
"; } else { $oldVersion = $this->getOldVersionOfPath($relativePath, $validationCode); $html .= ''; $html .= isset($this->fileSizes[$relativePath]) ? $this->parsesize($this->fileSizes[$relativePath]) : ''; $html .= $oldVersion ? " (v$oldVersion)" : ""; $html .= ''; } $html .= "
"; } 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 { $actionImage = 'contract'; $actionAlt = '-'; } return "$actionAlt"; } private function getGlyphForValidationCode($validationCodeOrArray) { if (is_array($validationCodeOrArray)) return $this->getWorstGlyphForFolder($validationCodeOrArray); return $this->glyph['file_' . e_file_inspector::getStatusForValidationCode($validationCodeOrArray)]; } private function getStatusRank($status) { $rank = PHP_INT_MIN; switch ($status) { case 'unknown': $rank = -2; break; case 'uncalc': $rank = -1; break; case 'check': $rank = 0; break; case 'missing': $rank = 1; break; case 'old': $rank = 2; break; case 'fail': $rank = 3; break; case 'warning': $rank = 4; break; } return $rank; } private function getWorstGlyphForFolder($treeFolder) { $worstStatus = 'unknown'; $worstStatusRank = -PHP_INT_MAX; array_walk_recursive($treeFolder, function ($value) use (&$worstStatus, &$worstStatusRank) { $currentStatus = e_file_inspector::getStatusForValidationCode($value); $currentStatusRank = $this->getStatusRank($currentStatus); if ($currentStatusRank > $worstStatusRank) { $worstStatusRank = $currentStatusRank; $worstStatus = $currentStatus; } }); return $this->glyph['folder_' . $worstStatus]; } private function displayAllowed($validationCode) { if ($this->opt('core') == 'integrity_fail_only' && $validationCode & e_file_inspector::VALIDATED) return false; elseif ($this->opt('core') == 'none' && $validationCode & e_file_inspector::VALIDATED_PATH_VERSION) return false; $status = e_file_inspector::getStatusForValidationCode($validationCode); $return = true; switch ($status) { case 'missing': $return = $this->opt('missing'); break; case 'unknown': $return = $this->opt('noncore'); break; case 'old': $return = $this->opt('oldcore'); break; } return $return; } /** * 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) { if (is_null($key)) { return $array = $value; } $keys = explode('/', $key); while (count($keys) > 1) { $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] = []; } $array = &$array[$key]; } $array[array_shift($keys)] = $value; return $array; } function scan_results() { $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, ] ]; $this->inspect($this->root_dir); array_walk_recursive($this->files, function ($validationCode) { $status = e_file_inspector::getStatusForValidationCode($validationCode); $category = $this->statusToLegacyCountCategory($status); $this->count[$category]['num']++; if ($validationCode & e_file_inspector::VALIDATED_PATH_VERSION && $validationCode & e_file_inspector::VALIDATED_FILE_EXISTS) $this->count['core']['num']++; }); echo "
 
"; if($this->opt('type') == 'tree') { $text = "
"; $text .= ""; $text .= "
".FR_LAN_2."
".$this->generateScanResultsHtml()."
"; } else { $text = "

".FR_LAN_2."

"; } $text .= ""; if($this->opt('type') == 'tree') { $text .= ""; } else { $text .= ""; } if($this->opt('core') != 'none') { $text .= ""; } if($this->opt('missing')) { $text .= ""; } if($this->opt('noncore')) { $text .= ""; } if($this->opt('oldcore')) { $text .= ""; } if($this->opt('core') == 'all') { $text .= ""; } if($this->count['warning']['num']) { $text .= ""; $text .= ""; $text .= ""; $text .= ""; } if($this->opt('integrity') && ($this->opt('core') != 'none')) { $integrity_icon = $this->count['fail']['num'] ? 'integrity_fail.png' : 'integrity_pass.png'; $integrity_text = $this->count['fail']['num'] ? '( '.$this->count['fail']['num'].' '.FR_LAN_19.' )' : '( '.FR_LAN_20.' )'; $text .= ""; $text .= ""; $text .= ""; $text .= ""; $text .= ""; $text .= ""; $text .= ""; $text .= ""; } if($this->opt('type') == 'tree' && !$this->results && $this->opt('regex')) { $text .= ""; } $text .= "
".FR_LAN_3." root_dir))."')\">
".FR_LAN_3."
".$this->iconTag['file_core']." ".FC_LAN_5.": ".($this->count['core']['num'] ? $this->count['core']['num'] : LAN_NONE)."  ".$this->parsesize($this->count['core']['size'], 2)."
".$this->iconTag['file_missing']." ".FC_LAN_13.": ".($this->count['missing']['num'] ? $this->count['missing']['num'] : LAN_NONE)." 
".$this->iconTag['file_unknown']." ".FC_LAN_7.": ".($this->count['unknown']['num'] ? $this->count['unknown']['num'] : LAN_NONE)." ".$this->parsesize($this->count['unknown']['size'], 2)."
".$this->iconTag['file_old']." ".FR_LAN_24.": ".($this->count['deprecated']['num'] ? $this->count['deprecated']['num'] : LAN_NONE)." ".$this->parsesize($this->count['deprecated']['size'], 2)."
".$this->iconTag['file']." ".FR_LAN_6.": ".($this->count['core']['num'] + $this->count['unknown']['num'] + $this->count['deprecated']['num'])." ".$this->parsesize($this->count['core']['size'] + $this->count['unknown']['size'] + $this->count['deprecated']['size'], 2)."
 
".$this->iconTag['warning']." ".FR_LAN_26."
".$this->iconTag['file_warning']." ".FR_LAN_28.": ".($this->count['warning']['num'] ? $this->count['warning']['num'] : LAN_NONE)." ".$this->parsesize($this->count['warning']['size'], 2)."
".FR_LAN_27."
 
".FR_LAN_7." ".$integrity_text."
".$this->iconTag['file_check']." ".FR_LAN_8.": ".($this->count['pass']['num'] ? $this->count['pass']['num'] : LAN_NONE)." ".$this->parsesize($this->count['pass']['size'], 2)."
".$this->iconTag['file_fail']." ".FR_LAN_9.": ".($this->count['fail']['num'] ? $this->count['fail']['num'] : LAN_NONE)." ".$this->parsesize($this->count['fail']['size'], 2)."
".$this->iconTag['file_uncalc']." ".FR_LAN_25.": ".($this->count['uncalculable']['num'] ? $this->count['uncalculable']['num'] : LAN_NONE)." ".$this->parsesize($this->count['uncalculable']['size'], 2)."
 
".$this->iconTag['info']." ".FR_LAN_10.": 

".FR_LAN_23."
"; if($this->opt('type') != 'tree') { $text .= " "; if(!$this->results && $this->opt('regex')) { $text .= ""; } ksort($this->files); foreach ($this->files as $relativePath => $validation) { if (!$this->displayAllowed($validation)) continue; list($icon, $title) = $this->getGlyphForValidationCode($validation); $text .= ''; $text .= ''; } } $text .= ""; $text .= "
".FR_LAN_23."
'; $text .= "$icon "; $text .= htmlspecialchars($relativePath); $text .= ''; $text .= isset($this->fileSizes[$relativePath]) ? $this->parsesize($this->fileSizes[$relativePath]) : ''; $oldVersion = $this->getOldVersionOfPath($relativePath, $validation); $text .= $oldVersion ? " (v$oldVersion)" : ""; $text .= '

"; echo $text; $this->sendProgress($this->totalFiles); self::pruneOldProgressFiles(); } function checksum($filename) { $checksum = md5(str_replace(array(chr(13),chr(10)), "", file_get_contents($filename))); return $checksum; } function parsesize($size, $dec = 0) { $size = $size ? $size : 0; $kb = 1024; $mb = 1024 * $kb; $gb = 1024 * $mb; $tb = 1024 * $gb; if($size < $kb) { return $size." ".CORE_LAN_B; } elseif($size < $mb) { return round($size/$kb)." ".CORE_LAN_KB; } elseif($size < $gb) { return round($size/$mb, $dec)." ".CORE_LAN_MB; } elseif($size < $tb) { return round($size/$gb, $dec)." ".CORE_LAN_GB; } else { return round($size/$tb, $dec)." ".CORE_LAN_TB; } } function regex_match($file) { $file_content = file_get_contents($file); $match = preg_match($_POST['regex'], $file_content); return $match; } function sendProgress($increment=0) { if(empty($this->options['scan'])) { return null; } $this->progress_units = $this->progress_units + $increment; $rand = (int) $this->progress_units; $total = (int) $this->totalFiles; $inc = round(($rand / $total) * 100); if($inc >= 100) { $inc = 100; } if( $this->progressPercentage === $inc) { return null; } $this->progressPercentage = $inc; self::writeScanProgress($this->options['scan'], $this->progressPercentage); return null; } public function exploit_interface() { // global $ns; $ns = e107::getRender(); $query = http_build_query($_POST); $text = " "; $ns->tablerender(FR_LAN_1, $text); } function headerCss() { $pref = e107::getPref(); echo "\n"; $e_js = e107::getJs(); // Core CSS - XXX awaiting for path changes if(!isset($no_core_css) || !$no_core_css) { $e_js->otherCSS('{e_WEB_CSS}e107.css'); } if(!deftrue('e_IFRAME') && isset($pref['admincss']) && $pref['admincss']) { $css_file = file_exists(THEME.'admin_'.$pref['admincss']) ? 'admin_'.$pref['admincss'] : $pref['admincss']; $e_js->themeCSS($css_file); } elseif(isset($pref['themecss']) && $pref['themecss']) { $css_file = file_exists(THEME.'admin_'.$pref['themecss']) ? 'admin_'.$pref['themecss'] : $pref['themecss']; $e_js->themeCSS($css_file); } else { $css_file = file_exists(THEME.'admin_style.css') ? 'admin_style.css' : 'style.css'; $e_js->themeCSS($css_file); } $e_js->renderJs('other_css', false, 'css', false); echo "\n\n"; // Core CSS $e_js->renderJs('core_css', false, 'css', false); echo "\n\n"; // Plugin CSS $e_js->renderJs('plugin_css', false, 'css', false); echo "\n\n"; // Theme CSS //echo "\n"; $e_js->renderJs('theme_css', false, 'css', false); echo "\n\n"; // Inline CSS - not sure if this should stay at all! $e_js->renderJs('inline_css', false, 'css', false); echo "\n\n"; $text = " \n"; echo $text; } /** * Get the PHP-standard version of the hash of the relative path * * @todo FIXME performance: This method checksums old files a second time. * @param string $relativePath Relative path to checksum * @param int $validationCode e_file_inspector validation bits * @return false|string */ private function getOldVersionOfPath($relativePath, $validationCode) { $oldVersion = false; if (($validationCode & e_file_inspector::VALIDATED_HASH_EXISTS) && !($validationCode & e_file_inspector::VALIDATED_HASH_CURRENT)) { $dbChecksums = $this->coreImage->getChecksums($relativePath); $actualChecksum = $this->coreImage->checksumPath(e_BASE . $relativePath); $oldVersion = array_search($actualChecksum, $dbChecksums); } return $oldVersion; } private static function writeScanProgress($scanId, $progress) { self::exitOnEvilScanId($scanId); $tmpDir = sys_get_temp_dir(); $progressPath = $tmpDir . "/" . self::SCAN_ID_PREFIX . $scanId; if ($progress >= 100) unlink($progressPath); else file_put_contents($progressPath, $progress); } public static function readScanProgress($scanId) { self::exitOnEvilScanId($scanId); $tmpDir = sys_get_temp_dir(); $progressPath = $tmpDir . "/" . self::SCAN_ID_PREFIX . $scanId; $result = trim(@file_get_contents($progressPath)); if (!strlen($result)) $result = '100'; return $result; } private static function exitOnEvilScanId($scanId) { if (!preg_match('/^[0-9A-F]+$/i', $scanId)) exit(1); } private static function pruneOldProgressFiles() { $tmpDir = sys_get_temp_dir(); $i = new DirectoryIterator($tmpDir); foreach ($i as $fileInfo) { $candidateFileName = $fileInfo->getFilename(); if (substr($candidateFileName, 0, strlen(self::SCAN_ID_PREFIX)) !== self::SCAN_ID_PREFIX) continue; if ($fileInfo->isFile() && time() - $fileInfo->getMTime() > 300) unlink($fileInfo->getRealPath()); } } } /* function fileinspector_adminmenu() //FIXME - has problems when navigation is on the LEFT instead of the right. { $var['setup']['text'] = FC_LAN_11; $var['setup']['link'] = e_SELF."?mode=setup"; $var['run']['text'] = FR_LAN_2; $var['run']['link'] = e_SELF."?mode=run"; $icon = e107::getParser()->toIcon('e-fileinspector-24'); $caption = $icon."".FC_LAN_1.""; e107::getNav()->admin($caption, $_GET['mode'], $var); }*/ function e_help() { // $fi = new file_inspector; $fi = e107::getSingleton('file_inspector'); $list = $fi->getLegend(); $text = ''; foreach($list as $v) { if(!empty($v[1])) { $text .= "
".$v[0]." ".$v[1]."
"; } } return array('caption'=>FC_LAN_37, 'text'=>$text); } require_once(e_ADMIN.'footer.php'); /* function headerjs() { e107::js('footer', '{e_WEB}/js/core/all.jquery.js', 'jquery', 1); e107::js('footer', '{e_WEB}js/core/front.jquery.js', 'jquery', 1); // Load all default functions. $text = e107::getJs()->renderJs('footer', 1, true, true); $text .= ""; return $text; }*/ ?>