temp = array(); $this->run = array(); } /** * * This starts or restarts the job working * * @param string $start_type Start types are 'runnow', 'runnowalt', 'cronrun', 'runext', 'runcli' * @param array|int $job_settings The id of job or the settings of a job to start */ private function create( $start_type, $job_settings = 0 ) { global $wpdb; /* @var wpdb $wpdb */ //check startype if ( ! in_array( $start_type, array( 'runnow', 'runnowalt', 'cronrun', 'runext', 'runcli' ) ) ) return; if ( is_int( $job_settings ) ) $this->job = BackWPup_Option::get_job( $job_settings ); elseif( is_array( $job_settings ) ) $this->job = $job_settings; else return; $this->start_time = current_time( 'timestamp' ); $this->lastmsg = __( 'Starting job', 'backwpup' ); //set Logfile $this->logfile = get_site_option( 'backwpup_cfg_logfolder' ) . 'backwpup_log_' . BackWPup::get_plugin_data( 'hash' ) . '_' . date_i18n( 'Y-m-d_H-i-s' ) . '.html'; //write settings to job if ( ! empty( $this->job[ 'jobid' ] ) ) { BackWPup_Option::update( $this->job[ 'jobid' ], 'lastrun', $this->start_time ); BackWPup_Option::update( $this->job[ 'jobid' ], 'logfile', $this->logfile ); //Set current logfile BackWPup_Option::update( $this->job[ 'jobid' ], 'lastbackupdownloadurl', '' ); } //Set needed job values $this->timestamp_last_update = microtime( TRUE ); $this->exclude_from_backup = explode( ',', trim( $this->job[ 'fileexclude' ] ) ); $this->exclude_from_backup = array_unique( $this->exclude_from_backup ); //create path to remove $this->remove_path = trailingslashit( str_replace( '\\', '/', realpath( ABSPATH ) ) ); if ( $this->remove_path == '/' ) $this->remove_path = ''; //setup job steps $this->steps_data[ 'CREATE' ][ 'CALLBACK' ] = ''; $this->steps_data[ 'CREATE' ][ 'NAME' ] = __( 'Job Start', 'backwpup' ); $this->steps_data[ 'CREATE' ][ 'STEP_TRY' ] = 0; //ADD Job types file /* @var $job_type_class BackWPup_JobTypes */ $job_need_dest = FALSE; if ( $job_types = BackWPup::get_job_types() ) { foreach ( $job_types as $id => $job_type_class ) { if ( in_array( $id, $this->job[ 'type' ] ) && $job_type_class->creates_file( ) ) { $this->steps_todo[ ] = 'JOB_' . $id; $this->steps_data[ 'JOB_' . $id ][ 'NAME' ] = $job_type_class->info[ 'description' ]; $this->steps_data[ 'JOB_' . $id ][ 'STEP_TRY' ] = 0; $this->steps_data[ 'JOB_' . $id ][ 'SAVE_STEP_TRY' ] = 0; $job_need_dest = TRUE; } } } //add destinations and create archive if a job where files to backup if ( $job_need_dest ) { //Create manifest file $this->steps_todo[ ] = 'CREATE_MANIFEST'; $this->steps_data[ 'CREATE_MANIFEST' ][ 'NAME' ] = __( 'Creates manifest file', 'backwpup' ); $this->steps_data[ 'CREATE_MANIFEST' ][ 'STEP_TRY' ] = 0; $this->steps_data[ 'CREATE_MANIFEST' ][ 'SAVE_STEP_TRY' ] = 0; //Add archive creation and backup filename on backup type archive if ( $this->job[ 'backuptype' ] == 'archive' ) { //get Backup folder if destination folder set if ( in_array( 'FOLDER', $this->job[ 'destinations' ] ) ) { $this->backup_folder = $this->job[ 'backupdir' ]; //check backup folder if ( ! empty( $this->backup_folder ) ) self::check_folder( $this->backup_folder, TRUE ); } //set temp folder to backup folder if not set because we need one if ( ! $this->backup_folder || $this->backup_folder == '/' ) $this->backup_folder = BackWPup::get_plugin_data( 'TEMP' ); //Create backup archive full file name $this->backup_file = $this->generate_filename( $this->job[ 'archivename' ], $this->job[ 'archiveformat' ] ); //add archive create $this->steps_todo[ ] = 'CREATE_ARCHIVE'; $this->steps_data[ 'CREATE_ARCHIVE' ][ 'NAME' ] = __( 'Creates archive', 'backwpup' ); $this->steps_data[ 'CREATE_ARCHIVE' ][ 'STEP_TRY' ] = 0; $this->steps_data[ 'CREATE_ARCHIVE' ][ 'SAVE_STEP_TRY' ] = 0; } //ADD Destinations /* @var BackWPup_Destinations $dest_class */ foreach ( BackWPup::get_registered_destinations() as $id => $dest ) { if ( ! in_array( $id, $this->job[ 'destinations' ] ) || empty( $dest[ 'class' ] ) ) continue; $dest_class = BackWPup::get_destination( $id ); if ( $dest_class->can_run( $this ) ) { if ( $this->job[ 'backuptype' ] == 'sync' ) { if ( $dest[ 'can_sync' ] ) { $this->steps_todo[] = 'DEST_SYNC_' . $id; $this->steps_data[ 'DEST_SYNC_' . $id ][ 'NAME' ] = $dest[ 'info' ][ 'description' ]; $this->steps_data[ 'DEST_SYNC_' . $id ][ 'STEP_TRY' ] = 0; $this->steps_data[ 'DEST_SYNC_' . $id ][ 'SAVE_STEP_TRY' ] = 0; } } else { $this->steps_todo[] = 'DEST_' . $id; $this->steps_data[ 'DEST_' . $id ][ 'NAME' ] = $dest[ 'info' ][ 'description' ]; $this->steps_data[ 'DEST_' . $id ][ 'STEP_TRY' ] = 0; $this->steps_data[ 'DEST_' . $id ][ 'SAVE_STEP_TRY' ] = 0; } } } } //ADD Job type no file if ( $job_types = BackWPup::get_job_types() ) { foreach ( $job_types as $id => $job_type_class ) { if ( in_array( $id, $this->job[ 'type' ] ) && ! $job_type_class->creates_file() ) { $this->steps_todo[ ] = 'JOB_' . $id; $this->steps_data[ 'JOB_' . $id ][ 'NAME' ] = $job_type_class->info[ 'description' ]; $this->steps_data[ 'JOB_' . $id ][ 'STEP_TRY' ] = 0; $this->steps_data[ 'JOB_' . $id ][ 'SAVE_STEP_TRY' ] = 0; } } } $this->steps_todo[] = 'END'; $this->steps_data[ 'END' ][ 'NAME' ] = __( 'End of Job', 'backwpup' ); $this->steps_data[ 'END' ][ 'STEP_TRY' ] = 1; //must write working data $this->write_running_file(); //create log file $head = ''; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . sprintf( __( 'BackWPup log for %1$s from %2$s at %3$s', 'backwpup' ), $this->job[ 'name' ], date_i18n( get_option( 'date_format' ) ), date_i18n( get_option( 'time_format' ) ) ) . "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= str_pad( '', 100 ) . PHP_EOL; $head .= str_pad( '', 100 ) . PHP_EOL; if ( ! empty( $this->job[ 'jobid' ] ) ) $head .= "job[ 'jobid' ] . "\" />" . PHP_EOL; $head .= "job[ 'name' ] ) . "\" />" . PHP_EOL; $head .= "job[ 'type' ] ) . "\" />" . PHP_EOL; $head .= str_pad( '', 100 ) . PHP_EOL; $head .= str_pad( '', 100 ) . PHP_EOL; $head .= "" . PHP_EOL; $head .= "" . PHP_EOL; $head .= sprintf( _x( '[INFO] %1$s version %2$s; A project of Inpsyde GmbH', 'Plugin name; Plugin Version','backwpup' ), BackWPup::get_plugin_data( 'name' ) , BackWPup::get_plugin_data( 'Version' ) ) . '
' . PHP_EOL; $head .= sprintf( _x( '[INFO] WordPress version %s', 'WordPress Version', 'backwpup' ), BackWPup::get_plugin_data( 'wp_version' ) ). '
' . PHP_EOL; $head .= sprintf( __( '[INFO] Blog url: %s', 'backwpup' ), esc_attr( site_url( '/' ) ) ). '
' . PHP_EOL; $head .= sprintf( __( '[INFO] BackWPup job: %1$s; %2$s', 'backwpup' ), esc_attr( $this->job[ 'name' ] ) , implode( '+', $this->job[ 'type' ] ) ) . '
' . PHP_EOL; if ( $this->job[ 'activetype' ] == 'wpcron' ) { //check next run $cron_next = wp_next_scheduled( 'backwpup_cron', array( 'id' => $this->job[ 'jobid' ] ) ); if ( ! $cron_next || $cron_next < time() ) { wp_unschedule_event( $cron_next, 'backwpup_cron', array( 'id' => $this->job[ 'jobid' ] ) ); $cron_next = BackWPup_Cron::cron_next( $this->job[ 'cron' ] ); wp_schedule_single_event( $cron_next, 'backwpup_cron', array( 'id' => $this->job[ 'jobid' ] ) ); $cron_next = wp_next_scheduled( 'backwpup_cron', array( 'id' => $this->job[ 'jobid' ] ) ); } //output scheduling if ( ! $cron_next ) $cron_next = __( 'Not scheduled!', 'backwpup' ); else $cron_next = date_i18n( 'D, j M Y @ H:i', $cron_next + ( get_option( 'gmt_offset' ) * 3600 ) , TRUE ) ; $head .= sprintf( __( '[INFO] BackWPup cron: %s; Next: %s ', 'backwpup' ), $this->job[ 'cron' ] , $cron_next ) . '
' . PHP_EOL; } elseif ( $this->job[ 'activetype' ] == 'link' ) $head .= __( '[INFO] BackWPup job start with link is active', 'backwpup' ) . '
' . PHP_EOL; else $head .= __( '[INFO] BackWPup no automatic job start configured', 'backwpup' ) . '
' . PHP_EOL; if ( $start_type == 'cronrun' ) $head .= __( '[INFO] BackWPup job started from wp-cron', 'backwpup' ) . '
' . PHP_EOL; elseif ( $start_type == 'runnow' or $start_type == 'runnowalt' ) $head .= __( '[INFO] BackWPup job started manually', 'backwpup' ) . '
' . PHP_EOL; elseif ( $start_type == 'runext' ) $head .= __( '[INFO] BackWPup job started from external url', 'backwpup' ) . '
' . PHP_EOL; elseif ( $start_type == 'runcli' ) $head .= __( '[INFO] BackWPup job started form commandline interface', 'backwpup' ) . '
' . PHP_EOL; $bit = ''; if ( PHP_INT_SIZE === 4 ) $bit = ' (32bit)'; if ( PHP_INT_SIZE === 8 ) $bit = ' (64bit)'; $head .= __( '[INFO] PHP ver.:', 'backwpup' ) . ' ' . PHP_VERSION . $bit .'; ' . PHP_SAPI . '; ' . PHP_OS . '
' . PHP_EOL; $head .= sprintf( __( '[INFO] Maximum PHP script execution time is %1$d seconds', 'backwpup' ), ini_get( 'max_execution_time' ) ) . '
' . PHP_EOL; if ( php_sapi_name() != 'cli' ) { $job_max_execution_time = get_site_option( 'backwpup_cfg_jobmaxexecutiontime' ); if ( ! empty( $job_max_execution_time ) ) { $head .= sprintf( __( '[INFO] Script restart time is configured to %1$d seconds', 'backwpup' ), $job_max_execution_time ) . '
' . PHP_EOL; } } $head .= sprintf( __( '[INFO] MySQL ver.: %s', 'backwpup' ), $wpdb->get_var( "SELECT VERSION() AS version" ) ) . '
' . PHP_EOL; if ( isset( $_SERVER[ 'SERVER_SOFTWARE' ] ) ) $head .= sprintf( __( '[INFO] Web Server: %s', 'backwpup' ), $_SERVER[ 'SERVER_SOFTWARE' ] ) . '
' . PHP_EOL; if ( function_exists( 'curl_init' ) ) { $curlversion = curl_version(); $head .= sprintf( __( '[INFO] curl ver.: %1$s; %2$s', 'backwpup' ), $curlversion[ 'version' ], $curlversion[ 'ssl_version' ] ) . '
' . PHP_EOL; } $head .= sprintf( __( '[INFO] Temp folder is: %s', 'backwpup' ), BackWPup::get_plugin_data( 'TEMP' ) ) . '
' . PHP_EOL; $head .= sprintf( __( '[INFO] Logfile is: %s', 'backwpup' ), $this->logfile ) . '
' . PHP_EOL; $head .= sprintf( __( '[INFO] Backup type is: %s', 'backwpup' ), $this->job[ 'backuptype' ] ) . '
' . PHP_EOL; if ( ! empty( $this->backup_file ) && $this->job[ 'backuptype' ] == 'archive' ) $head .= sprintf( __( '[INFO] Backup file is: %s', 'backwpup' ), $this->backup_folder . $this->backup_file ) . '
' . PHP_EOL; file_put_contents( $this->logfile, $head, FILE_APPEND ); //output info on cli if ( php_sapi_name() == 'cli' && defined( 'STDOUT' ) ) fwrite( STDOUT, strip_tags( $head ) ) ; //test for destinations if ( $job_need_dest ) { $desttest = FALSE; foreach ( $this->steps_todo as $deststeptest ) { if ( substr( $deststeptest, 0, 5 ) == 'DEST_' ) { $desttest = TRUE; break; } } if ( ! $desttest ) $this->log( __( 'No destination correctly defined for backup! Please correct job settings.', 'backwpup' ), E_USER_ERROR ); } //Set start as done $this->steps_done[] = 'CREATE'; } /** * * Get a url to run a job of BackWPup * * @param string $starttype Start types are 'runnow', 'runnowlink', 'cronrun', 'runext', 'restart', 'test' * @param int $jobid The id of job to start else 0 * @return array|object [url] is the job url [header] for auth header or object form wp_remote_get() */ public static function get_jobrun_url( $starttype, $jobid = 0 ) { $wp_admin_user = get_users( array( 'role' => 'backwpup_admin', 'number' => 1 ) ); //get a user for cookie auth $url = site_url( 'wp-cron.php' ); $header = array(); $authurl = ''; $query_args = array( '_nonce' => substr( wp_hash( wp_nonce_tick() . 'backwpup_job_run-' . $starttype, 'nonce' ), - 12, 10 ), 'doing_wp_cron' => sprintf( '%.22F', microtime( true ) ) ); if ( in_array( $starttype, array( 'restart', 'runnow', 'cronrun', 'runext', 'test' ) ) ) $query_args[ 'backwpup_run' ] = $starttype; if ( in_array( $starttype, array( 'runnowlink', 'runnow', 'cronrun', 'runext' ) ) && ! empty( $jobid ) ) $query_args[ 'jobid' ] = $jobid; if ( get_site_option( 'backwpup_cfg_httpauthuser' ) && get_site_option( 'backwpup_cfg_httpauthpassword' ) ) { $header[ 'Authorization' ] = 'Basic ' . base64_encode( get_site_option( 'backwpup_cfg_httpauthuser' ) . ':' . BackWPup_Encryption::decrypt( get_site_option( 'backwpup_cfg_httpauthpassword' ) ) ); $authurl = get_site_option( 'backwpup_cfg_httpauthuser' ) . ':' . BackWPup_Encryption::decrypt( get_site_option( 'backwpup_cfg_httpauthpassword' ) ) . '@'; } if ( $starttype == 'runext' ) { $query_args[ '_nonce' ] = get_site_option( 'backwpup_cfg_jobrunauthkey' ); $query_args[ 'doing_wp_cron' ] = NULL; if ( ! empty( $authurl ) ) { $url = str_replace( 'https://', 'https://' . $authurl, $url ); $url = str_replace( 'http://', 'http://' . $authurl, $url ); } } if ( $starttype == 'runnowlink' && ( ! defined( 'ALTERNATE_WP_CRON' ) || ! ALTERNATE_WP_CRON ) ) { $url = wp_nonce_url( network_admin_url( 'admin.php' ), 'backwpup_job_run-' . $starttype ); $query_args[ 'page' ] = 'backwpupjobs'; $query_args[ 'action' ] = 'runnow'; $query_args[ 'doing_wp_cron' ] = NULL; unset( $query_args[ '_nonce' ] ); } if ( $starttype == 'runnowlink' && defined( 'ALTERNATE_WP_CRON' ) && ALTERNATE_WP_CRON ) { $query_args[ 'backwpup_run' ] = 'runnowalt'; $query_args[ '_nonce' ] = substr( wp_hash( wp_nonce_tick() . 'backwpup_job_run-runnowalt', 'nonce' ), - 12, 10 ); $query_args[ 'doing_wp_cron' ] = NULL; } //Extra for WP-Cron control if ( class_exists( 'WP_Cron_Control' ) && ( $starttype == 'runext' || $starttype == 'runnow' || $starttype == 'restart' ) ) { $wp_cron_control_settings = get_option( 'wpcroncontrol_settings', array() ); if ( empty( $wp_cron_control_settings[ 'secret_string' ] ) && file_exists( WP_PLUGIN_DIR . '/wp-cron-control/wp-cron-control.php' ) ) { $wp_cron_control_settings[ 'secret_string' ] = md5( realpath( WP_PLUGIN_DIR . '/wp-cron-control/wp-cron-control.php' ) . get_current_blog_id() ); $wp_cron_control_settings[ 'enable' ] = 1; } if ( isset( $wp_cron_control_settings[ 'enable' ] ) && $wp_cron_control_settings[ 'enable' ] == 1 ) { if ( defined( 'WP_CRON_CONTROL_SECRET' ) ) { $wp_cron_control_settings[ 'secret_string' ] = WP_CRON_CONTROL_SECRET; } $query_args[ $wp_cron_control_settings[ 'secret_string' ] ] = ''; $query_args[ 'doing_wp_cron' ] = NULL; } } $cron_request = apply_filters( 'cron_request', array( 'url' => add_query_arg( $query_args, $url ), 'key' => $query_args[ 'doing_wp_cron' ], 'args' => array( 'blocking' => FALSE, 'sslverify' => apply_filters( 'https_local_ssl_verify', true ), 'timeout' => 0.01, 'headers' => $header, 'cookies' => array( new WP_Http_Cookie( array( 'name' => AUTH_COOKIE, 'value' => wp_generate_auth_cookie( $wp_admin_user[ 0 ]->ID, time() + 300, 'auth' ) ) ), new WP_Http_Cookie( array( 'name' => LOGGED_IN_COOKIE, 'value' => wp_generate_auth_cookie( $wp_admin_user[ 0 ]->ID, time() + 300, 'logged_in' ) ) ) ), 'user-agent' => BackWpup::get_plugin_data( 'User-Agent' ) ) ) ); if( $starttype == 'test' ) { $cron_request[ 'args' ][ 'timeout' ] = 15; $cron_request[ 'args' ][ 'blocking' ] = TRUE; } if ( ! in_array( $starttype, array( 'runnowlink', 'runext' ) ) ) { set_transient( 'doing_cron', $query_args[ 'doing_wp_cron' ] ); return wp_remote_post( $cron_request['url'], $cron_request['args'] ); } return $cron_request; } /** * */ public static function start_http( $starttype ) { //load text domain if needed if ( ! is_textdomain_loaded( 'backwpup' ) && ! get_site_option( 'backwpup_cfg_jobnotranslate') ) load_plugin_textdomain( 'backwpup', FALSE, BackWPup::get_plugin_data( 'BaseName' ) . '/languages' ); if ( $starttype != 'restart' ) { //check get vars if ( isset( $_GET[ 'jobid' ] ) ) $jobid = (int)$_GET[ 'jobid' ]; else $jobid = 0; //check job id exists if ( $jobid != BackWPup_Option::get( $jobid, 'jobid' ) ) die( '-1' ); //check folders if ( ! self::check_folder( get_site_option( 'backwpup_cfg_logfolder' ) ) || ! self::check_folder( BackWPup::get_plugin_data( 'TEMP' ), TRUE ) ) die( '-2' ); } // redirect if ( $starttype == 'runnowalt' ) { ob_start(); wp_redirect( add_query_arg( array( 'page' => 'backwpupjobs' ), network_admin_url( 'admin.php' ) ) ); echo ' '; while ( @ob_end_flush() ); flush(); } // Should be preventing doubled running job's on http requests $random = rand( 1, 9 ) * 100000; usleep( $random ); //check running job $backwpup_job_object = self::get_working_data(); //start class if ( ! $backwpup_job_object && in_array( $starttype, array( 'runnow', 'runnowalt', 'runext' ) ) && ! empty( $jobid ) ) { //schedule restart event wp_schedule_single_event( time() + 60, 'backwpup_cron', array( 'id' => 'restart' ) ); //start job $backwpup_job_object = new self(); $backwpup_job_object->create( $starttype, (int)$jobid ); } if( is_object( $backwpup_job_object ) && $backwpup_job_object instanceof BackWPup_Job ) $backwpup_job_object->run(); } /** * @param $jobid */ public static function start_cli( $jobid ) { if ( php_sapi_name() != 'cli' ) return; //define DOING_CRON to prevent caching if( ! defined( 'DOING_CRON' ) ) define( 'DOING_CRON', TRUE ); //load text domain if needed if ( ! is_textdomain_loaded( 'backwpup' ) && ! get_site_option( 'backwpup_cfg_jobnotranslate') ) load_plugin_textdomain( 'backwpup', FALSE, BackWPup::get_plugin_data( 'BaseName' ) . '/languages' ); //check job id exists $jobids = BackWPup_Option::get_job_ids(); if ( ! in_array( $jobid, $jobids ) ) die( __( 'Wrong BackWPup JobID', 'backwpup' ) ); //check folders if ( ! self::check_folder( get_site_option( 'backwpup_cfg_logfolder' ) ) ) die( __( 'Log folder does not exist or is not writable for BackWPup', 'backwpup' ) ); if ( ! self::check_folder( BackWPup::get_plugin_data( 'TEMP' ), TRUE ) ) die( __( 'Temp folder does not exist or is not writable for BackWPup', 'backwpup' ) ); //check running job if ( file_exists( BackWPup::get_plugin_data( 'running_file' ) ) ) die( __( 'A BackWPup job is already running', 'backwpup' ) ); //start/restart class fwrite( STDOUT, __( 'Job started', 'backwpup' ) . PHP_EOL ); fwrite( STDOUT, '----------------------------------------------------------------------' . PHP_EOL ); $backwpup_job_object = new self(); $backwpup_job_object->create( 'runcli', (int)$jobid ); $backwpup_job_object->run(); } /** * @param int $jobid */ public static function start_wp_cron( $jobid = 0 ) { if ( ! defined( 'DOING_CRON' ) || ! DOING_CRON ) return; //load text domain if needed if ( ! is_textdomain_loaded( 'backwpup' ) && ! get_site_option( 'backwpup_cfg_jobnotranslate') ) load_plugin_textdomain( 'backwpup', FALSE, BackWPup::get_plugin_data( 'BaseName' ) . '/languages' ); if ( ! empty( $jobid ) ) { //check folders if ( ! self::check_folder( get_site_option( 'backwpup_cfg_logfolder' ) ) || ! self::check_folder( BackWPup::get_plugin_data( 'TEMP' ), TRUE ) ) return; } // Should be preventing doubled running job's on http requests $random = rand( 1, 9 ) * 100000; usleep( $random ); //get running job $backwpup_job_object = self::get_working_data(); //start/restart class if ( empty( $backwpup_job_object ) && ! empty( $jobid ) ) { //schedule restart event wp_schedule_single_event( time() + 60, 'backwpup_cron', array( 'id' => 'restart' ) ); //start job $backwpup_job_object = new self(); $backwpup_job_object->create( 'cronrun', (int)$jobid ); } if( is_object( $backwpup_job_object ) && $backwpup_job_object instanceof BackWPup_Job ) $backwpup_job_object->run(); } /** * disable caches */ public static function disable_caches() { //Special settings @putenv( 'nokeepalive=1' ); @ini_set( 'zlib.output_compression', 'Off' ); // deactivate caches if ( ! defined( 'DONOTCACHEOBJECT' ) ) define( 'DONOTCACHEOBJECT', TRUE ); if ( ! defined( 'DONOTCACHEPAGE' ) ) define( 'DONOTCACHEPAGE', TRUE ); } /** * Run baby run */ public function run() { global $wpdb; /* @var wpdb $wpdb */ // Job can't run it is not created if ( empty( $this->steps_todo ) ) return; //Check double running and inactivity $last_update = microtime( TRUE ) - $this->timestamp_last_update; if ( ! empty( $this->pid ) && $last_update > 300 ) { $this->log( __( 'Job restarts due to inactivity for more than 5 minutes.', 'backwpup' ), E_USER_WARNING ); } elseif ( ! empty( $this->pid ) ) { return; } // set timestamp of script start $this->timestamp_script_start = microtime( TRUE ); //set Pid $this->pid = self::get_pid(); $this->uniqid = uniqid( '', TRUE ); //Early write new working file $this->write_running_file(); //set function for PHP user defined error handling $this->run[ 'PHP' ][ 'INI' ][ 'ERROR_LOG' ] = ini_get( 'error_log' ); $this->run[ 'PHP' ][ 'INI' ][ 'ERROR_REPORTING' ]= ini_get( 'error_reporting' ); $this->run[ 'PHP' ][ 'INI' ][ 'LOG_ERRORS' ] = ini_get( 'log_errors' ); $this->run[ 'PHP' ][ 'INI' ][ 'DISPLAY_ERRORS' ] = ini_get( 'display_errors' ); $this->run[ 'PHP' ][ 'INI' ][ 'HTML_ERRORS' ] = ini_get( 'html_errors' ); $this->run[ 'PHP' ][ 'INI' ][ 'REPORT_MEMLEAKS' ]= ini_get( 'report_memleaks' ); $this->run[ 'PHP' ][ 'INI' ][ 'ZLIB_OUTPUT_COMPRESSION' ] = ini_get( 'zlib.output_compression' ); $this->run[ 'PHP' ][ 'INI' ][ 'IMPLICIT_FLUSH' ] = ini_get( 'implicit_flush' ); @ini_set( 'error_log', $this->logfile ); if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_reporting( -1 ); } else { error_reporting( E_ALL ^ E_NOTICE ); } @ini_set( 'display_errors', 'Off' ); @ini_set( 'log_errors', 'On' ); @ini_set( 'html_errors', 'Off' ); @ini_set( 'report_memleaks', 'On' ); @ini_set( 'zlib.output_compression', 'Off' ); @ini_set( 'implicit_flush', 'Off' ); //increase MySQL timeout @ini_set( 'mysql.connect_timeout', '300' ); $wpdb->query( "SET session wait_timeout = 300" ); //set temp folder $can_set_temp_env = TRUE; $protected_env_vars = explode( ',', ini_get( 'safe_mode_protected_env_vars') ); foreach( $protected_env_vars as $protected_env ) { if ( strtoupper( trim( $protected_env ) ) == 'TMPDIR' ) $can_set_temp_env = FALSE; } if ( $can_set_temp_env ) { $this->run[ 'PHP' ][ 'ENV' ][ 'TEMPDIR' ] = getenv( 'TMPDIR' ); @putenv( 'TMPDIR='.BackWPup::get_plugin_data( 'TEMP') ); } //Write Wordpress DB errors to log $wpdb->suppress_errors( FALSE ); $wpdb->hide_errors(); //set wp max memory limit @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) ); //set error handler if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { set_error_handler( array( $this, 'log' ), -1 ); } else { set_error_handler( array( $this, 'log' ), E_ALL ^ E_NOTICE ); } set_exception_handler( array( $this, 'exception_handler' ) ); //not loading Textdomains and unload loaded if ( get_site_option( 'backwpup_cfg_jobnotranslate' ) ) { add_filter( 'override_load_textdomain', create_function( '','return TRUE;') ); $GLOBALS[ 'l10n' ] = array(); } // execute function on job shutdown register_shutdown_function( array( $this, 'shutdown' ) ); add_action( 'shutdown', array( $this, 'shutdown' ) ); //remove_action('shutdown', array( $this, 'shutdown' )); if ( function_exists( 'pcntl_signal' ) ) { declare( ticks = 1 ) ; //set ticks pcntl_signal( 15, array( $this, 'shutdown' ) ); //SIGTERM //pcntl_signal(9, array($this,'shutdown')); //SIGKILL pcntl_signal( 2, array( $this, 'shutdown' ) ); //SIGINT } //clear output buffer while( @ob_end_clean() ); @flush(); $job_types = BackWPup::get_job_types(); //go step by step foreach ( $this->steps_todo as $this->step_working ) { //Check if step already done if ( in_array( $this->step_working, $this->steps_done ) ) continue; //calc step percent if ( count( $this->steps_done ) > 0 ) $this->step_percent = round( count( $this->steps_done ) / count( $this->steps_todo ) * 100 ); else $this->step_percent = 1; // do step tries while ( TRUE ) { if ( $this->steps_data[ $this->step_working ][ 'STEP_TRY' ] >= get_site_option( 'backwpup_cfg_jobstepretry' ) ) { $this->log( __( 'Step aborted: too many attempts!', 'backwpup' ), E_USER_ERROR ); $this->temp = array(); $this->steps_done[ ] = $this->step_working; $this->substeps_done = 0; $this->substeps_todo = 0; $this->do_restart(); break; } $this->steps_data[ $this->step_working ][ 'STEP_TRY' ] ++; $done = FALSE; //executes the methods of job process if ( $this->step_working == 'CREATE_ARCHIVE' ) { $done = $this->create_archive(); } elseif ( $this->step_working == 'CREATE_MANIFEST' ) { $done = $this->create_manifest(); } elseif ( $this->step_working == 'END' ) { $this->end(); break 2; } elseif ( strstr( $this->step_working, 'JOB_' ) ) { $done = $job_types[ str_replace( 'JOB_', '', $this->step_working ) ]->job_run( $this ); } elseif ( strstr( $this->step_working, 'DEST_SYNC_' ) ) { $done = BackWPup::get_destination( str_replace( 'DEST_SYNC_', '', $this->step_working ) )->job_run_sync( $this ); } elseif ( strstr( $this->step_working, 'DEST_' ) ) { $done = BackWPup::get_destination( str_replace( 'DEST_', '', $this->step_working ) )->job_run_archive( $this ); } elseif ( ! empty( $this->steps_data[ $this->step_working ][ 'CALLBACK' ] ) ) { $done = $this->steps_data[ $this->step_working ][ 'CALLBACK' ]( $this ); } // set step as done if ( $done === TRUE ) { $this->temp = array(); $this->steps_done[] = $this->step_working; $this->substeps_done = 0; $this->substeps_todo = 0; $this->write_running_file(); } if ( count( $this->steps_done ) < count( $this->steps_todo ) -1 ) { $this->do_restart(); } if ( $done === TRUE ) { break; } } } } /** * Do a job restart * * @param bool $must Restart must done * @param bool $msg Log restart message */ public function do_restart( $must = FALSE, $msg = TRUE ) { //no restart if in end step if ( $this->step_working == 'END' || ( count( $this->steps_done ) + 1 ) >= count( $this->steps_todo ) ) return; //no restart on cli usage if ( php_sapi_name() == 'cli' ) return; //no restart when restart was 3 Seconds before $execution_time = microtime( TRUE ) - $this->timestamp_script_start; if ( ! $must && $execution_time < 3 ) return; //no restart if no working job if ( ! file_exists( BackWPup::get_plugin_data( 'running_file' ) ) ) return; //print message if ( $msg ) $this->log( __( 'Restart will be executed now.', 'backwpup' ) ); //do things for a clean restart $this->pid = 0; $this->uniqid = ''; $this->write_running_file(); remove_action( 'shutdown', array( $this, 'shutdown' ) ); //do restart wp_clear_scheduled_hook( 'backwpup_cron', array( 'id' => 'restart' ) ); wp_schedule_single_event( time() + 10, 'backwpup_cron', array( 'id' => 'restart' ) ); self::get_jobrun_url( 'restart' ); exit(); } /** * Do a job restart * * @param bool $do_restart_now should time restart now be done * @return int remaining time */ public function do_restart_time( $do_restart_now = FALSE ) { $job_max_execution_time = get_site_option( 'backwpup_cfg_jobmaxexecutiontime' ); if ( empty( $job_max_execution_time ) ) return 300; $execution_time = microtime( TRUE ) - $this->timestamp_script_start; // do restart 3 sec. before max. execution time if ( $do_restart_now || $execution_time >= ( $job_max_execution_time - 3 ) ) { $this->steps_data[ $this->step_working ][ 'SAVE_STEP_TRY' ] = $this->steps_data[ $this->step_working ][ 'STEP_TRY' ]; $this->steps_data[ $this->step_working ][ 'STEP_TRY' ] -= 1; $this->log( sprintf( __( 'Restart after %1$d seconds.', 'backwpup' ), ceil( $execution_time ), $job_max_execution_time ) ); $this->do_restart( TRUE, FALSE ); } return $job_max_execution_time - $execution_time; } /** * Get job restart time * * @return int remaining time */ public function get_restart_time() { $job_max_execution_time = get_site_option( 'backwpup_cfg_jobmaxexecutiontime' ); if ( empty( $job_max_execution_time ) ) return 300; $execution_time = microtime( TRUE ) - $this->timestamp_script_start; return $job_max_execution_time - $execution_time - 3; } /** * * Get data off a working job * * @return bool|object BackWPup_Job Object or Bool if file not exits */ public static function get_working_data() { if ( version_compare( PHP_VERSION, '5.3', '>=' ) ) { clearstatcache( TRUE, BackWPup::get_plugin_data( 'running_file' ) ); } else { clearstatcache(); } if ( ! file_exists( BackWPup::get_plugin_data( 'running_file' ) ) ) return FALSE; $file_data = file_get_contents( BackWPup::get_plugin_data( 'running_file' ), FALSE, NULL, 8 ); if ( $file_data === FALSE ) return FALSE; if ( $job_object = unserialize( $file_data ) ) { if ( $job_object instanceof BackWPup_Job ) return $job_object; } return FALSE; } /** * * Reads a BackWPup logfile header and gives back a array of information * * @param string $logfile full logfile path * * @return array|bool */ public static function read_logheader( $logfile ) { $usedmetas = array( "date" => "logtime", "backwpup_logtime" => "logtime", //old value of date "backwpup_errors" => "errors", "backwpup_warnings" => "warnings", "backwpup_jobid" => "jobid", "backwpup_jobname" => "name", "backwpup_jobtype" => "type", "backwpup_jobruntime" => "runtime", "backwpup_backupfilesize" => "backupfilesize" ); //get metadata of logfile $metas = array(); if ( is_readable( $logfile ) ) { if ( '.gz' == substr( $logfile, -3 ) ) $metas = (array)get_meta_tags( 'compress.zlib://' . $logfile ); else $metas = (array)get_meta_tags( $logfile ); } //only output needed data foreach ( $usedmetas as $keyword => $field ) { if ( isset( $metas[ $keyword ] ) ) { $joddata[ $field ] = $metas[ $keyword ]; } else { $joddata[ $field ] = ''; } } //convert date if ( isset( $metas[ 'date' ] ) ) $joddata[ 'logtime' ] = strtotime( $metas[ 'date' ] ) + ( get_option( 'gmt_offset' ) * 3600 ); //use file create date if none if ( empty( $joddata[ 'logtime' ] ) ) $joddata[ 'logtime' ] = filectime( $logfile ); return $joddata; } /** * * Shutdown function is call if script terminates try to make a restart if needed * * Prepare the job for start * * @internal param int the signal that terminates the job */ public function shutdown() { $args = func_get_args(); //nothing on empty if ( empty( $this->logfile ) ) return; //Put last error to log if one $lasterror = error_get_last(); if ( $lasterror[ 'type' ] == E_ERROR or $lasterror[ 'type' ] == E_PARSE or $lasterror[ 'type' ] == E_CORE_ERROR or $lasterror[ 'type' ] == E_CORE_WARNING or $lasterror[ 'type' ] == E_COMPILE_ERROR or $lasterror[ 'type' ] == E_COMPILE_WARNING ) $this->log( $lasterror[ 'type' ], $lasterror[ 'message' ], $lasterror[ 'file' ], $lasterror[ 'line' ] ); //Put sigterm to log if ( ! empty( $args[ 0 ] ) ) $this->log( sprintf( __( 'Signal %d is sent to script!', 'backwpup' ), $args[ 0 ] ), E_USER_ERROR ); $this->do_restart( TRUE, TRUE ); } /** * * Check is folder readable and exists create it if not * add .htaccess or index.html file in folder to prevent directory listing * * @param string $folder the folder to check * @param bool $donotbackup Create a file that the folder will not backuped * @return bool ok or not */ public static function check_folder( $folder, $donotbackup = FALSE ) { $folder = untrailingslashit( str_replace( '\\', '/', $folder ) ); if ( empty( $folder ) ) return FALSE; //check that is not home of WP if ( $folder == untrailingslashit( str_replace( '\\', '/', ABSPATH ) ) || $folder == untrailingslashit( str_replace( '\\', '/', WP_PLUGIN_DIR ) ) || $folder == untrailingslashit( str_replace( '\\', '/', WP_CONTENT_DIR ) ) ) { BackWPup_Admin::message( sprintf( __( 'Folder %1$s not allowed, please use another folder.', 'backwpup' ), $folder ), TRUE ); return FALSE; } //create folder if it not exists if ( ! is_dir( $folder ) ) { if ( ! wp_mkdir_p( $folder ) ) { BackWPup_Admin::message( sprintf( __( 'Cannot create folder: %1$s', 'backwpup' ), $folder ), TRUE ); return FALSE; } } //check is writable dir if ( ! is_writable( $folder ) ) { BackWPup_Admin::message( sprintf( __( 'Folder "%1$s" is not writable', 'backwpup' ), $folder ), TRUE ); return FALSE; } //create .htaccess for apache and index.php for folder security if ( get_site_option( 'backwpup_cfg_protectfolders') && ! file_exists( $folder . '/.htaccess' ) ) file_put_contents( $folder . '/.htaccess', "" . PHP_EOL . "" . PHP_EOL . "Deny from all" . PHP_EOL . "" . PHP_EOL . "" . PHP_EOL . "" . PHP_EOL . "Deny from all" . PHP_EOL . "" . PHP_EOL . "" . PHP_EOL . "" . PHP_EOL . "Deny from all" . PHP_EOL . "" . PHP_EOL . "" ); if ( get_site_option( 'backwpup_cfg_protectfolders') && ! file_exists( $folder . '/index.php' ) ) file_put_contents( $folder . '/index.php', "log( E_USER_ERROR, sprintf( __( 'Exception caught in %1$s: %2$s', 'backwpup' ), get_class( $exception ), htmlentities( $exception->getMessage() ) ), $exception->getFile(), $exception->getLine() ); } /** * Write messages to log file * * @internal param int the error number (E_USER_ERROR,E_USER_WARNING,E_USER_NOTICE, ...) * @internal param string the error message * @internal param string the full path of file with error (__FILE__) * @internal param int the line in that is the error (__LINE__) * * @return bool true */ public function log() { $args = func_get_args(); // if error has been suppressed with an @ if ( error_reporting() == 0 ) return TRUE; //if first the message an second the type switch it on user errors if ( isset( $args[ 1 ] ) && in_array( $args[ 1 ], array( E_USER_NOTICE, E_USER_WARNING, E_USER_ERROR, 16384 ) ) ) { $temp = $args[ 0 ]; $args[ 0 ] = $args[ 1 ]; $args[ 1 ] = $temp; } //if first the message and nothing else set if ( ! isset( $args[ 1 ] ) ) { $args[ 1 ] = $args[ 0 ]; $args[ 0 ] = E_USER_NOTICE; } //json message if array or object if ( is_array( $args[ 1 ] ) || is_object( $args[ 1 ] ) ) $args[ 1 ] = json_encode( $args[ 1 ] ); //if not set line and file get it if ( empty( $args[ 2 ] ) || empty( $args[ 3 ] ) ) { $debug_info = debug_backtrace(); $args[ 2 ] = $debug_info[ 0 ][ 'file' ]; $args[ 3 ] = $debug_info[ 0 ][ 'line' ]; } $error_or_warning = FALSE; switch ( $args[ 0 ] ) { case E_NOTICE: case E_USER_NOTICE: $messagetype = ''; break; case E_WARNING: case E_CORE_WARNING: case E_COMPILE_WARNING: case E_USER_WARNING: $this->warnings ++; $error_or_warning = TRUE; $messagetype = '' . __( 'WARNING:', 'backwpup' ) . ' '; break; case E_ERROR: case E_PARSE: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: $this->errors ++; $error_or_warning = TRUE; $messagetype = '' . __( 'ERROR:', 'backwpup' ) . ' '; break; case 8192: //E_DEPRECATED comes with php 5.3 case 16384: //E_USER_DEPRECATED comes with php 5.3 $messagetype = __( 'DEPRECATED:', 'backwpup' ) . ' '; break; case E_STRICT: $messagetype = __( 'STRICT NOTICE:', 'backwpup' ) . ' '; break; case E_RECOVERABLE_ERROR: $this->errors ++; $error_or_warning = TRUE; $messagetype = '' . __( 'RECOVERABLE ERROR:', 'backwpup' ) . ' '; break; default: $messagetype = $args[ 0 ] . ": "; break; } $in_file = str_replace( str_replace( '\\', '/', ABSPATH ), '', str_replace( '\\', '/', $args[ 2 ] ) ); //print message to cli if ( defined( 'WP_CLI' ) && WP_CLI ) { if ( $error_or_warning ) { WP_CLI::warning( '[' . date_i18n( 'd-M-Y H:i:s' ) . '] ' . strip_tags( $messagetype ) . str_replace( array( '…', ' ' ), array( '...', ' ' ), strip_tags( $args[ 1 ] ) ) ); } else { WP_CLI::log( '[' . date_i18n( 'd-M-Y H:i:s' ) . '] ' . strip_tags( $messagetype ) . str_replace( array( '…', ' ' ), array( '...', ' ' ), strip_tags( $args[ 1 ] ) ) ); } } elseif ( php_sapi_name() == 'cli' && defined( 'STDOUT' ) ) { fwrite( STDOUT, '[' . date_i18n( 'd-M-Y H:i:s' ) . '] ' . strip_tags( $messagetype ) . str_replace( array( '…', ' ' ), array( '...', ' ' ), strip_tags( $args[ 1 ] ) ) . PHP_EOL ) ; } //log line $timestamp = '[' . date_i18n( 'd-M-Y H:i:s' ) . '] '; //set last Message $message = $messagetype . htmlentities( $args[ 1 ], ENT_COMPAT , get_bloginfo( 'charset' ), FALSE ); if ( strstr( $message, 'lastmsg = $message; if ( $error_or_warning ) $this->lasterrormsg = $message; //write log file file_put_contents( $this->logfile, $timestamp . $message . '
' . PHP_EOL, FILE_APPEND ); //write new log header if ( $error_or_warning ) { $found = 0; $fd = fopen( $this->logfile, 'r+' ); $file_pos = ftell( $fd ); while ( ! feof( $fd ) ) { $line = fgets( $fd ); if ( stripos( $line, '', 100 ) . PHP_EOL ); $found ++; } if ( stripos( $line, '', 100 ) . PHP_EOL ); $found ++; } if ( $found >= 2 ) break; $file_pos = ftell( $fd ); } fclose( $fd ); } //write working data $this->update_working_data( $error_or_warning ); //true for no more php error handling. return TRUE; } /** * * Write the Working data to display the process or that i can executes again * The write will only done every second * * @global wpdb $wpdb */ public function update_working_data() { global $wpdb; /* @var wpdb $wpdb */ //to reduce server load if ( get_site_option( 'backwpup_cfg_jobwaittimems' ) > 0 && get_site_option( 'backwpup_cfg_jobwaittimems') <= 500000 ) usleep( get_site_option( 'backwpup_cfg_jobwaittimems' ) ); //check free memory $this->need_free_memory( '10M' ); //only run every 1 sec. $time_to_update = microtime( TRUE ) - $this->timestamp_last_update; if ( $time_to_update < 1 ) return; //FCGI must have a permanent output so that it not broke if ( stristr( PHP_SAPI, 'fcgi' ) || stristr( PHP_SAPI, 'litespeed' ) ) { //only if no output buffering is active if ( ob_get_level() == 0 ) { echo ' '; flush(); } } //set execution time again for 5 min @set_time_limit( 300 ); //check MySQL connection to WordPress Database and reconnect if needed $res = $wpdb->query( 'SELECT 1' ); if ( $res === FALSE ) $wpdb->db_connect(); //calc sub step percent if ( $this->substeps_todo > 0 && $this->substeps_done > 0 ) $this->substep_percent = round( $this->substeps_done / $this->substeps_todo * 100 ); else $this->substep_percent = 1; //check if job aborted if ( ! file_exists( BackWPup::get_plugin_data( 'running_file' ) ) ) { if ( $this->step_working != 'END' ) $this->end(); } else { $this->timestamp_last_update = microtime( TRUE ); //last update of working file $this->write_running_file(); } } public function write_running_file() { $clone = clone $this; $data = 'log( __( 'Cannot write progress to working file. Job will be aborted.', 'backwpup' ), E_USER_ERROR ); } } /** * * Called on job stop makes cleanup and terminates the script * */ private function end() { $this->step_working = 'END'; $this->substeps_todo = 1; $abort = FALSE; if ( ! file_exists( BackWPup::get_plugin_data( 'running_file' ) ) ) { if ( ! $this->user_abort ) $abort = TRUE; $this->log( __( 'Aborted by user!', 'backwpup' ), E_USER_ERROR ); } //delete old logs if ( get_site_option( 'backwpup_cfg_maxlogs' ) ) { $log_file_list = array(); if ( $dir = opendir( get_site_option( 'backwpup_cfg_logfolder' ) ) ) { //make file list while ( ( $file = readdir( $dir ) ) !== FALSE ) { if ( strpos( $file, 'backwpup_log_' ) == 0 && FALSE !== strpos( $file, '.html' ) ) $log_file_list[ filemtime( get_site_option( 'backwpup_cfg_logfolder' ) . '/' . $file ) ] = $file; } closedir( $dir ); } if ( sizeof( $log_file_list ) > 0 ) { krsort( $log_file_list, SORT_NUMERIC ); $num_delete_files = 0; $i = -1; foreach ( $log_file_list AS $log_file ) { $i ++; if ( $i < get_site_option( 'backwpup_cfg_maxlogs' ) ) continue; unlink( get_site_option( 'backwpup_cfg_logfolder' ) . $log_file ); $num_delete_files ++; } if ( $num_delete_files > 0 ) $this->log( sprintf( _n( 'One old log deleted', '%d old logs deleted', $num_delete_files, 'backwpup' ), $num_delete_files ) ); } } //Display job working time if ( $this->errors > 0 ) $this->log( sprintf( __( 'Job has ended with errors in %s seconds. You must resolve the errors for correct execution.', 'backwpup' ), current_time( 'timestamp' ) - $this->start_time ), E_USER_ERROR ); elseif ( $this->warnings > 0 ) $this->log( sprintf( __( 'Job finished with warnings in %s seconds. Please resolve them for correct execution.', 'backwpup' ), current_time( 'timestamp' ) - $this->start_time ), E_USER_WARNING ); else $this->log( sprintf( __( 'Job done in %s seconds.', 'backwpup' ), current_time( 'timestamp' ) - $this->start_time, E_USER_NOTICE ) ); //Update job options if ( ! empty( $this->job[ 'jobid' ] ) ) { $this->job[ 'lastruntime' ] = current_time( 'timestamp' ) - $this->start_time; BackWPup_Option::update( $this->job[ 'jobid' ], 'lastruntime', $this->job[ 'lastruntime' ] ); } //write header info if ( is_writable( $this->logfile ) ) { $fd = fopen( $this->logfile, 'r+' ); $filepos = ftell( $fd ); $found = 0; while ( ! feof( $fd ) ) { $line = fgets( $fd ); if ( stripos( $line, '', 100 ) . PHP_EOL ); $found ++; } if ( stripos( $line, '', 100 ) . PHP_EOL ); $found ++; } if ( $found >= 2 ) break; $filepos = ftell( $fd ); } fclose( $fd ); } //logfile end file_put_contents( $this->logfile, "" . PHP_EOL . "", FILE_APPEND ); //Send mail with log $sendmail = FALSE; if ( $this->errors > 0 && ! empty( $this->job[ 'mailerroronly' ] ) && ! empty( $this->job[ 'mailaddresslog' ] ) ) $sendmail = TRUE; if ( empty( $this->job[ 'mailerroronly' ] ) && ! empty( $this->job[ 'mailaddresslog' ] ) ) $sendmail = TRUE; if ( $sendmail ) { //special subject $status = __( 'SUCCESSFUL', 'backwpup' ); $priority = 3; //Normal if ( $this->warnings > 0 ) { $status = __( 'WARNING', 'backwpup' ); $priority = 2; //High } if ( $this->errors > 0 ) { $status = __( 'ERROR', 'backwpup' ); $priority = 1; //Highest } $subject = sprintf( __( '[%3$s] BackWPup log %1$s: %2$s', 'backwpup' ), date_i18n( 'd-M-Y H:i', $this->start_time, TRUE ), esc_attr( $this->job[ 'name' ] ), $status ); $headers = array(); $headers[] = 'Content-Type: text/html; charset='. get_bloginfo( 'charset' ); /* $headers[] = 'X-Priority: ' . $priority; */ // Priority not working with header setting if ( ! empty( $this->job[ 'mailaddresssenderlog' ] ) ) { if ( FALSE === $start_mail = strpos( $this->job[ 'mailaddresssenderlog' ], '<' ) ) { if ( FALSE === strpos( $this->job[ 'mailaddresssenderlog' ], '@' ) ) { $this->job[ 'mailaddresssenderlog' ] = '"' . str_replace( array( '<','>','@' ), '', $this->job[ 'mailaddresssenderlog' ] ) . '" <' . get_bloginfo( 'admin_email' ). '>'; } } elseif ( FALSE === strpos( $this->job[ 'mailaddresssenderlog' ], '>', $start_mail ) ) { $this->job[ 'mailaddresssenderlog' ] = '"' . str_replace( array( '<','>','@' ), '', substr( $this->job[ 'mailaddresssenderlog' ], 0, $start_mail ) ) . '" <' . get_bloginfo( 'admin_email' ). '>'; } $headers[] = 'From: ' . $this->job[ 'mailaddresssenderlog' ]; } wp_mail( $this->job[ 'mailaddresslog' ], $subject, file_get_contents( $this->logfile ), $headers ); } //set done $this->substeps_done = 1; $this->steps_done[ ] = 'END'; //clean up temp self::clean_temp_folder(); //remove shutdown action remove_action( 'shutdown', array( $this, 'shutdown' ) ); restore_exception_handler(); restore_error_handler(); if ( ! empty( $this->run[ 'PHP' ] ) ) { @ini_set( 'log_errors', $this->run[ 'PHP' ][ 'INI' ][ 'LOG_ERRORS' ] ); @ini_set( 'error_log', $this->run[ 'PHP' ][ 'INI' ][ 'ERROR_LOG' ] ); @ini_set( 'display_errors', $this->run[ 'PHP' ][ 'INI' ][ 'DISPLAY_ERRORS' ] ); @ini_set( 'html_errors', $this->run[ 'PHP' ][ 'INI' ][ 'HTML_ERRORS' ] ); @ini_set( 'zlib.output_compression', $this->run[ 'PHP' ][ 'INI' ][ 'ZLIB_OUTPUT_COMPRESSION' ] ); @ini_set( 'implicit_flush', $this->run[ 'PHP' ][ 'INI' ][ 'IMPLICIT_FLUSH' ] ); @ini_set( 'error_reporting', $this->run[ 'PHP' ][ 'INI' ][ 'ERROR_REPORTING' ] ); @ini_set( 'report_memleaks', $this->run[ 'PHP' ][ 'INI' ][ 'REPORT_MEMLEAKS' ] ); if ( !empty( $this->run[ 'PHP' ][ 'ENV' ][ 'TEMPDIR' ] ) ) { @putenv('TMPDIR=' . $this->run[ 'PHP' ][ 'ENV' ][ 'TEMPDIR' ] ); } } BackWPup_Cron::check_cleanup(); if ( $abort ) exit(); } public static function user_abort() { /* @var $job_object BackWPup_Job */ $job_object = BackWPup_Job::get_working_data(); unlink( BackWPup::get_plugin_data( 'running_file' ) ); //if job not working currently abort it this way for message $not_worked_time = microtime( TRUE ) - $job_object->timestamp_last_update; $restart_time = get_site_option( 'backwpup_cfg_jobmaxexecutiontime' ); if ( empty( $restart_time ) ) $restart_time = 60; if ( empty( $job_object->pid ) || $not_worked_time > $restart_time ) { $job_object->user_abort = TRUE; $job_object->update_working_data(); } } /** * * Increase automatically the memory that is needed * * @param int|string $memneed of the needed memory */ public function need_free_memory( $memneed ) { //need memory $needmemory = @memory_get_usage( TRUE ) + self::convert_hr_to_bytes( $memneed ); // increase Memory if ( $needmemory > self::convert_hr_to_bytes( ini_get( 'memory_limit' ) ) ) { $newmemory = round( $needmemory / 1024 / 1024 ) + 1 . 'M'; if ( $needmemory >= 1073741824 ) $newmemory = round( $needmemory / 1024 / 1024 / 1024 ) . 'G'; @ini_set( 'memory_limit', $newmemory ); } } /** * * Converts hr to bytes * * @param $size * @return int */ public static function convert_hr_to_bytes( $size ) { $size = strtolower( $size ); $bytes = (int) $size; if ( strpos( $size, 'k' ) !== FALSE ) $bytes = intval( $size ) * 1024; elseif ( strpos( $size, 'm' ) !== FALSE ) $bytes = intval($size) * 1024 * 1024; elseif ( strpos( $size, 'g' ) !== FALSE ) $bytes = intval( $size ) * 1024 * 1024 * 1024; return $bytes; } /** * * Callback for the CURLOPT_READFUNCTION that submit the transferred bytes * to build the process bar * * @param $curl_handle * @param $file_handle * @param $read_count * @return string * @internal param $out */ public function curl_read_callback( $curl_handle, $file_handle, $read_count ) { $data = NULL; if ( ! empty( $file_handle ) && is_numeric( $read_count ) ) $data = fread( $file_handle, $read_count ); if ( $this->job[ 'backuptype' ] == 'sync' ) return $data; $length = ( is_numeric( $read_count ) ) ? $read_count : strlen( $read_count ); $this->substeps_done = $this->substeps_done + $length; $this->update_working_data(); return $data; } /** * * Get the mime type of a file * * @param string $file The full file name * * @return bool|string the mime type or false */ public function get_mime_type( $file ) { if ( is_dir( $file ) || is_link( $file ) ) return 'application/octet-stream'; $mime_types = array( 'zip' => 'application/zip', 'gz' => 'application/gzip', 'bz2' => 'application/x-bzip', 'tar' => 'application/x-tar', '3gp' => 'video/3gpp', 'ai' => 'application/postscript', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'asc' => 'text/plain', 'atom' => 'application/atom+xml', 'au' => 'audio/basic', 'avi' => 'video/x-msvideo', 'bcpio' => 'application/x-bcpio', 'bin' => 'application/octet-stream', 'bmp' => 'image/bmp', 'cdf' => 'application/x-netcdf', 'cgm' => 'image/cgm', 'class' => 'application/octet-stream', 'cpio' => 'application/x-cpio', 'cpt' => 'application/mac-compactpro', 'csh' => 'application/x-csh', 'css' => 'text/css', 'dcr' => 'application/x-director', 'dif' => 'video/x-dv', 'dir' => 'application/x-director', 'djv' => 'image/vnd.djvu', 'djvu' => 'image/vnd.djvu', 'dll' => 'application/octet-stream', 'dmg' => 'application/octet-stream', 'dms' => 'application/octet-stream', 'doc' => 'application/msword', 'dtd' => 'application/xml-dtd', 'dv' => 'video/x-dv', 'dvi' => 'application/x-dvi', 'dxr' => 'application/x-director', 'eps' => 'application/postscript', 'etx' => 'text/x-setext', 'exe' => 'application/octet-stream', 'ez' => 'application/andrew-inset', 'flv' => 'video/x-flv', 'gif' => 'image/gif', 'gram' => 'application/srgs', 'grxml' => 'application/srgs+xml', 'gtar' => 'application/x-gtar', 'hdf' => 'application/x-hdf', 'hqx' => 'application/mac-binhex40', 'htm' => 'text/html', 'html' => 'text/html', 'ice' => 'x-conference/x-cooltalk', 'ico' => 'image/x-icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', 'iges' => 'model/iges', 'igs' => 'model/iges', 'jnlp' => 'application/x-java-jnlp-file', 'jp2' => 'image/jp2', 'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'js' => 'application/x-javascript', 'kar' => 'audio/midi', 'latex' => 'application/x-latex', 'lha' => 'application/octet-stream', 'lzh' => 'application/octet-stream', 'm3u' => 'audio/x-mpegurl', 'm4a' => 'audio/mp4a-latm', 'm4p' => 'audio/mp4a-latm', 'm4u' => 'video/vnd.mpegurl', 'm4v' => 'video/x-m4v', 'mac' => 'image/x-macpaint', 'man' => 'application/x-troff-man', 'mathml' => 'application/mathml+xml', 'me' => 'application/x-troff-me', 'mesh' => 'model/mesh', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mif' => 'application/vnd.mif', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpg' => 'video/mpeg', 'mpga' => 'audio/mpeg', 'ms' => 'application/x-troff-ms', 'msh' => 'model/mesh', 'mxu' => 'video/vnd.mpegurl', 'nc' => 'application/x-netcdf', 'oda' => 'application/oda', 'ogg' => 'application/ogg', 'ogv' => 'video/ogv', 'pbm' => 'image/x-portable-bitmap', 'pct' => 'image/pict', 'pdb' => 'chemical/x-pdb', 'pdf' => 'application/pdf', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', 'pic' => 'image/pict', 'pict' => 'image/pict', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'pnt' => 'image/x-macpaint', 'pntg' => 'image/x-macpaint', 'ppm' => 'image/x-portable-pixmap', 'ppt' => 'application/vnd.ms-powerpoint', 'ps' => 'application/postscript', 'qt' => 'video/quicktime', 'qti' => 'image/x-quicktime', 'qtif' => 'image/x-quicktime', 'ra' => 'audio/x-pn-realaudio', 'ram' => 'audio/x-pn-realaudio', 'ras' => 'image/x-cmu-raster', 'rdf' => 'application/rdf+xml', 'rgb' => 'image/x-rgb', 'rm' => 'application/vnd.rn-realmedia', 'roff' => 'application/x-troff', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'silo' => 'model/mesh', 'sit' => 'application/x-stuffit', 'skd' => 'application/x-koan', 'skm' => 'application/x-koan', 'skp' => 'application/x-koan', 'skt' => 'application/x-koan', 'smi' => 'application/smil', 'smil' => 'application/smil', 'snd' => 'audio/basic', 'so' => 'application/octet-stream', 'spl' => 'application/x-futuresplash', 'src' => 'application/x-wais-source', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svg' => 'image/svg+xml', 'swf' => 'application/x-shockwave-flash', 't' => 'application/x-troff', 'tcl' => 'application/x-tcl', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'tr' => 'application/x-troff', 'tsv' => 'text/tab-separated-values', 'txt' => 'text/plain', 'ustar' => 'application/x-ustar', 'vcd' => 'application/x-cdlink', 'vrml' => 'model/vrml', 'vxml' => 'application/voicexml+xml', 'wav' => 'audio/x-wav', 'wbmp' => 'image/vnd.wap.wbmp', 'wbxml' => 'application/vnd.wap.wbxml', 'webm' => 'video/webm', 'wml' => 'text/vnd.wap.wml', 'wmlc' => 'application/vnd.wap.wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wrl' => 'model/vrml', 'xbm' => 'image/x-xbitmap', 'xht' => 'application/xhtml+xml', 'xhtml' => 'application/xhtml+xml', 'xls' => 'application/vnd.ms-excel', 'xml' => 'application/xml', 'xpm' => 'image/x-xpixmap', 'xsl' => 'application/xml', 'xslt' => 'application/xslt+xml', 'xul' => 'application/vnd.mozilla.xul+xml', 'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', ); $filesuffix = pathinfo( $file, PATHINFO_EXTENSION ); $suffix = strtolower( $filesuffix ); if ( isset( $mime_types[ $suffix ] ) ) return $mime_types[ $suffix ]; if ( ! is_readable( $file ) ) return 'application/octet-stream'; if ( function_exists( 'fileinfo' ) ) { $finfo = finfo_open( FILEINFO_MIME_TYPE ); $mime = finfo_file( $finfo, $file ); } if ( empty( $mime ) && function_exists( 'mime_content_type' ) ) $mime = mime_content_type( $file ); if ( empty( $mime ) ) return 'application/octet-stream'; else return $mime; } /** * * Gifs back a array of files to backup in the selected folder * * @param string $folder the folder to get the files from * * @return array files to backup */ public function get_files_in_folder( $folder ) { $files = array(); $folder = trailingslashit( $folder ); if ( ! is_dir( $folder ) ) { $this->log( sprintf( _x( 'Folder %s not exists', 'Folder name', 'backwpup' ), $folder ), E_USER_WARNING ); return $files; } if ( ! is_readable( $folder ) ) { $this->log( sprintf( _x( 'Folder %s not readable', 'Folder name', 'backwpup' ), $folder ), E_USER_WARNING ); return $files; } if ( $dir = opendir( $folder ) ) { while ( FALSE !== ( $file = readdir( $dir ) ) ) { if ( in_array( $file, array( '.', '..' ) ) || is_dir( $folder . $file ) ) continue; foreach ( $this->exclude_from_backup as $exclusion ) { //exclude files $exclusion = trim( $exclusion ); if ( FALSE !== stripos( $folder . $file, trim( $exclusion ) ) && ! empty( $exclusion ) ) continue 2; } if ( $this->job[ 'backupexcludethumbs' ] && strpos( $folder, BackWPup_File::get_upload_dir() ) !== FALSE && preg_match( "/\-[0-9]{1,4}x[0-9]{1,4}.+\.(jpg|png|gif)$/i", $file ) ) { continue; } if ( is_link( $folder . $file ) ) { $this->log( sprintf( __( 'Link "%s" not following.', 'backwpup' ), $folder . $file ), E_USER_WARNING ); } elseif ( ! is_readable( $folder . $file ) ) { $this->log( sprintf( __( 'File "%s" is not readable!', 'backwpup' ), $folder . $file ), E_USER_WARNING ); } else { $file_size = filesize( $folder . $file ); if ( ! is_int( $file_size ) || $file_size < 0 || $file_size > 2147483647 ) { $this->log( sprintf( __( 'File size of ā€œ%sā€ cannot be retrieved. File might be too large and will not be added to queue.', 'backwpup' ), $folder . $file . ' ' . $file_size ), E_USER_WARNING ); continue; } $files[ ] = $folder . $file; $this->count_files_in_folder ++; $this->count_filesize_in_folder = $this->count_filesize_in_folder + $file_size; } } closedir( $dir ); } return $files; } /** * @param create manifest file * @return bool */ public function create_manifest( ) { $this->substeps_todo = 3; $this->log( sprintf( __( '%d. Trying to generate a manifest file …', 'backwpup' ), $this->steps_data[ $this->step_working ][ 'STEP_TRY' ] ) ); //build manifest $manifest = array(); // add blog information $manifest[ 'blog_info' ][ 'url' ] = home_url(); $manifest[ 'blog_info' ][ 'wpurl' ] = site_url(); $manifest[ 'blog_info' ][ 'prefix' ] = $GLOBALS[ 'wpdb' ]->prefix; $manifest[ 'blog_info' ][ 'description' ] = get_option('blogdescription'); $manifest[ 'blog_info' ][ 'stylesheet_directory' ] = get_template_directory_uri(); $manifest[ 'blog_info' ][ 'activate_plugins' ] = wp_get_active_and_valid_plugins(); $manifest[ 'blog_info' ][ 'activate_theme' ] = wp_get_theme()->get('Name'); $manifest[ 'blog_info' ][ 'admin_email' ] = get_option('admin_email'); $manifest[ 'blog_info' ][ 'charset' ] = get_bloginfo( 'charset' ); $manifest[ 'blog_info' ][ 'version' ] = BackWPup::get_plugin_data( 'wp_version' ); $manifest[ 'blog_info' ][ 'backwpup_version' ] = BackWPup::get_plugin_data( 'version' ); $manifest[ 'blog_info' ][ 'language' ] = get_bloginfo( 'language' ); $manifest[ 'blog_info' ][ 'name' ] = get_bloginfo( 'name' ); $manifest[ 'blog_info' ][ 'abspath' ] = ABSPATH; $manifest[ 'blog_info' ][ 'uploads' ] = wp_upload_dir(); $manifest[ 'blog_info' ][ 'contents' ][ 'basedir' ] = WP_CONTENT_DIR; $manifest[ 'blog_info' ][ 'contents' ][ 'baseurl' ] = WP_CONTENT_URL; $manifest[ 'blog_info' ][ 'plugins' ][ 'basedir' ] = WP_PLUGIN_DIR; $manifest[ 'blog_info' ][ 'plugins' ][ 'baseurl' ] = WP_PLUGIN_URL; $manifest[ 'blog_info' ][ 'themes' ][ 'basedir' ] = get_theme_root(); $manifest[ 'blog_info' ][ 'themes' ][ 'baseurl' ] = get_theme_root_uri(); // add job settings $manifest[ 'job_settings' ] = $this->job; // add archive info foreach( $this->additional_files_to_backup as $file ) { $manifest[ 'archive' ][ 'extra_files' ][] = basename( $file ); } if ( isset( $this->steps_data[ 'JOB_FILE' ] ) ) { if ( $this->job[ 'backuproot'] ) $manifest[ 'archive' ][ 'abspath' ] = trailingslashit( str_replace( $this->remove_path, '', str_replace( '\\', '/',ABSPATH) ) ); if ( $this->job[ 'backupuploads'] ) $manifest[ 'archive' ][ 'uploads' ] = trailingslashit( str_replace( $this->remove_path, '', BackWPup_File::get_upload_dir() ) ); if ( $this->job[ 'backupcontent'] ) $manifest[ 'archive' ][ 'contents' ] = trailingslashit( str_replace( $this->remove_path, '', str_replace( '\\', '/',WP_CONTENT_DIR ) ) ); if ( $this->job[ 'backupplugins']) $manifest[ 'archive' ][ 'plugins' ] = trailingslashit( str_replace( $this->remove_path, '', str_replace( '\\', '/', WP_PLUGIN_DIR ) ) ); if ( $this->job[ 'backupthemes'] ) $manifest[ 'archive' ][ 'themes' ] = trailingslashit( str_replace( $this->remove_path, '', str_replace( '\\', '/', get_theme_root() ) ) ); } if ( ! file_put_contents( BackWPup::get_plugin_data( 'TEMP' ) . 'manifest.json', json_encode( $manifest ) ) ) return FALSE; $this->substeps_done = 1; //Create backwpup_readme.txt $readme_text = __( 'You may have noticed the manifest.json file in this archive.', 'backwpup' ) . PHP_EOL; $readme_text .= __( 'manifest.json might be needed for later restoring a backup from this archive.', 'backwpup' ) . PHP_EOL; $readme_text .= __( 'Please leave manifest.json untouched and in place. Otherwise it is safe to be ignored.', 'backwpup' ) . PHP_EOL; if ( ! file_put_contents( BackWPup::get_plugin_data( 'TEMP' ) . 'backwpup_readme.txt', $readme_text ) ) return FALSE; $this->substeps_done = 2; //add file to backup files if ( is_readable( BackWPup::get_plugin_data( 'TEMP' ) . 'manifest.json' ) ) { $this->additional_files_to_backup[ ] = BackWPup::get_plugin_data( 'TEMP' ) . 'manifest.json'; $this->count_files ++; $this->additional_files_to_backup[ ] = BackWPup::get_plugin_data( 'TEMP' ) . 'backwpup_readme.txt'; $this->count_files ++; $this->count_filesize = $this->count_filesize + filesize( BackWPup::get_plugin_data( 'TEMP' ) . 'manifest.json' ); $this->count_filesize = $this->count_filesize + filesize( BackWPup::get_plugin_data( 'TEMP' ) . 'backwpup_readme.txt' ); $this->log( sprintf( __( 'Added manifest.json file with %1$s to backup file list.', 'backwpup' ), size_format( filesize( BackWPup::get_plugin_data( 'TEMP' ) . 'manifest.json' ), 2 ) ) ); } $this->substeps_done = 3; return TRUE; } /** * Creates the backup archive */ private function create_archive() { //load folders to backup $folders_to_backup = $this->get_folders_to_backup(); $this->substeps_todo = $this->count_folder + 1; //initial settings for restarts in archiving if ( ! isset( $this->steps_data[ $this->step_working ]['on_file'] ) ) { $this->steps_data[ $this->step_working ]['on_file'] = ''; } if ( ! isset( $this->steps_data[ $this->step_working ]['on_folder'] ) ) { $this->steps_data[ $this->step_working ]['on_folder'] = ''; } if ( $this->steps_data[ $this->step_working ][ 'on_folder' ] == '' && $this->steps_data[ $this->step_working ][ 'on_file' ] == '' && is_file( $this->backup_folder . $this->backup_file ) ) { unlink( $this->backup_folder . $this->backup_file ); } if ( $this->steps_data[ $this->step_working ]['SAVE_STEP_TRY'] != $this->steps_data[ $this->step_working ][ 'STEP_TRY' ] ) $this->log( sprintf( __( '%d. Trying to create backup archive …', 'backwpup' ), $this->steps_data[ $this->step_working ][ 'STEP_TRY' ] ), E_USER_NOTICE ); try { $backup_archive = new BackWPup_Create_Archive( $this->backup_folder . $this->backup_file ); //show method for creation if ( $this->substeps_done == 0 ) $this->log( sprintf( _x( 'Compressing files as %s. Please be patient, this may take a moment.', 'Archive compression method', 'backwpup'), $backup_archive->get_method() ) ); //add extra files if ( $this->substeps_done == 0 ) { if ( ! empty( $this->additional_files_to_backup ) && $this->substeps_done == 0 ) { foreach ( $this->additional_files_to_backup as $file ) { if ( $backup_archive->add_file( $file, basename( $file ) ) ) {; $this->count_files ++; $this->count_filesize = filesize( $file ); $this->update_working_data(); } else { $backup_archive->close(); $this->steps_data[ $this->step_working ][ 'on_file' ] = ''; $this->steps_data[ $this->step_working ][ 'on_folder' ] = ''; $this->log( __( 'Cannot create backup archive correctly. Aborting creation.', 'backwpup' ), E_USER_ERROR ); return FALSE; } } } $this->substeps_done ++; } //add normal files while ( $folder = array_shift( $folders_to_backup ) ) { //jump over already done folders if ( in_array( $this->steps_data[ $this->step_working ]['on_folder'], $folders_to_backup ) ) continue; $this->steps_data[ $this->step_working ]['on_folder'] = $folder; $files_in_folder = $this->get_files_in_folder( $folder ); //add empty folders if ( empty( $files_in_folder ) ) { $folder_name_in_archive = trim( ltrim( str_replace( $this->remove_path, '', $folder ), '/' ) ); if ( ! empty ( $folder_name_in_archive ) ) $backup_archive->add_empty_folder( $folder, $folder_name_in_archive ); continue; } //add files while ( $file = array_shift( $files_in_folder ) ) { //jump over already done files if ( in_array( $this->steps_data[ $this->step_working ]['on_file'], $files_in_folder ) ) continue; $this->steps_data[ $this->step_working ]['on_file'] = $file; //close archive before restart $restart_time = $this->get_restart_time(); if ( $restart_time < 0 ) { unset( $backup_archive ); $this->do_restart_time( TRUE ); } //generate filename in archive $in_archive_filename = ltrim( str_replace( $this->remove_path, '', $file ), '/' ); //add file to archive if ( $backup_archive->add_file( $file, $in_archive_filename ) ) { $this->update_working_data(); } else { $backup_archive->close(); $this->steps_data[ $this->step_working ][ 'on_file' ] = ''; $this->steps_data[ $this->step_working ][ 'on_folder' ] = ''; $this->substeps_done = 0; $this->backup_filesize = filesize( $this->backup_folder . $this->backup_file ); if ( ( $this->backup_filesize + filesize( $file ) ) >= 2147483647 ) { $this->log( __( 'Aborting creation.', 'backwpup' ), E_USER_ERROR ); return TRUE; } $this->log( __( 'Cannot create backup archive correctly. Aborting creation.', 'backwpup' ), E_USER_ERROR ); return FALSE; } } $this->steps_data[ $this->step_working ]['on_file'] = ''; $this->substeps_done ++; } //restart if needed $restart_time = $this->get_restart_time(); if ( $restart_time < 5 ) { unset( $backup_archive ); $this->do_restart_time( TRUE ); } $backup_archive->close(); unset( $backup_archive ); $this->log( __( 'Backup archive created.', 'backwpup' ), E_USER_NOTICE ); } catch ( Exception $e ) { $this->log( $e->getMessage(), E_USER_ERROR, $e->getFile(), $e->getLine() ); unset( $backup_archive ); return FALSE; } $this->backup_filesize = filesize( $this->backup_folder . $this->backup_file ); if ( $this->backup_filesize ) $this->log( sprintf( __( 'Archive size is %s.', 'backwpup' ), size_format( $this->backup_filesize, 2 ) ), E_USER_NOTICE ); $this->log( sprintf( __( '%1$d Files with %2$s in Archive.', 'backwpup' ), $this->count_files + $this->count_files_in_folder, size_format( $this->count_filesize + $this->count_filesize_in_folder, 2 ) ), E_USER_NOTICE ); return TRUE; } /** * @param $name * @param string $suffix * @param bool $delete_temp_file * @return string */ public function generate_filename( $name, $suffix = '', $delete_temp_file = TRUE ) { $datevars = array( '%d', '%j', '%m', '%n', '%Y', '%y', '%a', '%A', '%B', '%g', '%G', '%h', '%H', '%i', '%s' ); $datevalues = array( date_i18n( 'd' ), date_i18n( 'j' ), date_i18n( 'm' ), date_i18n( 'n' ), date_i18n( 'Y' ), date_i18n( 'y' ), date_i18n( 'a' ), date_i18n( 'A' ), date_i18n( 'B' ), date_i18n( 'g' ), date_i18n( 'G' ), date_i18n( 'h' ), date_i18n( 'H' ), date_i18n( 'i' ), date_i18n( 's' ) ); if ( ! empty( $suffix ) && substr( $suffix, 0, 1 ) != '.' ) $suffix = '.' . $suffix; $name = str_replace( $datevars, $datevalues, self::sanitize_file_name( $name ) ); $name .= $suffix; if ( $delete_temp_file && is_writeable( BackWPup::get_plugin_data( 'TEMP' ) . $name ) && !is_dir( BackWPup::get_plugin_data( 'TEMP' ) . $name ) && !is_link( BackWPup::get_plugin_data( 'TEMP' ) . $name ) ) { unlink( BackWPup::get_plugin_data( 'TEMP' ) . $name ); } return $name; } /** * @param $filename * @return bool */ public function is_backup_archive( $filename ) { $filename = basename( $filename ); if ( ! substr( $filename, -3 ) == '.gz' || ! substr( $filename, -4 ) == '.bz2' || ! substr( $filename, -4 ) == '.tar' || ! substr( $filename, -4 ) == '.zip' ) return FALSE; $filename = str_replace( array( '.gz', '.bz2', '.tar', '.zip' ), '', $filename ); $datevars = array( '%d', '%j', '%m', '%n', '%Y', '%y', '%a', '%A', '%B', '%g', '%G', '%h', '%H', '%i', '%s' ); $dateregex = array( '(0[1-9]|[12][0-9]|3[01])', '([1-9]|[12][0-9]|3[01])', '(0[1-9]|1[012])', '([1-9]|1[012])', '((19|20|21)[0-9]{2})', '([0-9]{2})', '(am|pm)', '(AM|PM)', '([0-9]{3})', '([1-9]|1[012])', '([0-9]|1[0-9]|2[0-3])', '(0[1-9]|1[012])', '(0[0-9]|1[0-9]|2[0-3])', '([0-5][0-9])', '([0-5][0-9])' ); $regex = "/^" . str_replace( $datevars, $dateregex, self::sanitize_file_name( $this->job[ 'archivename' ] ) ) . "$/"; preg_match( $regex, $filename, $matches ); if ( ! empty( $matches[ 0 ] ) && $matches[ 0 ] == $filename ) return TRUE; return FALSE; } /** * Sanitizes a filename, replacing whitespace with underscores. * * @param $filename * * @return mixed */ public static function sanitize_file_name( $filename ) { $filename = trim( $filename ); $special_chars = array( "?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr(0) ); $filename = str_replace( $special_chars, '', $filename ); $filename = str_replace( array( ' ', '%20', '+' ), '_', $filename ); $filename = str_replace( array( "\n", "\t", "\r" ), '-', $filename ); $filename = trim( $filename, '.-_' ); return $filename; } /** * Get the Process id of working script * * @return int */ private static function get_pid( ) { if ( function_exists( 'posix_getpid' ) ) { return posix_getpid(); } elseif ( function_exists( 'getmypid' ) ) { return getmypid(); } return -1; } /** * For storing and getting data in/from a extra temp file * * @param string $storage The name of the storage * @param array $data data to save in storage * @return array|mixed|null data from storage */ public function data_storage( $storage = NULL, $data = NULL ) { if ( empty( $storage ) ) return $data; $storage = strtolower( $storage ); $file = BackWPup::get_plugin_data( 'temp' ) . 'backwpup-' . BackWPup::get_plugin_data( 'hash' ) . '-'.$storage.'.json'; if ( ! empty( $data ) ) { file_put_contents( $file, json_encode( $data ) ); } elseif ( is_readable( $file ) ) { $json = file_get_contents( $file ); $data = json_decode( $json, TRUE ); } return $data; } /** * Get list of Folder for backup * * @return array folder list */ public function get_folders_to_backup( ) { $file = BackWPup::get_plugin_data( 'temp' ) . 'backwpup-' . BackWPup::get_plugin_data( 'hash' ) . '-folder.php'; if ( ! file_exists( $file ) ) return array(); $folders = array(); $file_data = file( $file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); foreach( $file_data as $folder ) { $folder = trim( str_replace( array( 'count_folder = count( $folders ); return $folders; } /** * Add a Folders to Folder list that should be backup * * @param array $folders folder to add * @param bool $new overwrite existing file */ public function add_folders_to_backup( $folders = array(), $new = FALSE ) { if ( ! is_array( $folders ) ) $folders = (array) $folders; $file = BackWPup::get_plugin_data( 'temp' ) . 'backwpup-' . BackWPup::get_plugin_data( 'hash' ) . '-folder.php'; if ( ! file_exists( $file ) || $new ) file_put_contents( $file, '