0byt3m1n1
Path:
/
data
/
applications
/
aps
/
b2evolution
/
4.0.5-0
/
standard
/
htdocs
/
inc
/
maintenance
/
model
/
[
Home
]
File: _backup.class.php
<?php /** * This file is part of b2evolution - {@link http://b2evolution.net/} * See also {@link http://sourceforge.net/projects/evocms/}. * * @copyright (c)2009 by Francois PLANQUE - {@link http://fplanque.net/} * Parts of this file are copyright (c)2009 by The Evo Factory - {@link http://www.evofactory.com/}. * * Released under GNU GPL License - {@link http://b2evolution.net/about/license.html} * * {@internal Open Source relicensing agreement: * The Evo Factory grants Francois PLANQUE the right to license * The Evo Factory's contributions to this file and the b2evolution project * under any OSI approved OSS license (http://www.opensource.org/licenses/). * }} * * @package maintenance * * {@internal Below is a list of authors who have contributed to design/coding of this file: }} * @author efy-maxim: Evo Factory / Maxim. * @author fplanque: Francois Planque. * * @version $Id: _backup.class.php,v 1.8.2.1 2010/07/13 13:06:29 fplanque Exp $ */ if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); /** * @var strings base application paths */ global $basepath, $conf_subdir, $skins_subdir, $adminskins_subdir; global $plugins_subdir, $media_subdir, $backup_subdir, $upgrade_subdir; /** * @var array backup paths */ global $backup_paths; /** * @var array backup tables */ global $backup_tables; /** * Backup folder/files default settings * - 'label' checkbox label * - 'note' checkbox note * - 'path' path to folder or file * - 'included' true if folder or file must be in backup * @var array */ $backup_paths = array( 'application_files' => array ( 'label' => T_( 'Application files' ), /* It is files root. Please, don't remove it. */ 'path' => '*', 'included' => true ), 'configuration_files' => array ( 'label' => T_( 'Configuration files' ), 'path' => $conf_subdir, 'included' => true ), 'skins_files' => array ( 'label' => T_( 'Skins' ), 'path' => array( $skins_subdir, $adminskins_subdir ), 'included' => true ), 'plugins_files' => array ( 'label' => T_( 'Plugins' ), 'path' => $plugins_subdir, 'included' => true ), 'media_files' => array ( 'label' => T_( 'Media folder' ), 'path' => $media_subdir, 'included' => false ), 'backup_files' => array ( 'label' => NULL, // Don't display in form. Just exclude from backup. 'path' => $backup_subdir, 'included' => false ), 'upgrade_files' => array ( 'label' => NULL, // Don't display in form. Just exclude from backup. 'path' => $upgrade_subdir, 'included' => false ) ); /** * Backup database tables default settings * - 'label' checkbox label * - 'note' checkbox note * - 'tables' tables list * - 'included' true if database tables must be in backup * @var array */ $backup_tables = array( 'content_tables' => array ( 'label' => T_( 'Content tables' ), /* It means collection of all of the tables. Please, don't remove it. */ 'table' => '*', 'included' => true ), 'logs_stats_tables' => array ( 'label' => T_( 'Logs & stats tables' ), 'table' => array( 'T_sessions', 'T_hitlog', 'T_basedomains', 'T_track__goalhit', 'T_track__keyphrase', ), 'included' => false ) ); /** * Backup class * This class is responsible to backup application files and data. * */ class Backup { /** * All of the paths and their 'included' values defined in backup configuration file * @var array */ var $backup_paths; /** * All of the tables and their 'included' values defined in backup configuration file * @var array */ var $backup_tables; /** * True if pack backup files * @var boolean */ var $pack_backup_files; /** * Constructor */ function Backup() { global $backup_paths, $backup_tables; // Set default settings defined in backup configuration file // Set backup folders/files default settings $this->backup_paths = array(); foreach( $backup_paths as $name => $settings ) { $this->backup_paths[$name] = $settings['included']; } // Set backup tables default settings $this->backup_tables = array(); foreach( $backup_tables as $name => $settings ) { $this->backup_tables[$name] = $settings['included']; } $this->pack_backup_files = true; } /** * Load settings from request */ function load_from_Request() { global $backup_paths, $backup_tables, $Messages; // Load folders/files settings from request foreach( $backup_paths as $name => $settings ) { if( array_key_exists( 'label', $settings ) && !is_null( $settings['label'] ) ) { // We can set param $this->backup_paths[$name] = param( 'bk_'.$name, 'boolean' ); } } // Load tables settings from request foreach( $backup_tables as $name => $settings ) { $this->backup_tables[$name] = param( 'bk_'.$name, 'boolean' ); } $this->pack_backup_files = param( 'bk_pack_backup_files', 'boolean', 0 ); // Check are there something to backup if( !$this->has_included( $this->backup_paths ) && !$this->has_included( $this->backup_tables ) ) { $Messages->add( T_( 'There is nothing to backup. Please select at least one option' ), 'error' ); return false; } return true; } /** * Start backup */ function start_backup() { global $basepath, $backup_path, $servertimenow; // Create current backup path $cbackup_path = $backup_path.date( 'Y-m-d-H-i-s', $servertimenow ).'/'; echo '<p>'.sprintf( T_('Starting backup to: «%s» ...'), $cbackup_path ).'</p>'; flush(); // Prepare backup directory $success = prepare_maintenance_dir( $backup_path, true ); // Backup directories and files if( $success && $this->has_included( $this->backup_paths ) ) { $backup_files_path = $this->pack_backup_files ? $cbackup_path : $cbackup_path.'files/'; // Prepare files backup directory if( $success = prepare_maintenance_dir( $backup_files_path, false ) ) { // We can backup files $success = $this->backup_files( $backup_files_path ); } } // Backup database if( $success && $this->has_included( $this->backup_tables ) ) { $backup_tables_path = $this->pack_backup_files ? $cbackup_path : $cbackup_path.'db/'; // Prepare database backup directory if( $success = prepare_maintenance_dir( $backup_tables_path, false ) ) { // We can backup database $success = $this->backup_database( $backup_tables_path ); } } if( $success ) { echo '<p>'.sprintf( T_('Backup complete. Directory: «%s»'), $cbackup_path ).'</p>'; flush(); return true; } @rmdir_r( $cbackup_path ); return false; } /** * Backup files * @param string backup directory path */ function backup_files( $backup_dirpath ) { global $basepath, $backup_paths, $inc_path; echo '<h4>'.T_( 'Creating folders/files backup...' ).'</h4>'; flush(); // Find included and excluded files $included_files = array(); if( $root_included = $this->backup_paths['application_files'] ) { $included_files = get_filenames( $basepath, true, true, true, false, true, true ); } // Prepare included/excluded paths $excluded_files = array(); foreach( $this->backup_paths as $name => $included ) { foreach( $this->path_to_array( $backup_paths[$name]['path'] ) as $path ) { if( $root_included && !$included ) { $excluded_files[] = $path; } elseif( !$root_included && $included ) { $included_files[] = $path; } } } // Remove excluded list from included list $included_files = array_diff( $included_files, $excluded_files ); if( $this->pack_backup_files ) { // Create ZIPped backup $zip_filepath = $backup_dirpath.'files.zip'; // Pack using 'zlib' extension and PclZip wrapper // Load PclZip class (PHP4): load_class( '_ext/pclzip/pclzip.lib.php', 'PclZip' ); $PclZip = new PclZip( $zip_filepath ); echo sprintf( T_( 'Archiving files to «<strong>%s</strong>»...' ), $zip_filepath ).'<br/>'; flush(); foreach( $included_files as $included_file ) { echo sprintf( T_( 'Backing up «<strong>%s</strong>» ...' ), $basepath.$included_file ).'<br/>'; flush(); $file_list = $PclZip->add( no_trailing_slash( $basepath.$included_file ), PCLZIP_OPT_REMOVE_PATH, no_trailing_slash( $basepath ) ); if ($file_list == 0) { echo '<p style="color:red">'.sprintf( T_( 'Unable to create «%s»' ), $zip_filepath ).'</p>'; flush(); return false; } } } else { // Copy directories and files to backup directory foreach( $included_files as $included_file ) { $this->recurse_copy( no_trailing_slash( $basepath.$included_file ), no_trailing_slash( $backup_dirpath.$included_file ) ); } } return true; } /** * Backup database * * @param string backup directory path */ function backup_database( $backup_dirpath ) { global $DB, $db_config, $backup_tables, $inc_path; echo '<h4>'.T_( 'Creating database backup...' ).'</h4>'; flush(); // Collect all included tables $ready_to_backup = array(); foreach( $this->backup_tables as $name => $included ) { if( $included ) { $tables = aliases_to_tables( $backup_tables[$name]['table'] ); if( is_array( $tables ) ) { $ready_to_backup = array_merge( $ready_to_backup, $tables ); } elseif( $tables == '*' ) { foreach( $DB->get_results( 'SHOW TABLES', ARRAY_N ) as $row ) { $ready_to_backup[] = $row[0]; } } else { $ready_to_backup[] = $tables; } } } // Ensure there are no duplicated tables $ready_to_backup = array_unique( $ready_to_backup ); // Exclude tables foreach( $this->backup_tables as $name => $included ) { if( !$included ) { $tables = aliases_to_tables( $backup_tables[$name]['table'] ); if( is_array( $tables ) ) { $ready_to_backup = array_diff( $ready_to_backup, $tables ); } elseif( $tables != '*' ) { $index = array_search( $tables, $ready_to_backup ); if( $index ) { unset( $ready_to_backup[$index] ); } } } } // Create and save created SQL backup script $backup_sql_filename = 'db.sql'; $backup_sql_filepath = $backup_dirpath.$backup_sql_filename; // Check if backup file exists if( file_exists( $backup_sql_filepath ) ) { // Stop tables backup, because backup file exists echo '<p style="color:red">'.sprintf( T_( 'Unable to write database dump. Database dump already exists: «%s»' ), $backup_sql_filepath ).'</p>'; flush(); return false; } $f = @fopen( $backup_sql_filepath , 'w+' ); if( $f == false ) { // Stop backup, because it can't open backup file for writing echo '<p style="color:red">'.sprintf( T_( 'Unable to write database dump. Could not open «%s» for writing.' ), $backup_sql_filepath ).'</p>'; flush(); return false; } echo sprintf( T_( 'Dumping tables to «<strong>%s</strong>»...' ), $backup_sql_filepath ).'<br/>'; flush(); // Create and save created SQL backup script foreach( $ready_to_backup as $table ) { // progressive display of what backup is doing echo sprintf( T_( 'Backing up table «<strong>%s</strong>» ...' ), $table ).'<br/>'; flush(); $row_table_data = $DB->get_row( 'SHOW CREATE TABLE '.$table, ARRAY_N ); fwrite( $f, $row_table_data[1].";\n\n" ); $values_list = array(); foreach( $DB->get_results( 'SELECT * FROM '.$table, ARRAY_N ) as $row ) { $values = '('; $num_fields = count( $row ); for( $index = 0; $index < $num_fields; $index++ ) { $row[$index] = ereg_replace("\n","\\n", addslashes( $row[$index] ) ); if ( isset($row[$index]) ) { $values .= '\''.$row[$index].'\'' ; } else { $values .= '\'\''; } if ( $index<( $num_fields-1 ) ) { $values .= ','; } } $values_list[] = $values.')'; } if( !empty( $values_list ) ) { fwrite( $f, 'INSERT INTO '.$table.' VALUES '.implode( ',', $values_list ).";\n\n" ); } unset( $values_list ); // Flush the output to a file fflush( $f ); } // Close backup file input stream fclose($f); if( $this->pack_backup_files ) { // Pack created backup SQL script // Pack using 'zlib' extension and PclZip wrapper // Load PclZip class (PHP4): load_class( '_ext/pclzip/pclzip.lib.php', 'PclZip' ); $zip_filepath = $backup_dirpath.'db.zip'; $PclZip = new PclZip( $zip_filepath ); $file_list = $PclZip->add( $backup_dirpath.$backup_sql_filename, PCLZIP_OPT_REMOVE_PATH, no_trailing_slash( $backup_dirpath ) ); if ($file_list == 0) { echo '<p style="color:red">'.sprintf( T_( 'Unable to create «%s»' ), $zip_filepath ).'</p>'; flush(); return false; } unlink( $backup_sql_filepath ); } return true; } /** * Copy directory recursively * @param string source directory * @param string destination directory * @param array excluded directories */ function recurse_copy( $src, $dest, $root = true ) { if( is_dir( $src ) ) { $dir = opendir( $src ); @mkdir( $dest ); while( false !== ( $file = readdir( $dir ) ) ) { if ( ( $file != '.' ) && ( $file != '..' ) ) { $srcfile = $src.'/'.$file; if ( is_dir( $srcfile ) ) { if( $root ) { // progressive display of what backup is doing echo sprintf( T_( 'Backing up «<strong>%s</strong>» ...' ), $srcfile ).'<br/>'; flush(); } $this->recurse_copy( $srcfile, $dest . '/' . $file, false ); } else { // Copy file copy( $srcfile, $dest.'/'. $file ); } } } closedir( $dir ); } else { copy( $src, $dest ); } } /** * Include all of the folders and tables to backup. */ function include_all() { global $backup_paths, $backup_tables; foreach( $backup_paths as $name => $settings ) { if( array_key_exists( 'label', $settings ) && !is_null( $settings['label'] ) ) { $this->backup_paths[$name] = true; } } foreach( $backup_tables as $name => $settings ) { $this->backup_tables[$name] = true; } } /** * Check has data list included directories/files or tables * @param array list * @return boolean */ function has_included( & $data_list ) { foreach( $data_list as $included ) { if( $included ) { return true; } } return false; } /** * Convert path to array * @param mixed path * @return array */ function path_to_array( $path ) { if( is_array( $path ) ) { return $path; } return array( $path ); } } /* * $Log: _backup.class.php,v $ */ ?>