} pb_backupbuddy::save(); //pb_backupbuddy::alert( 'Edited schedule `' . htmlentities( $submitted_schedule['data']['title'] ) . '`.' ); $editedSchedule = $submitted_schedule['data']; backupbuddy_core::addNotification('schedule_updated', 'Backup schedule updated', 'An existing schedule "' . $editedSchedule['title'] . '" has been updated.', $editedSchedule); } } elseif (count($submitted_schedule['errors']) > 0) { foreach ($submitted_schedule['errors'] as $error) { pb_backupbuddy::alert($error); } } $data['schedule_form'] = $schedule_form; /***** END ADDING (or editing) SCHEDULE AND PROCESSING FORM *****/ // Validate that all internal schedules are properly registered in the WordPress cron. require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::validate_bb_schedules_in_wp(); $schedules = array(); foreach (pb_backupbuddy::$options['schedules'] as $schedule_id => $schedule) { $profile = pb_backupbuddy::$options['profiles'][(int) $schedule['profile']]; $title = esc_html($schedule['title']); if ($profile['type'] == 'full') { $type = 'Full'; } elseif ($profile['type'] == 'files') { $type = 'Files only'; } elseif ($profile['type'] == 'db') { $type = 'Database only'; } else { $type = 'Unknown (' . $schedule['type'] . ')'; } $type = $profile['title'] . ' (' . $type . ')'; $interval = $schedule['interval'];
private static function _verb_confirmDeployment() { $serial = pb_backupbuddy::_POST('serial'); require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::remove_temp_tables($serial); die(json_encode(array('success' => true))); }
<?php backupbuddy_core::verifyAjaxAccess(); // Note: importbuddy, backup files, etc should have already been cleaned up by importbuddy itself at this point. $serial = pb_backupbuddy::_POST('serial'); $direction = pb_backupbuddy::_POST('direction'); pb_backupbuddy::load(); if ('pull' == $direction) { // Local so clean up here. require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::cleanup_temp_tables($serial); die('1'); } elseif ('push' == $direction) { // Remote so call API to clean up. require_once pb_backupbuddy::plugin_path() . '/classes/remote_api.php'; $destinationID = pb_backupbuddy::_POST('destinationID'); if (!isset(pb_backupbuddy::$options['remote_destinations'][$destinationID])) { die('Error #8383983: Invalid destination ID `' . htmlentities($destinationID) . '`.'); } $destinationArray = pb_backupbuddy::$options['remote_destinations'][$destinationID]; if ('site' != $destinationArray['type']) { die('Error #8378332: Destination with ID `' . htmlentities($destinationID) . '` not of "site" type.'); } $apiKey = $destinationArray['api_key']; $apiSettings = backupbuddy_remote_api::key_to_array($apiKey); if (false === ($response = backupbuddy_remote_api::remoteCall($apiSettings, 'confirmDeployment', array('serial' => $serial), 30, null, null, null, null, null, null, null, $returnRaw = true))) { $message = 'Error #2378378324. Unable to confirm remote deployment with serial `' . $serial . '` via remote API. This is a non-fatal warning. BackupBuddy will automatically clean up temporary data later.'; pb_backupbuddy::status('error', $message); die($message); } else { if (false === ($response_decoded = json_decode($response, true))) {
foreach ($crons as $timestamp => &$cron) { if (isset($cron[$hook])) { unset($cron[$hook]); } if (empty($cron)) { unset($crons[$timestamp]); } } } } update_option('cron', $crons); } // ********** END 6.4.0.12 UPGRADE ********** // ********** BEGIN 6.4.0.13 UPGRADE ********** require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::remove_wp_schedules_with_no_bb_schedule(); // Handles upgrading schedule tags, housekeeping tag, and removal of faulty old tags. // ********** END 6.4.0.13 UPGRADE ********** // ********** BEGIN 6.4.0.21 UPGRADE ********** pb_backupbuddy::$options['data_version'] = '13'; pb_backupbuddy::save(); // ********** END 6.4.0.21 UPGRADE ********** // ***** MISC BELOW ***** // Remote any saved plaintext confirmation of importbuddy password. if (isset(pb_backupbuddy::$options['importbuddy_pass_hash_confirm'])) { unset(pb_backupbuddy::$options['importbuddy_pass_hash_confirm']); pb_backupbuddy::save(); } // MISC SETUP: // Set up default error email notification email address if none is set. if (pb_backupbuddy::$options['email_notify_error'] == '') {
function post_backup($fail_mode = false, $cancel_backup = false) { pb_backupbuddy::status('message', __('Cleaning up after backup.', 'it-l10n-backupbuddy')); // Delete temporary data directory. if (file_exists($this->_backup['temp_directory'])) { pb_backupbuddy::status('details', __('Removing temp data directory.', 'it-l10n-backupbuddy')); pb_backupbuddy::$filesystem->unlink_recursive($this->_backup['temp_directory']); } // Delete temporary ZIP directory. if (file_exists(backupbuddy_core::getBackupDirectory() . 'temp_zip_' . $this->_backup['serial'] . '/')) { pb_backupbuddy::status('details', __('Removing temp zip directory.', 'it-l10n-backupbuddy')); pb_backupbuddy::$filesystem->unlink_recursive(backupbuddy_core::getBackupDirectory() . 'temp_zip_' . $this->_backup['serial'] . '/'); } if (true === $fail_mode) { pb_backupbuddy::status('warning', 'Backup archive limiting has been skipped since there was an error to avoid deleting potentially good backups to make room for a potentially bad backup.'); } else { $this->trim_old_archives(); // Clean up any old excess archives pushing us over defined limits in settings. } if (true === $cancel_backup) { pb_backupbuddy::status('details', 'Backup stopped so deleting backup ZIP file.'); $unlink_result = @unlink($this->_backup['archive_file']); if (true === $unlink_result) { pb_backupbuddy::status('details', 'Deleted stopped backup file.'); } else { pb_backupbuddy::status('error', 'Unable to delete stopped backup file. You should delete it manually as it may be damaged from stopping mid-backup. File to delete: `' . $this->_backup['archive_file'] . '`.'); } $this->_backup['finish_time'] = -1; //pb_backupbuddy::save(); $this->_backup_options->save(); } else { // Not cancelled. $this->_backup['archive_size'] = @filesize($this->_backup['archive_file']); pb_backupbuddy::status('details', __('Final ZIP file size', 'it-l10n-backupbuddy') . ': ' . pb_backupbuddy::$format->file_size($this->_backup['archive_size'])); pb_backupbuddy::status('archiveSize', pb_backupbuddy::$format->file_size($this->_backup['archive_size'])); if ($fail_mode === false) { // Not cancelled and did not fail so mark finish time. //error_log( print_r( $this->_backup_options->options, true ) ); $archiveFile = basename($this->_backup_options->options['archive_file']); // Calculate backup download URL, if any. //$downloadURL = pb_backupbuddy::ajax_url( 'download_archive' ) . '&backupbuddy_backup=' . $archiveFile; $downloadURL = ''; $abspath = str_replace('\\', '/', ABSPATH); // Change slashes to handle Windows as we store backup_directory with Linux-style slashes even on Windows. $backup_dir = str_replace('\\', '/', backupbuddy_core::getBackupDirectory()); if (FALSE !== stristr($backup_dir, $abspath)) { // Make sure file to download is in a publicly accessible location (beneath WP web root technically). //pb_backupbuddy::status( 'details', 'mydir: `' . $backup_dir . '`, abs: `' . $abspath . '`.'); $sitepath = str_replace($abspath, '', $backup_dir); $downloadURL = rtrim(site_url(), '/\\') . '/' . trim($sitepath, '/\\') . '/' . $archiveFile; } $integrityIsOK = '-1'; if (isset($this->_backup_options->options['integrity']['is_ok'])) { $integrityIsOK = $this->_backup_options->options['integrity']['is_ok']; } $destinations = array(); foreach ($this->_backup_options->options['steps'] as $step) { if ('send_remote_destination' == $step['function']) { $destinations[] = array('id' => $step['args'][0], 'title' => pb_backupbuddy::$options['remote_destinations'][$step['args'][0]]['title'], 'type' => pb_backupbuddy::$options['remote_destinations'][$step['args'][0]]['type']); } } pb_backupbuddy::status('details', 'Updating statistics for last backup completed and number of edits since last backup.'); $finishTime = microtime(true); pb_backupbuddy::$options['last_backup_finish'] = $finishTime; pb_backupbuddy::$options['last_backup_stats'] = array('archiveFile' => $archiveFile, 'archiveURL' => $downloadURL, 'archiveSize' => $this->_backup['archive_size'], 'start' => pb_backupbuddy::$options['last_backup_start'], 'finish' => $finishTime, 'type' => $this->_backup_options->options['profile']['type'], 'profileTitle' => htmlentities($this->_backup_options->options['profile']['title']), 'scheduleTitle' => $this->_backup_options->options['schedule_title'], 'integrityStatus' => $integrityIsOK, 'destinations' => $destinations); //error_log( print_r( pb_backupbuddy::$options['last_backup_stats'], true ) ); pb_backupbuddy::$options['edits_since_last'] = 0; // Reset edit stats for notifying user of how many posts/pages edited since last backup happened. pb_backupbuddy::save(); } } require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::cleanup_temp_dir(); if ($this->_backup['trigger'] == 'manual') { // Do nothing. No notifications as of pre-3.0 2012. } elseif ($this->_backup['trigger'] == 'deployment') { // Do nothing. No notifications. } elseif ($this->_backup['trigger'] == 'deployment_pulling') { // Do nothing. } elseif ($this->_backup['trigger'] == 'scheduled') { if (false === $fail_mode && false === $cancel_backup) { pb_backupbuddy::status('details', __('Sending scheduled backup complete email notification.', 'it-l10n-backupbuddy')); $message = 'completed successfully in ' . pb_backupbuddy::$format->time_duration(time() - $this->_backup['start_time']) . ".\n"; backupbuddy_core::mail_notify_scheduled($this->_backup['serial'], 'complete', __('Scheduled backup', 'it-l10n-backupbuddy') . ' "' . $this->_backup['schedule_title'] . '" ' . $message); } } else { pb_backupbuddy::status('error', 'Error #4343434. Unknown backup trigger `' . $this->_backup['trigger'] . '`.'); } pb_backupbuddy::status('message', __('Finished cleaning up.', 'it-l10n-backupbuddy')); if (true === $cancel_backup) { pb_backupbuddy::status('details', 'Backup cancellation complete.'); return false; } else { if (true === $fail_mode) { pb_backupbuddy::status('details', __('As this backup did not pass the integrity check you should verify it manually or re-scan. Integrity checks can fail on good backups due to permissions, large file size exceeding memory limits, etc. You may manually disable integrity check on the Settings page but you will no longer be notified of potentially bad backups.', 'it-l10n-backupbuddy')); } else { if ($this->_backup['trigger'] != 'deployment' && $this->_backup['trigger'] != 'deployment_pulling') { //$stats = stat( $this->_backup['archive_file'] ); //$sizeFormatted = pb_backupbuddy::$format->file_size( $stats['size'] ); pb_backupbuddy::status('archiveInfo', json_encode(array('file' => basename($this->_backup['archive_file']), 'url' => pb_backupbuddy::ajax_url('download_archive') . '&backupbuddy_backup=' . basename($this->_backup['archive_file'])))); } } } return true; }
$_POST['pb_backupbuddy_importbuddy_pass_hash_confirm'] = ''; } } // Set importbuddy dummy text to display in form box. Equal length to the provided password. $data['importbuddy_pass_dummy_text'] = str_pad('', pb_backupbuddy::$options['importbuddy_pass_length'], ')'); $_POST['pb_backupbuddy_importbuddy_pass_hash_confirm'] = ''; // Always clear confirmation after processing it. // Run periodic cleanup to make sure high security mode changes are applied. $lockMode = 0; if (isset($_POST['pb_backupbuddy_lock_archives_directory'])) { $lockMode = $_POST['pb_backupbuddy_lock_archives_directory']; } if ($lockMode != pb_backupbuddy::$options['lock_archives_directory']) { // Setting changed. require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::run_periodic(0); // 0 cleans up everything even if not very old. } /* BEGIN SAVE MULTISITE SPECIFIC SETTINGS IN SET OPTIONS SO THEY ARE AVAILABLE GLOBALLY */ if (is_multisite()) { // Save multisite export option to the global site/network options for global retrieval. $options = get_site_option('pb_' . pb_backupbuddy::settings('slug')); $options['multisite_export'] = pb_backupbuddy::_POST('pb_backupbuddy_multisite_export'); update_site_option('pb_' . pb_backupbuddy::settings('slug'), $options); unset($options); } /* END SAVE MULTISITE SPECIFIC SETTINGS IN SET OPTIONS SO THEY ARE AVAILABLE GLOBALLY */ // Load settings view. pb_backupbuddy::load_view('settings', $data); /* echo '<pre>';
function _housekeeping() { require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::run_periodic(); }
private static function _step_send_pending_files($startAt = 0) { // Load state into self::$_state & fileoptions object into self::$_stateObj. if (false === self::_load_state()) { return false; } if (0 == $startAt) { $startAt = self::$_state['stats']['last_filesend_startat']; pb_backupbuddy::status('details', 'Starting to send pending files at position `' . $startAt . '` based on stored stats position.'); } else { pb_backupbuddy::status('details', 'Starting to send pending files at position `' . $startAt . '` based on passed value.'); } if (false === self::_load_catalog()) { return false; } require_once pb_backupbuddy::plugin_path() . '/destinations/bootstrap.php'; // Truncate log if it is getting too large. Keeps newest half. self::_truncate_log(); // Loop through files in the catalog. $loopCount = 0; $checkCount = 0; $sendTimeSum = 0; $sendSizeSum = 0; $sendAttemptCount = 0; $logTruncateCheck = 0; $lastSendThisPass = false; $sendMoreRemain = false; $sendAttemptCount = 0; $lackSignatureData = 0; $tooManyAttempts = 0; foreach (self::$_catalog as $signatureFile => &$signatureDetails) { $loopCount++; if (0 != $startAt) { // Resuming... if ($loopCount < $startAt) { continue; } } $checkCount++; // Every X files that get sent, make sure log file is not getting too big AND back up catalog. if (0 == ($sendAttemptCount + 1) % 150) { // Backup catalog. self::backup_catalog(); } // If already backed up OR we do not have signature data yet then skip for now. if (0 != $signatureDetails['b'] || 0 == $signatureDetails['m']) { if (0 == $signatureDetails['m']) { $lackSignatureData++; } continue; } // If too many attempts have passed then skip. if ($signatureDetails['t'] >= self::MAX_SEND_ATTEMPTS) { $tooManyAttempts++; continue; } // Load destination settings. $destination_settings = self::get_destination_settings(); // If too many remote sends have failed today then give up for now since something is likely wrong. if (self::$_state['stats']['recent_send_fails'] > $destination_settings['max_daily_failures']) { $error = 'Error #5002: Too many file transfer failures have occurred so stopping transfers. We will automatically try again in 12 hours. Verify there are no remote file transfer problems. Check recently send file logs on Remote Destinations page. Don\'t want to wait? Pause Files process then select "Reset Send Attempts" under "Advanced Troubleshooting Options".'; backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $error); self::$_state['step']['last_status'] = $error; pb_backupbuddy::status('error', $error); return false; } // If this is not the first file we've sent this pass, see if we have enough time for more. if ($sendSizeSum > 0) { // Check if it appears we have enough time to send at least a full single chunk in this pass or if we need to pass off to a subsequent run. $send_speed = $sendSizeSum / 1048576 / $sendTimeSum; // Estimated speed at which we can send files out. Unit: MB / sec. $time_elapsed = microtime(true) - pb_backupbuddy::$start_time; $time_remaining = $destination_settings['max_time'] - ($time_elapsed + self::TIME_WIGGLE_ROOM); // Estimated time remaining before PHP times out. Unit: seconds. $size_possible_with_remaining_time = $send_speed * $time_remaining; // Size possible to send with remaining time (takes into account wiggle room). $size_to_send = $signatureDetails['s'] / 1048576; // Size we want to send this pass. Unit: MB. if ($destination_settings['max_burst'] < $size_to_send) { // If the chunksize is smaller than the full file then cap at sending that much. $size_to_send = $destination_settings['max_burst']; } if ($size_possible_with_remaining_time < $size_to_send) { // File (or chunk) is bigger than what we have time to send. $lastSendThisPass = true; $sendMoreRemain = true; $send_speed_status = 'Not enough time to send more. To continue in next live_periodic pass.'; } else { $send_speed_status = 'Enough time to send more. Preparing for send.'; } pb_backupbuddy::status('details', 'Not the first normal file to send this pass. Send speed: `' . $send_speed . '` MB/sec. Time elapsed: `' . $time_elapsed . '` sec. Time remaining (with wiggle): `' . $time_remaining . '` sec based on reported max time of `' . $destination_settings['max_time'] . '` sec. Size possible with remaining time: `' . $size_possible_with_remaining_time . '` MB. Size to chunk (greater of filesize or chunk): `' . $size_to_send . '` MB. Conclusion: `' . $send_speed_status . '`.'); } // end subsequent send time check. // NOT out of time so send this. if (true !== $lastSendThisPass) { // Run cleanup on send files. require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::trim_remote_send_stats($file_prefix = 'send-live_', $limit = $destination_settings['max_send_details_limit'], '', $purge_log = true); // Only keep last 5 send fileoptions. // Moved into trim_remote_send_stats(). backupbuddy_housekeeping::purge_logs( $file_prefix = 'status-remote_send-live_', $limit = $destination_settings['max_send_details_limit'] ); // Only keep last 5 send logs. // Increment try count for transfer attempts and save. $signatureDetails['t']++; self::$_catalogObj->save(); // Save position in case process starts over to prevent race conditions resulting in double send of files. $destination_settings['_live_next_step'] = array('send_pending_files', array()); // Next function and args to try and run after finishing send of this file. self::$_state['stats']['last_filesend_startat'] = $loopCount + 1; self::$_stateObj->save(); $full_file = ABSPATH . substr($signatureFile, 1); if (!file_exists($full_file)) { pb_backupbuddy::status('details', 'File in catalog no longer exists (or permissions block). Skipping send of file `' . $full_file . '`.'); } else { // Send file. AFTER success sending this Stash2 destination will automatically trigger the live_periodic processing _IF_ multipart send. If success or fail the we come back here to potentially send more files in the same PHP pass so small files don't each need their own PHP page run. Unless the process has restarted then this will still be the 'next' function to run. $send_id = 'live_' . md5($signatureFile) . '-' . pb_backupbuddy::random_string(6); pb_backupbuddy::status('details', 'Live starting send function.'); $sendTimeStart = microtime(true); // Close catalog & state while sending if > X size to prevent collisions. if ($signatureDetails['s'] > self::CLOSE_CATALOG_WHEN_SENDING_FILESIZE) { self::$_catalogObj = ''; self::$_stateObj = ''; } // Send file to remote. $sendAttemptCount++; $result = pb_backupbuddy_destinations::send($destination_settings, $full_file, $send_id, $delete_after = false, $isRetry = false, $trigger = 'live_periodic', $destination_id = backupbuddy_live::getLiveID()); // Re-open catalog (if closed). if (false === self::_load_state()) { pb_backupbuddy::status('error', 'Error #5489458443: Unable to re-open temporarily closed state.'); return false; } if (false === self::_load_catalog()) { pb_backupbuddy::status('error', 'Error #5489458443: Unable to re-open temporarily closed catalog.'); return false; } $sendTimeFinish = microtime(true); if (true === $result) { $result_status = 'Success sending in single pass.'; $sendTimeSum += $sendTimeFinish - $sendTimeStart; // Add to time sent sending. // Set a minimum threshold so small files don't make server appear slower than reality due to overhead. $minimum_size_threshold = self::MINIMUM_SIZE_THRESHOLD_FOR_SPEED_CALC; // Pretend file is at least 500k each. if ($signatureDetails['s'] < $minimum_size_threshold) { $sendSizeSum += $minimum_size_threshold; } else { $sendSizeSum += $signatureDetails['s']; // Add to size of data sent. } } elseif (false === $result) { self::$_state['stats']['recent_send_fails']++; $result_status = 'Failure sending in single/first pass. See log above for error details. Failed sends today: `' . self::$_state['stats']['recent_send_fails'] . '`.'; } elseif (is_array($result)) { $result_status = 'Chunking commenced. Ending sends for this pass.'; //$lastSendThisPass = true; // TODO: Ideally at this point we would have Live sleep until the large chunked file finished sending. } pb_backupbuddy::status('details', 'Live ended send files function. Status: ' . $result_status . '.'); } // end file exists. } // Check if we are done sending for this PHP pass/run. if (true === $lastSendThisPass) { break; } } // End foreach signatures. pb_backupbuddy::status('details', 'Checked `' . $checkCount . '` items for sending. Sent `' . $sendAttemptCount . '`. Skipped due to too many send attempts: `' . $tooManyAttempts . '`. Skipped due to lacking signature data: `' . $lackSignatureData . '`.'); if ($tooManyAttempts > 0) { $warning = 'Warning #5003. `' . $tooManyAttempts . '` files were skipped due to too many send attempts failing. Check the Remote Destinations page\'s Recently sent files list to check for errors of failed sends. To manually reset sends Pause the Files process and wait for it to finish, then select the Advanced Troubleshooting Option to "Reset Send Attempts".'; pb_backupbuddy::status('warning', $warning); backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $warning); } // Schedule next run if we still have more files to potentially send. if (true === $sendMoreRemain) { return array('Sending queued files', array($loopCount)); } else { // No more files. self::$_state['stats']['last_filesend_startat'] = 0; // Reset the startat location. pb_backupbuddy::status('details', 'No more files remain. Reset filesend startat position back to 0.'); return true; } }
success: function(data){ data = jQuery.trim( data ); if ( '1' == data ) { alert( 'Remote transfer aborted. This may take a moment to take effect.' ); } else { alert( 'Error #85448949. Unexpected server response. Details: `' + data + '`.' ); } } }); return false; }); }); </script> <?php require_once pb_backupbuddy::plugin_path() . '/classes/housekeeping.php'; backupbuddy_housekeeping::trim_remote_send_stats(); $remote_sends = array(); $send_fileoptions = pb_backupbuddy::$filesystem->glob_by_date(backupbuddy_core::getLogDirectory() . 'fileoptions/send-*.txt'); if (!is_array($send_fileoptions)) { $send_fileoptions = array(); } foreach ($send_fileoptions as $send_fileoption) { $send_id = str_replace('.txt', '', str_replace('send-', '', basename($send_fileoption))); pb_backupbuddy::status('details', 'About to load fileoptions data.'); require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php'; pb_backupbuddy::status('details', 'Fileoptions instance #23.'); $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = true, $ignore_lock = true, $create_file = false); if (true !== ($result = $fileoptions_obj->is_ok())) { pb_backupbuddy::status('error', __('Fatal Error #9034.32393. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result); return false; }