Вход Регистрация
Файл: IPBMafia.ru_IPB_3.4.6_Final_Rus _Nulled/board/upload/admin/sources/classes/backup.php
Строк: 357
<?php
/**
 * <pre>
 * Invision Power Services
 * IP.Board v3.4.6
 * Back Up Model
 * Last Updated: $Date: 2012-05-10 21:10:13 +0100 (Thu, 10 May 2012) $
 * </pre>
 *
 * @author         Matt Mecham
 * @copyright    (c) 2001 - 2009 Invision Power Services, Inc.
 * @license        http://www.invisionpower.com/company/standards.php#license
 * @package        IP.Board
 * @link        http://www.invisionpower.com
 * @since        Tue. 15th June 2012
 * @version        $Rev: 10721 $
 *
 */

/**
 * Back up model
 * @author matt
 *
 */
class ipsBackup
{
    
/**
     * Holds the back-up variables
     * @var array
     */
    
private $Vars       = array();
    
    
/**
     * DB tables and primary keys
     * @var array
     */
    
private $Keys        = array();
    
/**
     * Contains list of tables NOT to gather.
     * @var array
     */
    
private $BlackList = array();
    
    
/**
     * Contains list of tables ONLY to gather.
     * @var array
     */
    
private $WhiteList = array();
    
    
/**
     * Contains all the schematic info. Use wisely, it can be 'uuuge (700k+)
     */
    
private $SchematicData = array();
    
    
/**
     * Limits for the batches
     * @var array
     */
    
private $Limits        = array( 'rows' => 0, 'bytes' => 0 );
    
    
/**
     * Construct
     */
    
public function __construct()
    {
        
/* Make objects */
        
$this->registry = ipsRegistry::instance();
        
$this->DB       = $this->registry->DB();
        
        
/* Fetch *lists */
        
$this->BlackList = $this->_getBlackList();
        
$this->Whitelist = $this->_getWhiteList();
        
        
/* Fetch data variables */
        
$this->Vars         = $this->_getVars();
        
        
/* Fetch db table pkeys */
        
$this->Keys      = $this->_getKeys();
        
        
/* Set default limits for the batch pulling */
        
$this->setLimits( 'rows', 10000 );
        
$this->setLimits( 'bytes', 20 * 1024 * 1024 );
    }
    
    
/**
     * Add an insert/delete/update/replace query to our log
     * @param string $query
     * @param string $table
     */
    
public function addRawQueryToLog( $query, $table )
    {
        
/* This would be LOLs */
        
if ( $this->backUpRunning() && ! stristr( 'insert into ' . $this->registry->dbFunctions()->getPrefix() . 'backup_queue', $query ) )
        {
            
$this->DB->insert( 'backup_queue', array( 'queue_entry_date'  => IPS_UNIX_TIME_NOW,
                                                      
'queue_entry_type'  => 5,
                                                      
'queue_entry_table' => $this->_stripPrefix( $table ),
                                                      
'queue_entry_sql'   => $query ) );
        }
    }
    
    
/**
     * Is the back up system ready to process queries?
     *
     */
    
public function backUpRunning()
    {
        return ( 
$this->Vars['populate_all_done'] > 0 ) ? true : false;
    }

    
    
/**
     * Does it need to reset?
     *
     */
    
public function checkForRestart()
    {
        
/* Eventually we'll expand the system so it can be pinged to see if a restart is needed but for now... */
        
return ( ! $this->Vars['populate_all_done'] ) ? true : false;
    }
    
    
/**
     * Send batch to the backup server
     */
    
public function sendBatch()
    {
        
/* Fetch kernel class */
        
require_once( IPS_KERNEL_PATH . 'classFileManagement.php' );
        
$cfm = new classFileManagement();
        
        
/* Fetch DB data */
        
$tables        = $this->_getDatabaseSchematics();
        
$sqlRows       = array();
        
$touchedTables = array();
        
$bytesUsed     = '';
        
$topId           = 0;
        
$delIds           = array();
        
        
/* Do we need to restart? */
        
if ( $this->checkForRestart() )
        {
            
$this->populateLogWithAllTables();
            
            return 
true;
        }
        
        
/* Little short cut */
        
$p = $this->registry->dbFunctions()->getPrefix();
        
        
/* Start looping on the table */
        
$this->DB->build( array( 'select' => '*',
                                 
'from'   => 'backup_queue',
                                 
'order'  => 'queue_id',
                                 
'limit'  => array( 0, $this->Limits['rows'] ) ) );
        
        
$o = $this->DB->execute();
        
        while( 
$row = $this->DB->fetch( $o ) )
        {
            
$tbl    = $this->_stripPrefix( $row['queue_entry_table'] );
            
$sql    = '';
            
$fields = array();
            
            
$touchedTables[ $tbl ] = $tbl;
            
            if ( 
$row['queue_entry_sql'] )
            {
                
$sql = $row['queue_entry_sql'];
            }
            else
            {
                
/* Get fields */
                
foreach( $tables[ $row['queue_entry_table'] ]['cols'] as $col )
                {
                    
$fields[] = $col['Field'];
                }
                
                if ( ! 
count( $fields ) )
                {
                    
/* Empty - so remove this queue row or we'll never progress */
                    
$delIds[] = $row['queue_id'];
                    
                    continue;
                }
                
                
/* INSERT */
                
if ( $row['queue_entry_type'] == 1 )
                {
                    
/* Get data */
                    
$pKey    = $row['queue_entry_key'];
                    
$pKeyVal = ( $this->_isConcat( $pKey ) ) ? addslashes( $row['queue_entry_value'] ) : $row['queue_entry_value'];
                    
$data    = array();
                    
$vals    = array();
                    
                    
$data    = $this->DB->buildAndFetch( array( 'select' => '`' . implode( "`, `", $fields ) . '`',
                                                                
'from'   => $tbl,
                                                                
'where'  => $pKey . "='" . $pKeyVal . "'" ) );
                    
                    if ( ! 
is_array( $data ) OR ! count( $data ) )
                    {
                        
/* Empty - so remove this queue row or we'll never progress */
                        
$delIds[] = $row['queue_id'];
                        
                        continue;
                    }
                    
                    foreach( 
$data as $k => $v )
                    {
                        
$vals[] = $this->_makeValueSafeForQuery( $v );
                    }
                    
                    
$sql  = "INSERT INTO " . $p . $tbl . "(`" . implode( "`, `", $fields ). "`) " .
                            
"VALUES( '" . implode( "', '", $vals ) . "');";
                }
            }
            
            
/* Got anything? */
            
if ( ! $sql )
            {
                
/* Empty - so remove this queue row or we'll never progress */
                
$delIds[] = $row['queue_id'];
                    
                continue;
            }
            
            
/* check size */
            
$bytesUsed += IPSLib::strlenToBytes( strlen( $sql ) );
            
            
/* Truth time! */
            
if ( $bytesUsed >= $this->Limits['bytes'] )
            {
                break;
            }
            else
            {
                
$sqlRows[] = $sql;
                
                
/* top id to remove */
                
$topId = $row['queue_id'];
            }
        }
        
        
/* Anything to delete? */
        
if ( count( $delIds ) )
        {
            
$this->DB->delete( 'backup_queue', 'queue_id IN (' . implode( ',', array_values( $delIds ) ) . ')' );
        }
        
        
/* What do we have? */
        
if ( $topId && count( $sqlRows ) )
        {
            
$dataToSend = $this->_createTextToSend( $sqlRows, array_keys( $touchedTables ) );
                                    
            
$returnedData = $cfm->postFileContents( $this->_getBackupServerUrl(), array( 'backup_data' => @gzcompress( $dataToSend ), 'lkey' => ipsRegistry::$settings['ipb_reg_number'] ) );
                
            
$test = json_decode( trim( $returnedData ), true );
            
            if ( 
is_array( $test ) && $test['status'] == 'ok' )
            {
                
$this->DB->delete( 'backup_queue', 'queue_id <= ' . intval( $topId ) );
                
$this->_addLog( intval( $test['rows'] ), $test['status'] );
                
                
$this->Vars['rows_sent']  = intval( $this->Vars['rows_sent'] ) + count( $sqlRows );
                
$this->Vars['rows_total'] = $this->_getStoredRowCount();
                
$this->_setVars();
            }
            else
            {
                
# Fail lol
                
$this->_addLog( 0, $test['status'] );
            }
        }
    }
    
    
/**
     * Do the first run
     * This will reset the system and re-populate the entire log table - USE WITH CAUTION!
     */
    
public function populateLogWithAllTables( $tablesToIndex=300 )
    {
        
$lastTable = $this->Vars['populate_all_last_table'];
        
$lastProc  = '';
        
        
/* Reset the system if not middle of processing */
        
if ( ! $lastTable )
        {
            
$this->_resetSystem();
        }
            
        
/* Little short cut */
        
$p = $this->registry->dbFunctions()->getPrefix();
        
        
/* Lets go */
        
foreach( $this->Keys as $table => $pKey )
        {
            
/* Seek to the first unindexed table */
            
if ( ! $lastProc )
            {
                if ( 
$lastTable and $table != $lastTable )
                {
                    continue;
                }
                
                if ( ( 
$lastTable == $table ) || ! $lastTable )
                {
                    
$lastProc = $table;
                }
            }
            
            
$this->DB->allow_sub_select = 1;
            
            
$pKeyText = ( $this->_isConcat( $pKey ) ) ? addslashes( $pKey ) : $pKey;
            
            
/* Fetch, then */
            
$this->DB->query( 'INSERT INTO ' . $p . 'backup_queue (queue_entry_date, queue_entry_type, queue_entry_table, queue_entry_key, queue_entry_value, queue_entry_sql)' .
                              
"( SELECT UNIX_TIMESTAMP(), 1, '" . $table . "', '" . $pKeyText . "', " . $pKey . ", '' FROM " . $table . " )" );
            
            
$this->Vars['populate_all_last_table'] = $table;
            
$this->_setVars();
        }
        
        
/* We are all done */
        
if ( ( $lastTable && $lastProc == $this->Vars['populate_all_last_table'] ) OR ! $lastProc OR ( $tablesToIndex >= count( $this->Keys ) ) )
        {
            
$this->Vars['rows_sent']               = 0;
            
$this->Vars['rows_total']               = $this->_getStoredRowCount();
            
$this->Vars['populate_all_done']       = IPS_UNIX_TIME_NOW;
            
$this->Vars['populate_all_last_table'] = '';
            
$this->_setVars();
        }
    }
    
    
/**
     * Ok to fetch the table data?
     * @param string $table
     */
    
public function isOkToGetThisTableData( $table )
    {
        
$table = $this->_stripPrefix( $table );
        
        if ( 
count( $this->Whitelist ) )
        {
            if ( 
in_array( $table, $this->Whitelist ) )
            {
                return 
true;
            }
        }
        
        return ( 
$this->_isBlackListTable( $table ) ) ? false : true;
    }
    
    
/**
     * Rebuilds the cache file so we can find out a little about the database structure
     */
    
public function rebuildPrimaryKeyCacheFile()
    {
        
$cache     = array();
        
$schematic = $this->_getDatabaseSchematics();
        
        foreach( 
$schematic as $table => $data )
        {
            
$hasKey = false;
            
            if ( 
count( $data['idx'] ) )
            {
                foreach( 
$data['idx'] as $idx )
                {
                    if ( 
$idx['Key_name'] == 'PRIMARY' )
                    {
                        
$cache[ $table ] = $idx['Column_name'];
                        
$hasKey = true;
                        break;
                    }
                }
            }
            
            if ( ! 
$hasKey )
            {
                
/* Lets make a key */
                
$c      = 0;
                
$concat = array();
                
                foreach( 
$data['cols'] as $col )
                {
                    if ( 
strtolower( $col['Type'] ) != 'mediumtext' )
                    {
                        if ( 
stristr( strtolower( $col['Type'] ), 'int(' ) )
                        {
                            
$concat[] = $col['Field'];
                        }
                        else
                        {
                            
$concat[] = 'SUBSTR(' . $col['Field'] . ', 1, 32)';
                        }
                        
                        
$c++;
                    }
                    
                    if ( 
$c > 5 )
                    {
                        break;
                    }
                }
                
                
$cache[ $table ] = 'CONCAT_WS( ',', ' . implode( ',', $concat ) . ' )';
            }
        }
        
        
$contents = '<' . "?phpn" . '$keyCache = ' . var_export( $cache, true ) . ';' . "n?" . '>';
        
        if ( ! 
file_put_contents( $this->_getBackUpKeyCacheFilename(), $contents ) )
        {
            
trigger_error( 'Не удалось записать файл кэша системы резервного копирования' );
        }
        
        
/* Reset table pkeys */
        
$this->Keys = $this->_getKeys();
    }
    
    
/**
     * Set a per batch limit
     * @param string $key
     * @param string $value
     */
    
public function setLimits( $key, $value )
    {
        switch( 
$key )
        {
            case 
'row':
            case 
'pergo':
            case 
'rows':
                
$this->Limits['rows'] = $value;
            break;
            case 
'bytes':
            case 
'b':
                
$this->Limits['bytes'] = $value;
            break;
            case 
'kb':
                
$this->Limits['bytes'] = $value * 1024;
            break;
            case 
'mb':
                
$this->Limits['bytes'] = $value * 1024 * 1024;
            break;
        }
    }
    
    
/**
     * Get the number of rows in the queue table
     * @return int, yo
     */
    
private function _getStoredRowCount()
    {
        
$count = $this->DB->buildAndFetch( array( 'select' => 'count(*) as tnuoc', 'from' => 'backup_queue' ) );
        
        return 
$count['tnuoc'];
    }
    
    
/**
     * Resets the system and preps for re-logging all
     */
    
private function _resetSystem()
    {
        
/* Reset */
        
$this->Vars['populate_all_start']      = IPS_UNIX_TIME_NOW;
        
$this->Vars['populate_all_done']       = 0;
        
$this->Vars['populate_all_last_table'] = '';
    
        
$this->_setVars();
        
        
/* Delete current logs */
        
$this->DB->delete('backup_queue');
        
$this->DB->delete('backup_log');
        
        
/* Rebuild cache file */
        
$this->rebuildPrimaryKeyCacheFile();
    }
    
    
/**
     * Gets the database keys
     * @return array
     */
    
private function _getKeys()
    {
        
$keyCache = array();
    
        if ( ! 
is_file( $this->_getBackUpKeyCacheFilename() ) )
        {
            
$this->rebuildPrimaryKeyCacheFile();
        }
    
        include( 
$this->_getBackUpKeyCacheFilename() );
        
        return 
$keyCache;
    }
    
    
/**
     * Gets the vars from the deebee
     * @return array:
     */
    
private function _getVars()
    {
        
$vars = array();
        
        
$db = $this->DB->buildAndFetchAll( array( 'select' => '*',
                                                  
'from'   => 'backup_vars' ) );
        
        if ( 
is_array( $db ) )
        {
            foreach( 
$db as $var )
            {
                
$vars[ $var['backup_var_key'] ] = $var['backup_var_value'];
            }
        }

        if( !isset(
$vars['populate_all_done']) )
        {
            
$vars['populate_all_done']    = 0;
        }

        return 
$vars;
    }
    
    
/**
     * Update the variables 
     */
    
private function _setVars()
    {
        foreach( 
$this->Vars as $k => $v )
        {
            
$this->DB->replace( 'backup_vars',array( 'backup_var_key' => $k, 'backup_var_value' => $v ), array( 'backup_var_key' ) );
        }
    }
    
    
/**
     * Removes table prefix if one exists
     * @param string $table
     * @return string
     */
    
private function _stripPrefix( $table )
    {
        if ( 
$this->registry->dbFunctions()->getPrefix() && preg_match( "/^" . $this->registry->dbFunctions()->getPrefix() ."/i", $table ) )
        {
            
$table = preg_replace( "/^" . $this->registry->dbFunctions()->getPrefix() ."(.*)$/i", '1', $table );
        }
        
        return 
$table;
    }
    
    
/**
     * Returns ignored tables
     */
    
private function _getWhiteList()
    {
        return array();
    }
    
    
/**
     * Returns ignored tables
     */
    
private function _getBlackList()
    {
        
/* @todo abstract this puppy */
        
return array( 'admin_login_logs',
                      
'admin_logs',
                      
'api_log',
                      
'backup_log',
                      
'backup_queue',
                      
'backup_vars',
                      
'blog_askimet_logs',
                      
'blog_trackback_spamlogs',
                      
'blog_views',
                      
'chat_log_archive',
                      
'content_cache_posts',
                      
'content_cache_sigs',
                      
'core_editor_autosave',
                      
'core_item_markers',
                      
'core_like_cache',
                      
'core_share_links_caches',
                      
'core_share_links_log',
                      
'core_tags_cache',
                      
'error_logs',
                      
'gallery_image_views',
                      
'mail_error_logs',
                      
'moderator_logs',
                      
'profile_friends_flood',
                      
'profile_portal_views',
                      
'reputation_cache',
                      
'search_sessions',
                      
'sessions',
                      
'skin_cache',
                      
'skin_templates_cache',
                      
'spam_service_log',
                      
'spider_logs',
                      
'task_logs',
                      
'topic_views' );
    }
    
/**
     * Return database schematic information
     */
    
private function _getDatabaseSchematics()
    {
        if ( 
count( $this->SchematicData ) )
        {
            return 
$this->SchematicData;
        }
        
        
$this->DB->query( "SHOW TABLE STATUS FROM `" . $this->registry->dbFunctions()->getDatabaseName() . "`" );
        
        
/* Loop through the results */
        
$this->SchematicData = array();
        
        while( 
$row = $this->DB->fetch() )
        {
            
/* Check to ensure it's a table for this install... */
            
if ( $this->registry->dbFunctions()->getPrefix() && ! preg_match( "/^" . $this->registry->dbFunctions()->getPrefix() ."/i", $row['Name'] ) )
            {
                continue;
            }
            
            if ( ! 
$this->isOkToGetThisTableData( $row['Name'] ) )
            {
                continue;
            }        
            
            
/* Add to output array */
            
$this->SchematicData[ $row['Name'] ] = array( 'cols' => array(), 'idx' => array(), 'data' => $row );
        }
        
        
/* Now fetch table information */
        
foreach( $this->SchematicData as $name => $data )
        {
            
/* Fetch data */
            
$this->DB->query( "DESCRIBE " . $name );
            
            while( 
$row = $this->DB->fetch() )
            {
                
$this->SchematicData[ $name ]['cols'][] = $row;
            }
            
            
/* Fetch index data */
            
$this->DB->query( "SHOW INDEX FROM `" . $this->registry->dbFunctions()->getDatabaseName() . "`.`" . $name . "`" );
            
            while( 
$row = $this->DB->fetch() )
            {
                
$this->SchematicData[ $name ]['idx'][] = $row;
            }
        }
        
        return 
$this->SchematicData;
    }
    
    
/**
     * Check to see if this is an ignored table
     * @param string $table
     */
    
private function _isBlackListTable( $table )
    {
        return ( 
in_array( $table, $this->BlackList ) ) ? true : false;
    }
    
    
/**
     * Add slashes to single quotes to stop sql breaks
     *
     * @param    string    $value    String to add slashes too
     * @return    string
     */
    
private function _makeValueSafeForQuery( $value )
    {
        return 
$this->DB->addSlashes( $value );
    }
    
    
/**
     * @param string $str
     * @return boolean
     */
    
private function _isConcat( $str )
    {
        return ( 
substr( $str, 0, 10 ) == 'CONCAT_WS(' ) ? true : false;
    }
    
    
/**
     * Creates the post text
     * @param string $sqlData
     */
    
private function _createTextToSend( $sqlData, $touchedTables=null )
    {
        
$tables       = $this->_getDatabaseSchematics();
        
$tblsToSend   = array();
        
$tblsToCreate = array();
        
$schematic    = '';
        
        
/* Little short cut */
        
$p = $this->registry->dbFunctions()->getPrefix();
        
        if ( 
is_array( $touchedTables ) )
        {
            foreach( 
$touchedTables as $tbl )
            {
                
/* $touchedTables has no prefix */
                
$tblsToSend[ $p . $tbl ] = $tables[ $p . $tbl ];
                
                
$this->DB->query( "SHOW CREATE TABLE " . $p . $tbl );
                
$_f = $this->DB->fetch();
                
                
$tblsToCreate[] = str_replace( array( "n", "r" ), "n", $_f['Create Table'] );
            }
        }
        
        
$document = serialize( array( 'tableData' => $tblsToSend, 'createTables' => $tblsToCreate, 'sql' => $sqlData, 'vars' => $this->Vars ) );
        
        return 
$document;
    }
    
    
/**
     * Should be face-smashingly obvious.
     * @return string
     */
    
private function _getBackUpKeyCacheFilename()
    {
        return 
IPS_CACHE_PATH . 'cache/backUpKeyCache.php';
    }
    
    
/**
     * Gets the backup server URL (clearly)
     * @return string
     */
    
private function _getBackupServerUrl()
    {
        return 
'http://gateway.backuptest.lw.ipslink.com/index.php';
    }
    
    
/**
     * Adds a log to the back up system
     * @param int $rows
     * @param string $status
     */
    
private function _addLog( $rows, $status )
    {
        
$this->DB->insert( 'backup_log', array( 'log_row_count' => $rows, 'log_result' => $status ) );
    }
}
Онлайн: 1
Реклама