debug = FALSE;
require_once(e_HANDLER.'form_handler.php');
$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');
$rs = new form;
set_time_limit(18000);
$e_sub_cat = 'fileinspector';
if(isset($_GET['scan']))
{
session_write_close();
while (@ob_end_clean());
header("Content-type: text/html; charset=".CHARSET, true);
$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;
echo "
Results
".$fi->headerCss()." ".headerjs()."
\n";
// echo "
loading..";
// echo "..";
//flush();
$_POST = $_GET;
if($_GET['exploit'])
{
$fi->exploit();
}
else
{
$fi->scan_results();
}
echo "";
exit();
}
else
{
$fi = new file_inspector;
require_once('auth.php');
if (e_QUERY) {
// $fi -> snapshot_interface();
} else if (isset($_POST['scan'])) {
$fi->exploit_interface();
$fi->scan_config();
} else {
$fi->scan_config();
}
}
class file_inspector {
var $root_dir;
var $files = array();
var $parent;
var $count = array();
var $results = 0;
var $totalFiles = 0;
var $coredir = array();
var $progress_units = 0;
function file_inspector()
{
global $e107,$core_image;
//$this->totalFiles = count($core_image,COUNT_RECURSIVE);
$this->countFiles($core_image);
$this -> root_dir = $e107 -> file_path;
if (substr($this -> root_dir, -1) == '/') {
$this -> root_dir = substr($this -> root_dir, 0, -1);
}
if ($_POST['core'] == 'fail') {
$_POST['integrity'] = TRUE;
}
if (MAGIC_QUOTES_GPC && $_POST['regex']) {
$_POST['regex'] = stripslashes($_POST['regex']);
}
if ($_POST['regex']) {
if ($_POST['core'] == 'fail') {
$_POST['core'] = 'all';
}
$_POST['missing'] = 0;
$_POST['integrity'] = 0;
}
}
// Find the Total number of core files before scanning begins.
function countFiles($array)
{
foreach($array as $k=>$val)
{
if(is_array($val))
{
$this->countFiles($val);
}
elseif($val)
{
$this->totalFiles++;
}
}
}
function scan_config() {
global $ns, $rs, $pref;
$text = "";
$ns -> tablerender(FC_LAN_1, $text);
}
function scan($dir, $image)
{
$handle = opendir($dir.'/');
while (false !== ($readdir = readdir($handle)))
{
if ($readdir != '.' && $readdir != '..' && $readdir != '/' && $readdir != 'CVS' && $readdir != 'Thumbs.db' && (strpos('._', $readdir) === FALSE))
{
$path = $dir.'/'.$readdir;
if (is_dir($path))
{
$dirs[$path] = $readdir;
}
elseif (!isset($image[$readdir]))
{
$files[$readdir] = $this -> checksum($path, TRUE);
}
}
}
closedir($handle);
if (isset($dirs)) {
ksort ($dirs);
foreach ($dirs as $dir_path => $dir_list) {
$list[$dir_list] = ($set = $this -> scan($dir_path, $image[$dir_list])) ? $set : array();
}
}
if (isset($files)) {
ksort ($files);
foreach ($files as $file_name => $file_list) {
$list[$file_name] = $file_list;
}
}
return $list;
}
// Given a full path and filename, looks it up in the list to determine valid actions; returns:
// 'check' - file is expected to be present, and validity is to be checked
// 'ignore' - file may or may not be present - check its validity if found, but not an error if missing
// 'uncalc' - file must be present, but its integrity cannot be checked.
// 'nocalc' - file may be present, but its integrity cannot be checked. Not an error if missing
function check_action($dir, $name)
{
global $coredir;
if ($name == 'e_inspect.php') { return 'nocalc'; } // Special case for plugin integrity checking
$filename = $dir.'/'.$name;
$admin_dir = $this->root_dir.'/'.$coredir['admin'].'/';
$image_dir = $this->root_dir.'/'.$coredir['images'].'/';
$test_list = array();
// Files that are unable to be checked
$test_list[$admin_dir.'core_image.php'] = 'uncalc';
$test_list[$this->root_dir.'/e107_config.php'] = 'uncalc';
// Files that are likely to be renamed by user
$test_list[$admin_dir.'filetypes_.php'] = 'ignore';
$test_list[$this->root_dir.'/e107.htaccess'] = 'ignore';
$test_list[$this->root_dir.'/e107.robots.txt'] = 'ignore';
if (isset($test_list[$filename])) { return $test_list[$filename]; }
return 'check';
}
// This function does the real work
// $list -
// $deprecated
// $level
// $dir
// &$tree_end
// &$parent_expand
function inspect($list, $deprecated, $level, $dir, &$tree_end, &$parent_expand)
{
global $coredir,$lng;
$langs = explode(",",e_LANLIST);
$lang_short = array();
foreach($langs as $k=>$val)
{
if($val == "English") // Core release language.
{
unset($langs[$k]);
continue;
}
$lang_short[] = $lng->convert($val);
}
unset ($childOut);
$parent_expand = false;
if (substr($dir, -1) == '/')
{
$dir = substr($dir, 0, -1);
}
$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++;
// print_a($list);
$this->sendProgress($this->count['core']['num'],$this->totalFiles,FR_LAN_1);
foreach ($list as $key => $value)
{
$this -> parent = $dir_id;
if (is_array($value))
{ // Entry is a subdirectory - recurse another level
$path = $dir.'/'.$key;
$child_open = false;
$child_end = true;
$sub_text .= $this -> inspect($value, $deprecated[$key], $level, $path, $child_end, $child_expand);
$tree_end = false;
if ($child_expand)
{
$parent_expand = true;
$last_expand = true;
}
}
else
{
$this->sendProgress($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;
if (($this -> files[$dir_id][$fid]['size'] = filesize($path)) !== FALSE)
{ // We're checking a file here
if ($_POST['core'] != 'none')
{ // Look at core files
$this -> count['core']['num']++;
$this -> count['core']['size'] += $this -> files[$dir_id][$fid]['size'];
if ($_POST['regex'])
{ // Developer prefs activated - search file contents according to regex
$file_content = file($path); // Get contents of file
if (($this -> files[$dir_id][$fid]['size'] = filesize($path)) !== FALSE)
{
if ($this -> files[$dir_id][$fid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content))
{ // Search string found - add file to list
$this -> files[$dir_id][$fid]['file'] = ($_POST['type'] == 'tree') ? $key : $path;
$this -> files[$dir_id][$fid]['icon'] = 'file_core.png';
$dir_icon = 'fileinspector.png';
$parent_expand = TRUE;
$this -> results++;
}
else
{ // Search string not found - discard from list
unset($this -> files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
$dir_icon = ($dir_icon == 'fileinspector.png') ? $dir_icon : 'folder.png';
}
}
}
else
{
if ($_POST['integrity'])
{ // Actually check file 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.png';
$dir_icon = 'folder_fail.png';
$parent_expand = TRUE;
}
else
{
$this -> count['pass']['num']++;
$this -> count['pass']['size'] += $this -> files[$dir_id][$fid]['size'];
if ($_POST['core'] != 'fail')
{
$this -> files[$dir_id][$fid]['icon'] = 'file_check.png';
$dir_icon = ($dir_icon == 'folder_fail.png' || $dir_icon == 'folder_missing.png') ? $dir_icon : 'folder_check.png';
}
else
{
unset($this -> files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
}
}
break;
case 'uncalc' :
case 'nocalc' :
$this -> count['uncalculable']['num']++;
$this -> count['uncalculable']['size'] += $this -> files[$dir_id][$fid]['size'];
if ($_POST['core'] != 'fail')
{
$this -> files[$dir_id][$fid]['icon'] = 'file_uncalc.png';
}
else
{
unset($this -> files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
}
break;
}
}
else
{ // Just identify as core file
$this -> files[$dir_id][$fid]['icon'] = 'file_core.png';
}
}
}
else
{
unset ($this -> files[$dir_id][$fid]);
$known[$dir_id][$fid] = true;
}
}
else if ($_POST['missing'])
{
switch ($this_action = $this->check_action($dir,$key))
{
case 'check' :
case 'uncalc' :
$this -> count['missing']['num']++;
$this -> files[$dir_id][$fid]['icon'] = 'file_missing.png';
$dir_icon = ($dir_icon == 'folder_fail.png') ? $dir_icon : 'folder_missing.png';
$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;
}
}
else
{
unset ($this -> files[$dir_id][$fid]);
}
}
}
if ($_POST['noncore'] || $_POST['oldcore'])
{
$handle = opendir($dir.'/');
while (is_resource($handle) && false !== ($readdir = readdir($handle)))
{
$prog_count = $this->count['unknown']['num'] + $this->count['deprecated']['num'];
$this->sendProgress($prog_count,$this->totalFiles,FR_LAN_1);
if ($readdir != '.' && $readdir != '..' && $readdir != '/' && $readdir != '.svn' && $readdir != 'CVS' && $readdir != 'Thumbs.db' && (strpos('._', $readdir) === FALSE))
{
if (is_dir($dir.'/'.$readdir))
{
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;
}
}
}
else
{
if($_POST['nolang']) // Hide Non-core Languages.
{
// PHP Lang files.
$lreg = "/[\/_](".implode("|",$langs).")/";
if(preg_match($lreg, $dir.'/'.$readdir))
{
continue;
}
// TinyMce Lang files.
$lregs = "/[\/_](".implode("|",$lang_short).")_dlg\.js/";
if(preg_match($lregs, $dir.'/'.$readdir))
{
continue;
}
// PhpMailer Lang Files.
$lregsm = "/[\/_]phpmailer\.lang-(".implode("|",$lang_short).")\.php/";
if(preg_match($lregsm, $dir.'/'.$readdir))
{
continue;
}
}
$aid = strtolower($readdir);
if (!isset($this -> files[$dir_id][$aid]['file']) && !$known[$dir_id][$aid]) {
if (strpos($dir.'/'.$readdir, 'htmlarea') === false) {
if (isset($deprecated[$readdir])) {
if ($_POST['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.png';
$this -> count['deprecated']['num']++;
$this -> count['deprecated']['size'] += $this -> files[$dir_id][$aid]['size'];
}
} else {
if ($_POST['noncore']) {
$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_unknown.png';
$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.png';
$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.png';
$parent_expand = TRUE;
}
if ($_POST['regex']) {
$file_content = file($dir.'/'.$readdir);
if ($this -> files[$dir_id][$aid]['lines'] = preg_grep("#".$_POST['regex']."#".$_POST['mod'], $file_content)) {
$dir_icon = 'fileinspector.png';
$parent_expand = TRUE;
$this -> results++;
} else {
unset($this -> files[$dir_id][$aid]);
$dir_icon = ($dir_icon == 'fileinspector.png') ? $dir_icon : 'folder.png';
}
} else {
if (isset($deprecated[$readdir])) {
if ($_POST['oldcore']) {
$dir_icon = ($dir_icon == 'folder_warning.png' || $dir_icon == 'folder_fail.png' || $dir_icon == 'folder_missing.png' || $dir_icon == 'folder_old_dir.png') ? $dir_icon : 'folder_old.png';
$parent_expand = TRUE;
}
} else {
if ($_POST['noncore']) {
$dir_icon = ($dir_icon == 'folder_warning.png' || $dir_icon == 'folder_fail.png' || $dir_icon == 'folder_missing.png' || $dir_icon == 'folder_old.png' || $dir_icon == 'folder_old_dir.png') ? $dir_icon : 'folder_unknown.png';
$parent_expand = TRUE;
}
}
}
} else if ($_POST['core'] == 'none') {
unset($this -> files[$dir_id][$aid]);
}
}
}
}
closedir($handle);
}
$this->sendProgress($this->count['core']['num'],$this->totalFiles,FR_LAN_1);
$dir_icon = $dir_icon ? $dir_icon : 'folder.png';
$icon = "";
$hide = ($last_expand && $dir_icon != 'folder_core.png') ? "" : "style='display: none'";
$text = "";
$text .= $tree_end ? "
" : "
";
$text .= "
".$icon." ".$directory."";
$text .= $tree_end ? "" : "
".$sub_text."
";
$text .= "
";
$this -> files[$dir_id]['.']['icon'] = $dir_icon;
return $text;
}
function scan_results()
{
global $ns, $rs, $core_image, $deprecated_image;
$scan_text = $this -> inspect($core_image, $deprecated_image, 0, $this -> root_dir);
$this->sendProgress($this->totalFiles,$this->totalFiles,' ');
echo "
";
if ($_POST['type'] == 'tree') {
$text = "
".FR_LAN_2." |
";
$text .= " | |
";
$text .= "