$Date: 2006-03-23 07:34:25 -0500 (Thu, 23 Mar 2006) $
| > $Revision: 177 $
| > $Author: brandon $
+---------------------------------------------------------------------------
|
| > Diagnostics Center
| > Module written by Brandon Farber
| > Date started: 19th April 2006
|
| > Module Version Number: 1.0.0
+--------------------------------------------------------------------------
*/
if ( ! defined( 'IN_ACP' ) )
{
print "
Incorrect access
You cannot access this file directly. If you have recently upgraded, make sure you upgraded 'admin.php'.";
exit();
}
class ad_diagnostics
{
var $base_url;
var $dir_split = "/";
/**
* Section title name
*
* @var string
*/
var $perm_main = "help";
/**
* Section title name
*
* @var string
*/
var $perm_child = "diag";
function auto_run()
{
//-----------------------------------------
// Load skin
//-----------------------------------------
$this->html = $this->ipsclass->acp_load_template( 'cp_skin_diagnostics' );
//-----------------------------------------
// Set default nav
//-----------------------------------------
$this->ipsclass->admin->nav[] = array( $this->ipsclass->form_code, 'Diagnostics' );
if ( strtoupper( substr(PHP_OS, 0, 3) ) === 'WIN' )
{
$this->dir_split = "\\";
}
//-----------------------------------------
switch($this->ipsclass->input['code'])
{
case 'dbindex':
$this->ipsclass->admin->cp_permission_check( $this->perm_main.'|'.$this->perm_child.':do' );
$this->db_index_check();
break;
case 'dbchecker':
$this->ipsclass->admin->cp_permission_check( $this->perm_main.'|'.$this->perm_child.':do' );
$this->db_check();
break;
case 'whitespace':
$this->ipsclass->admin->cp_permission_check( $this->perm_main.'|'.$this->perm_child.':do' );
$this->whitespace_check();
break;
case 'filepermissions':
$this->ipsclass->admin->cp_permission_check( $this->perm_main.'|'.$this->perm_child.':do' );
$this->permissions_check();
break;
case 'fileversions':
$this->ipsclass->admin->cp_permission_check( $this->perm_main.'|'.$this->perm_child.':do' );
$this->version_check();
break;
//-----------------------------------------
default:
$this->ipsclass->admin->cp_permission_check( $this->perm_main.'|'.$this->perm_child.':do' );
$this->list_functions();
break;
}
}
/*-------------------------------------------------------------------------*/
// Version Check
/*-------------------------------------------------------------------------*/
function version_check()
{
$this->ipsclass->admin->page_detail = "Running different version files can produce unexpected results. For example, a version 2.1 file is not compatible with a verison 2.0 file. If any files are listed below in red, it is recommended you upload fresh copies of those files.";
$this->ipsclass->admin->page_title = "IPB Diagnostics";
$this->ipsclass->admin->nav[] = array( '', 'Version Check Results' );
set_time_limit(0);
$dir = preg_replace( "#^(.+?)\/$#", "\\1", ROOT_PATH );
$file_versions = array();
$upgrade_history = array();
$latest_version = array( 'upgrade_version_id' => '' );
$file_versions = $this->version_recur_dir( $dir );
$this->ipsclass->adskin->td_header[] = array( "" , "30%" );
$this->ipsclass->adskin->td_header[] = array( "" , "70%" );
$this->ipsclass->html .= $this->ipsclass->adskin->start_table( "Version Information" );
$this->ipsclass->DB->simple_construct( array( 'select' => '*', 'from' => 'upgrade_history', 'order' => 'upgrade_version_id DESC', 'limit' => array(0, 5) ) );
$this->ipsclass->DB->simple_exec();
while( $r = $this->ipsclass->DB->fetch_row() )
{
if ( $r['upgrade_version_id'] > $latest_version['upgrade_version_id'] )
{
$latest_version = $r;
}
$upgrade_history[] = $r;
}
//-----------------------------------------
// Got real version number?
//-----------------------------------------
if ( $this->ipsclass->version == 'v<{%dyn.down.var.human.version%}>' )
{
$this->ipsclass->version = 'v'.$latest_version['upgrade_version_human'];
}
if ( $this->ipsclass->acpversion == '<{%dyn.down.var.long_version_id%}>' )
{
$this->ipsclass->acpversion = $latest_version['upgrade_version_id'];
}
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( "IPB Version", $this->ipsclass->version.' (ID: '.$this->ipsclass->acpversion.')' ) );
if( !count($upgrade_history) )
{
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( "Upgrade History", 'None Available' ) );
}
else
{
foreach( $upgrade_history as $history_row )
{
$history_row['_date'] = $this->ipsclass->get_date( $history_row['upgrade_date'], 'SHORT' );
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( "Upgrade {$history_row['_date']}", "{$history_row['upgrade_version_human']} ({$history_row['upgrade_version_id']})" ) );
}
}
$this->ipsclass->html .= $this->ipsclass->adskin->end_table();
$this->ipsclass->adskin->td_header[] = array( "File" , "70%" );
$this->ipsclass->adskin->td_header[] = array( "Version" , "30%" );
$this->ipsclass->html .= $this->ipsclass->adskin->start_table( "Version Check Results" );
if( is_array($file_versions) && count($file_versions) )
{
foreach( $file_versions as $file => $version )
{
if( 'v'.$version == $this->ipsclass->version )
{
$version = "";
}
else
{
$version = "";
}
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( $file, $version ) );
}
}
else
{
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( " There was a processing error - we could not read the files" ) );
}
$this->ipsclass->html .= $this->ipsclass->adskin->end_table();
$this->ipsclass->admin->output();
}
/*-------------------------------------------------------------------------*/
// Version check, recursive
/*-------------------------------------------------------------------------*/
function version_recur_dir($dir)
{
$skip_dirs = array( 'jscripts', 'cache', 'ssi_templates', 'style_avatars', 'style_emoticons', 'style_images', 'upgrade', 'uploads', 'images', 'i18n', 'PEAR', 'components_acp',
'components_init', 'components_location', 'components_ucp', 'components_public' );
$skip_files = array( 'conf_global.php', 'conf.php', $this->ipsclass->vars['sql_driver'].'_fulltext.php', $this->ipsclass->vars['sql_driver'].'_tables.php',
$this->ipsclass->vars['sql_driver'].'_inserts.php', $this->ipsclass->vars['sql_driver'].'_install.php' );
$files = array();
$dh = @opendir($dir);
while (false !== ($file = readdir($dh)))
{
if ( preg_match( "#^[_\.]#", $file ) )
{
continue;
}
if ( $file != '.' && $file != '..' )
{
$newpath = $dir.$this->dir_split.$file;
$level = explode( $this->dir_split, $newpath );
if ( is_dir($newpath) && !in_array( $file, $skip_dirs ) && ($newpath.'../' != 'modules') )
{
$files = array_merge( $files, $this->version_recur_dir($newpath) );
}
else
{
if ( strpos( $file, ".php" ) !== false && !is_dir( $newpath ) && !in_array( $file, $skip_files ) )
{
$file = file_get_contents($newpath);
preg_match( "#Invision Power Board v(.+?)\s+?#i", $file, $matches);
$files[$newpath] = isset($matches[1]) ? $matches[1] : '';
}
}
}
}
closedir($dh);
return $files;
}
/*-------------------------------------------------------------------------*/
// Permission Checks
/*-------------------------------------------------------------------------*/
function permissions_check()
{
$this->ipsclass->admin->page_detail = "Certain files and directories must have the proper permissions set on them in order for IPB to properly write data to your disk. On Windows, you should ensure the files have \"Read/Write\" permissions, while on Unix/Linux you should ensure the files are \"CHMOD 777\".";
$this->ipsclass->admin->page_title = "IPB Diagnostics";
$this->ipsclass->admin->nav[] = array( '', 'Permission Check Results' );
$checkdirs = array( 'style_images', 'style_emoticons', 'cache', 'cache'.$this->dir_split.'skin_cache', 'cache'.$this->dir_split.'lang_cache', 'uploads' );
$langfiles = array( 'lang_boards', 'lang_buddy', 'lang_calendar', 'lang_emails', 'lang_email_content', 'lang_error',
'lang_forum', 'lang_global', 'lang_help', 'lang_legends', 'lang_login', 'lang_mlist',
'lang_mod', 'lang_msg', 'lang_online', 'lang_portal', 'lang_post', 'lang_printpage',
'lang_profile', 'lang_register', 'lang_search', 'lang_stats', 'lang_subscriptions',
'lang_topic', 'lang_ucp', 'lang_chatpara' , 'lang_editors', 'lang_chatsigma',
'acp_lang_acpperms', 'acp_lang_member', 'acp_lang_portal', 'lang_tar'
);
$root_dir = preg_replace( "#^(.+?)\/$#", "\\1".$this->dir_split, ROOT_PATH );
//-----------------------------------------
// Get language directories
//-----------------------------------------
$this->ipsclass->init_load_cache( array( 'languages' ) );
if( is_array( $this->ipsclass->cache['languages'] ) && count( $this->ipsclass->cache['languages'] ) )
{
foreach( $this->ipsclass->cache['languages'] as $v )
{
$checkdirs[] = 'cache'.$this->dir_split.'lang_cache'.$this->dir_split.$v['ldir'];
foreach( $langfiles as $filename )
{
$checkdirs[] = 'cache'.$this->dir_split.'lang_cache'.$this->dir_split.$v['ldir'].$this->dir_split.$filename.'.php';
}
}
}
else
{
$this->ipsclass->DB->build_query( array( 'select' => 'ldir', 'from' => 'languages' ) );
$this->ipsclass->DB->exec_query();
while( $v = $this->ipsclass->DB->fetch_row() )
{
$checkdirs[] = 'cache'.$this->dir_split.'lang_cache'.$this->dir_split.$v['ldir'];
foreach( $langfiles as $filename )
{
$checkdirs[] = 'cache'.$this->dir_split.'lang_cache'.$this->dir_split.$v['ldir'].$this->dir_split.$filename.'.php';
}
}
}
//-----------------------------------------
// Get emoticon directories
//-----------------------------------------
if( is_array( $this->ipsclass->cache['emoticons'] ) && count( $this->ipsclass->cache['emoticons'] ) )
{
foreach( $this->ipsclass->cache['emoticons'] as $v )
{
$checkdirs[] = 'style_emoticons'.$this->dir_split.$v['emo_set'];
}
}
else
{
$this->ipsclass->DB->build_query( array( 'select' => 'emo_set', 'from' => 'emoticons' ) );
$this->ipsclass->DB->exec_query();
while( $v = $this->ipsclass->DB->fetch_row() )
{
$checkdirs[] = 'style_emoticons'.$this->dir_split.$v['emo_set'];
}
}
//-----------------------------------------
// Get skin directories
//-----------------------------------------
$skin_dirs = array();
if( is_array( $this->ipsclass->cache['skin_id_cache'] ) && count( $this->ipsclass->cache['skin_id_cache'] ) )
{
foreach( $this->ipsclass->cache['skin_id_cache'] as $k => $v )
{
if( $k == 1 && !IN_DEV )
{
continue;
}
$checkdirs[] = 'cache'.$this->dir_split.'skin_cache'.$this->dir_split.'cacheid_'.$v['set_skin_set_id'];
$skin_dirs[] = $v['set_skin_set_id'];
}
}
else
{
$this->ipsclass->DB->build_query( array( 'select' => 'set_skin_set_id', 'from' => 'skin_sets' ) );
$this->ipsclass->DB->exec_query();
while( $v = $this->ipsclass->DB->fetch_row() )
{
$checkdirs[] = 'cache'.$this->dir_split.'skin_cache'.$this->dir_split.'cacheid_'.$v['set_skin_set_id '];
$skin_dirs[] = $v['set_skin_set_id'];
}
}
//-----------------------------------------
// Get skin files
//-----------------------------------------
$this->ipsclass->DB->load_cache_file( ROOT_PATH.'sources/sql/'.SQL_DRIVER.'_extra_queries.php', 'sql_extra_queries' );
$this->ipsclass->DB->cache_add_query( 'diag_distinct_skins', array(), 'sql_extra_queries' );
$this->ipsclass->DB->cache_exec_query();
while( $v = $this->ipsclass->DB->fetch_row() )
{
foreach( $skin_dirs as $dir )
{
$checkdirs[] = 'cache'.$this->dir_split.'skin_cache'.$this->dir_split.'cacheid_'.$dir.$this->dir_split.$v['group_name'].'.php';
}
}
set_time_limit(0);
$checkdirs = array_unique($checkdirs);
$output = array();
foreach( $checkdirs as $dir_to_check )
{
if( !file_exists( $root_dir.$dir_to_check ) )
{
# Could be skin files from custom skins for components they don't own
# or they could be using safe_mode skins
# Make sure skin_cache still shows up though...
if( !strpos( $dir_to_check, 'skin_' ) OR !strpos( $dir_to_check, '.php' ) )
{
$output[] = "";
}
}
else if( !is_writeable( $root_dir.$dir_to_check ) )
{
$output[] = "";
}
else if( is_writeable( $root_dir.$dir_to_check ) )
{
$output[] = "";
}
}
$this->ipsclass->html .= $this->ipsclass->adskin->start_table( "Permissions Check Results" );
if( is_array($output) && count($output) )
{
foreach( $output as $html_row )
{
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( $html_row ) );
}
}
else
{
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( "We did not find any files or folders to check. Oooops." ) );
}
$this->ipsclass->html .= $this->ipsclass->adskin->end_table();
$this->ipsclass->admin->output();
}
/*-------------------------------------------------------------------------*/
// WHITE SPACE CHECK
/*-------------------------------------------------------------------------*/
function whitespace_check()
{
$this->ipsclass->admin->page_detail = "If there is any whitespace before or after the php tags in files used by IPB, it can result in blank pages or malformed html. If any results are returned you should open those files and delete the extra spaces or line breaks at the beginning and/or end of the file.";
$this->ipsclass->admin->page_title = "IPB Diagnostics";
$this->ipsclass->admin->nav[] = array( '', 'Whitespace Check Results' );
set_time_limit(0);
$dir = preg_replace( "#^(.+?)\/$#", "\\1", ROOT_PATH );
$files_with_junk = array();
$files_with_junk = $this->recur_dir( $dir );
$this->ipsclass->html .= $this->ipsclass->adskin->start_table( "Whitespace Check Results" );
if( is_array($files_with_junk) && count($files_with_junk) )
{
foreach( $files_with_junk as $html_row )
{
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( $html_row." has whitespace at the beginning or end of the file" ) );
}
}
else
{
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( " All files appear to be in good order" ) );
}
$this->ipsclass->html .= $this->ipsclass->adskin->end_table();
$this->ipsclass->admin->output();
}
function recur_dir($dir)
{
$skip_dirs = array( 'uploads', 'style_images', 'gallery_setup', 'blog_setup', 'style_emoticons', 'style_avatars',
'jscripts', 'clientscripts', 'images', 'acp_js_skin' );
$files = array();
$dh = @opendir($dir);
while (false !== ($file = readdir($dh)))
{
if ( preg_match( "#^[_\.]#", $file ) )
{
continue;
}
if ( $file != '.' && $file != '..' )
{
$newpath = $dir.$this->dir_split.$file;
$level = explode( $this->dir_split, $newpath );
if ( is_dir($newpath) && !in_array( $file, $skip_dirs ) )
{
$files = array_merge( $files, $this->recur_dir($newpath) );
}
else
{
if ( strpos( $file, ".php" ) !== false && !is_dir( $newpath ) )
{
$file = file_get_contents($newpath);
$current_length = strlen($file);
$file = trim($file);
$actual_length = strlen($file);
if ( $current_length != $actual_length )
{
$files[] = $newpath;
}
}
}
}
}
closedir($dh);
return $files;
}
/*-------------------------------------------------------------------------*/
// CHECK DB INDEXES
/*-------------------------------------------------------------------------*/
function db_index_check()
{
$this->ipsclass->admin->page_detail = "Database indexes help your database engine work more efficiently with the data it hosts. If any of the indexes are missing, it can cause your site to run slower than it should. Please use the appropriate links or queries to fix any indexes reported missing below.";
$this->ipsclass->admin->page_title = "IPB Diagnostics";
$this->ipsclass->admin->nav[] = array( '', 'Database Index Results' );
//-----------------------------------------
// Fixing something?
//-----------------------------------------
$queries_to_run = array();
foreach( $this->ipsclass->input as $k => $v )
{
if( preg_match( "/^query(\d+)$/", $k, $matches ) )
{
$queries_to_run[] = $v;
}
}
if( isset($this->ipsclass->input['query']) AND $this->ipsclass->input['query'] )
{
$queries_to_run[] = $this->ipsclass->input['query'];
}
if( count($queries_to_run) > 0 )
{
foreach( $queries_to_run as $the_query )
{
$sql = trim( urldecode( base64_decode($the_query) ) );
if ( preg_match( "/^(DROP|FLUSH)/i", trim($sql) ) )
{
$this->ipsclass->main_msg = "Sorry, those queries are not allowed for your safety";
continue;
}
else if ( preg_match( "/^(?!SELECT)/i", preg_replace( "#\s{1,}#s", "", $sql ) ) and preg_match( "/admin_login_logs/i", preg_replace( "#\s{1,}#s", "", $sql ) ) )
{
$this->ipsclass->main_msg = "Sorry, those queries are not allowed for your safety. Please use the 'Fix Manually' option for this query.";
continue;
}
else
{
$this->ipsclass->DB->return_die = 1;
$this->ipsclass->DB->query($sql,1);
if( $this->ipsclass->DB->error != "" )
{
$this->ipsclass->main_msg .= "SQL Error
{$this->ipsclass->DB->error}
";
}
else
{
$this->ipsclass->main_msg .= "Query: ".htmlspecialchars($sql)."
Executed Successfully
";
}
$this->ipsclass->DB->error = "";
$this->ipsclass->DB->failed = 0;
}
}
}
//-----------------------------------------
// Get current table definitions
//-----------------------------------------
if( !file_exists( ROOT_PATH."/install/sql/{$this->ipsclass->vars['sql_driver']}_tables.php" ) )
{
$this->ipsclass->admin->error( "You must upload /install/sql/{$this->ipsclass->vars['sql_driver']}_tables.php from the IPB installation package for your current version to run this tool" );
}
//require ROOT_PATH."sources/action_admin/sql_{$this->ipsclass->vars['sql_driver']}.php";
require_once( KERNEL_PATH . 'db_lib/' . strtolower($this->ipsclass->vars['sql_driver']) . '_tools.php' );
require_once( ROOT_PATH . 'install/sql/' . strtolower($this->ipsclass->vars['sql_driver']) . '_tables.php' );
$db_tools = new db_tools( $this->ipsclass );
$output = array();
if ( !$output = $db_tools->db_index_diag( $TABLE ) )
{
$this->ipsclass->admin->error( "There was an error and we could not process your " . strtolower($this->ipsclass->vars['sql_driver']) . "_tables.php file." );
}
if( $output['error_count'] > 0 )
{
$this->ipsclass->adskin->td_header[] = array( "{none}" , "50%" );
$this->ipsclass->adskin->td_header[] = array( "{none}" , "50%" );
$this->ipsclass->html .= $this->html->dbindexer_javascript();
$this->ipsclass->html .= $this->ipsclass->adskin->start_table( "WARNING: ERRORS FOUND" );
$this->ipsclass->html .= $this->ipsclass->adskin->add_td_row( array( array( "