Пример #1
0
 function cron($method, $args, $rescheduleCount = 0)
 {
     //if ( ( '1' == pb_backupbuddy::$options['limit_single_cron_per_pass'] ) && ( $this->_methods_ran > 0 ) ) { // If limiting to one cron method per PHP load AND we have already ran one method this PHP process then chunk to next run.
     if (1 == 2) {
         // Disabled until 7.0.
         $rescheduleCount++;
         $nextRun = time() + 1;
         $options = array($args, $rescheduleCount);
         if ($rescheduleCount >= backupbuddy_constants::CRON_SINGLE_PASS_RESCHEDULE_LIMIT) {
             // Safety net to prevent runaway rescheduling.
             $message = 'Error #8399823: Max cron single pass reschedule limit of `' . backupbuddy_constants::CRON_SINGLE_PASS_RESCHEDULE_LIMIT . '` hit. Method: `' . $method . '`; Args: `' . print_r($options, true) . '`.';
             pb_backupbuddy::status('error', $message);
             if ('process_backup' == $method) {
                 // If backup process then log to serial log file.
                 pb_backupbuddy::status('error', $message, $args[0]);
             }
             return false;
         }
         if (false === backupbuddy_core::schedule_single_event($nextRun, $method, $options)) {
             $message = 'Error #838923: Unable to reschedule cron based on setting to limit single cron per pass enabled. Method: `' . $method . '`; Args: `' . print_r($options, true) . '`. Reschedule count: `' . $rescheduleCount . '`.';
             pb_backupbuddy::status('error', $message);
             if ('process_backup' == $method) {
                 // If backup process then log to serial log file.
                 pb_backupbuddy::status('error', $message, $args[0]);
             }
             return false;
         }
         $message = 'Rescheduled cron as setting to limit single cron per pass enabled. Details: `' . print_r($options, true) . '`. Reschedule count: `' . $rescheduleCount . '`.';
         pb_backupbuddy::status('details', $message);
         if ('process_backup' == $method) {
             // If backup process then log to serial log file.
             pb_backupbuddy::status('details', $message, $args[0]);
         }
         /*
          *		TODO:	Once PING API is available, request a ping in the future so we make sure this actually runs reasonably soon.
          *				Because we need a delay we are not firing off the cron here immediately so there will be no chaining of PHP
          *				which may result in large delays before the next process if there's little site traffic.
          */
         //error_log( 'rescheduled_cron' );
         return true;
     }
     $this->_methods_ran++;
     return call_user_func_array(array(&$this, '_' . $method), $args);
 }
Пример #2
0
 public static function schedule_php_memory_tests($force_run = false)
 {
     pb_backupbuddy::status('details', 'About to schedule PHP memory tests.');
     if (pb_backupbuddy::$options['php_memory_test_minimum_interval'] <= 0) {
         pb_backupbuddy::status('warnings', 'PHP memory test disabled based on advanced settings.');
         return false;
     }
     // Don't run memory test too often.
     if (pb_backupbuddy::$options['last_tested_php_memory'] > 0) {
         // if it's run at least once...
         $elapsed = time() - pb_backupbuddy::$options['last_tested_php_memory'];
         if ($elapsed < pb_backupbuddy::$options['php_memory_test_minimum_interval']) {
             // Not enough time elapsed since last run.
             pb_backupbuddy::status('details', 'Not enough time elapsed since last PHP memory test interval. Waiting until next housekeeping (or longer). Elapsed: `' . $elapsed . '`. Interval limit: `' . pb_backupbuddy::$options['php_memory_test_minimum_interval'] . '`.');
             return;
         }
     }
     // Schedule to run test.
     $cronArgs = array($schedule_results = true);
     $schedule_result = backupbuddy_core::schedule_single_event(time(), 'php_memory_test', $cronArgs);
     if (true === $schedule_result) {
         pb_backupbuddy::status('details', 'PHP memory test cron event scheduled.');
     } else {
         pb_backupbuddy::status('error', 'PHP memory test cron event FAILED to be scheduled.');
     }
     // Spawn now if enabled.
     if ('1' != pb_backupbuddy::$options['skip_spawn_cron_call']) {
         pb_backupbuddy::status('details', 'Spawning cron now.');
         update_option('_transient_doing_cron', 0);
         // Prevent cron-blocking for next item.
         spawn_cron(time() + 150);
         // Adds > 60 seconds to get around once per minute cron running limit.
     }
 }
Пример #3
0
            pb_backupbuddy::alert('Error: Unable to delete `' . $item . '`. Verify permissions.');
        }
    }
    if (count($deleted_files) > 0) {
        pb_backupbuddy::alert('Deleted ' . implode(', ', $deleted_files) . '.');
        delete_transient('pb_backupbuddy_stashquota_' . $itxapi_username);
        // Delete quota transient since it probably has changed now.
    }
    echo '<br>';
}
// Handle copying files to local
if (pb_backupbuddy::_GET('cpy_file') != '') {
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating Stash copy.');
    backupbuddy_core::schedule_single_event(time(), 'process_remote_copy', array('stash', pb_backupbuddy::_GET('cpy_file'), $settings));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
// Handle download link
if (pb_backupbuddy::_GET('downloadlink_file') != '') {
    $link = $s3->get_object($manage_data['bucket'], $manage_data['subkey'] . $remote_path . pb_backupbuddy::_GET('downloadlink_file'), array('preauth' => time() + 3600));
    pb_backupbuddy::alert('You may download this backup (' . pb_backupbuddy::_GET('downloadlink_file') . ') with <a href="' . $link . '">this link</a>. The link is valid for one hour.');
    echo '<br>';
}
// QUOTA INFORMATION.
$account_info = pb_backupbuddy_destination_stash::get_quota(array('itxapi_username' => $itxapi_username, 'itxapi_password' => $itxapi_password), false);
/*
echo '<pre>';
Пример #4
0
 public static function send($settings = array(), $files = array(), $send_id = '', $delete_after = false)
 {
     global $pb_backupbuddy_destination_errors;
     if ('1' == $settings['disabled']) {
         $pb_backupbuddy_destination_errors[] = __('Error #48933: This destination is currently disabled. Enable it under this destination\'s Advanced Settings.', 'it-l10n-backupbuddy');
         return false;
     }
     if (!is_array($files)) {
         $files = array($files);
     }
     self::$_timeStart = microtime(true);
     if (count($files) > 1) {
         $message = 'Error #84545894585: This destination currently only supports one file per send.';
         pb_backupbuddy::status('error', $message);
         global $pb_backupbuddy_destination_errors;
         $pb_backupbuddy_destination_errors[] = $message;
         return false;
     }
     require_once pb_backupbuddy::plugin_path() . '/classes/remote_api.php';
     $apiSettings = backupbuddy_remote_api::key_to_array($settings['api_key']);
     if (site_url() == $apiSettings['siteurl']) {
         $message = 'Error #4389843. You are trying to use this site\'s own API key. You must use the API key from the remote destination site.';
         pb_backupbuddy::status('error', $message);
         global $pb_backupbuddy_destination_errors;
         $pb_backupbuddy_destination_errors[] = $message;
         return false;
     }
     $apiURL = $apiSettings['siteurl'];
     $file = $files[0];
     $filePath = '';
     if ('' != $settings['sendFilePath']) {
         $filePath = $settings['sendFilePath'];
     }
     $maxPayload = $settings['max_payload'] * 1024 * 1024;
     // Convert to bytes.
     $encodeReducedPayload = floor(($settings['max_payload'] - $settings['max_payload'] * 0.37) * 1024 * 1024);
     // Take into account 37% base64 encoding overhead. Convert to bytes. Remove any decimals down via floor.
     // Open file for reading.
     if (FALSE === ($fs = @fopen($file, 'r'))) {
         pb_backupbuddy::status('error', 'Error #438934894: Unable to open file `' . $file . '` for reading.');
         return false;
     }
     // If chunked resuming then seek to the correct place in the file.
     if ('' != $settings['resume_point'] && $settings['resume_point'] > 0) {
         // Resuming send of a partially transferred file.
         if (0 !== fseek($fs, $settings['resume_point'])) {
             // Returns 0 on success.
             pb_backupbuddy::status('error', 'Error #327834783: Failed to seek file to resume point `' . $settings['resume_point'] . '` via fseek().');
             return false;
         }
         $prevPointer = $settings['resume_point'];
     } else {
         // New file send.
         $size = filesize($file);
         $encodedSize = $size * 0.37 + $size;
         pb_backupbuddy::status('details', 'File size of file to send: ' . pb_backupbuddy::$format->file_size($size) . '. After encoding overhead: ' . pb_backupbuddy::$format->file_size($encodedSize));
         if ($encodedSize > $maxPayload) {
             $settings['chunks_total'] = ceil($encodedSize / $maxPayload);
             // $maxPayload );
             pb_backupbuddy::status('details', 'This file + encoding exceeds the maximum per-chunk payload size so will be read in and sent in chunks of ' . $settings['max_payload'] . 'MB (' . $maxPayload . ' bytes) totaling approximately ' . $settings['chunks_total'] . ' chunks.');
         } else {
             pb_backupbuddy::status('details', 'This file + encoding does not exceed per-chunk payload size of ' . $settings['max_payload'] . 'MB (' . $maxPayload . ' bytes) so sending in one pass.');
         }
         $prevPointer = 0;
     }
     pb_backupbuddy::status('details', 'Reading in `' . $encodeReducedPayload . '` bytes at a time to send.');
     $dataRemains = true;
     //$loopCount = 0;
     //$loopTimeSum = 0; // Used for average send time per chunk.
     while (TRUE === $dataRemains && FALSE !== ($fileData = fread($fs, $encodeReducedPayload))) {
         // Grab one chunk of data at a time.
         pb_backupbuddy::status('details', 'Read in file data.');
         if (feof($fs)) {
             pb_backupbuddy::status('details', 'Read to end of file (feof true). No more chunks left after this send.');
             $dataRemains = false;
         }
         $isFileTest = false;
         if (false !== stristr(basename($file), 'remote-send-test.php')) {
             $isFileTest = true;
             $settings['sendType'] = 'test';
         }
         if (true === $dataRemains) {
             $isFileDone = false;
         } else {
             $isFileDone = true;
         }
         if (!isset($size)) {
             $size = '';
         }
         pb_backupbuddy::status('details', 'Connecting to remote server to send data.');
         $response = backupbuddy_remote_api::remoteCall($apiSettings, 'sendFile_' . $settings['sendType'], array(), $settings['max_time'], $file, $fileData, $prevPointer, $isFileTest, $isFileDone, $size, $filePath);
         unset($fileData);
         // Free up memory.
         $settings['chunks_sent']++;
         if (true === $dataRemains) {
             // More chunks remain.
             pb_backupbuddy::status('details', 'Connection finished sending part ' . $settings['chunks_sent'] . ' of ~' . $settings['chunks_total'] . '.');
         } else {
             // No more chunks remain.
             pb_backupbuddy::status('details', 'Connection finished sending final part ' . $settings['chunks_sent'] . '.');
         }
         if (false === $response) {
             echo implode(', ', backupbuddy_remote_api::getErrors()) . ' ';
             pb_backupbuddy::status('error', 'Errors encountered details: ' . implode(', ', backupbuddy_remote_api::getErrors()));
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = backupbuddy_remote_api::getErrors();
             return false;
             //implode( ', ', backupbuddy_remote_api::getErrors() );
         }
         if (FALSE === ($prevPointer = ftell($fs))) {
             pb_backupbuddy::status('error', 'Error #438347844: Unable to get ftell pointer of file handle for passing to prevPointer.');
             @fclose($fs);
             return false;
         } else {
             pb_backupbuddy::status('details', 'File pointer: `' . $prevPointer . '`.');
         }
         if (true === $dataRemains) {
             // More data remains so see if we need to consider chunking to a new PHP process.
             // If we are within X second of reaching maximum PHP runtime then stop here so that it can be picked up in another PHP process...
             if (microtime(true) - self::$_timeStart + self::TIME_WIGGLE_ROOM >= $settings['max_time']) {
                 pb_backupbuddy::status('message', 'Approaching limit of available PHP chunking time of `' . $settings['max_time'] . '` sec. Ran for ' . round(microtime(true) - self::$_timeStart, 3) . ' sec. Proceeding to use chunking.');
                 @fclose($fs);
                 // Tells next chunk where to pick up.
                 $settings['resume_point'] = $prevPointer;
                 // Schedule cron.
                 $cronTime = time();
                 $cronArgs = array($settings, $files, $send_id, $delete_after);
                 $cronHashID = md5($cronTime . serialize($cronArgs));
                 $cronArgs[] = $cronHashID;
                 $schedule_result = backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
                 if (true === $schedule_result) {
                     pb_backupbuddy::status('details', 'Next Site chunk step cron event scheduled.');
                 } else {
                     pb_backupbuddy::status('error', 'Next Site chunk step cron even FAILED to be scheduled.');
                 }
                 spawn_cron(time() + 150);
                 // Adds > 60 seconds to get around once per minute cron running limit.
                 update_option('_transient_doing_cron', 0);
                 // Prevent cron-blocking for next item.
                 return array($prevPointer, 'Sent part ' . $settings['chunks_sent'] . ' of ~' . $settings['chunks_total'] . ' parts.');
                 // filepointer location, elapsed time during the import
             } else {
                 // End if.
                 pb_backupbuddy::status('details', 'Not approaching time limit.');
             }
         } else {
             pb_backupbuddy::status('details', 'No more data remains (eg for chunking) so finishing up.');
         }
     }
     // end while data remains in file.
     // Update fileoptions stats.
     pb_backupbuddy::status('details', 'About to load fileoptions data.');
     require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
     pb_backupbuddy::status('details', 'Fileoptions instance #20.');
     $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
     if (true !== ($result = $fileoptions_obj->is_ok())) {
         pb_backupbuddy::status('error', __('Fatal Error #9034.279327. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
         return false;
     }
     pb_backupbuddy::status('details', 'Fileoptions data loaded.');
     $fileoptions =& $fileoptions_obj->options;
     $fileoptions['finish_time'] = microtime(true);
     $fileoptions['status'] = 'success';
     $fileoptions['_multipart_status'] = 'Sent all parts.';
     if (isset($uploaded_speed)) {
         $fileoptions['write_speed'] = $uploaded_speed;
     }
     $fileoptions_obj->save();
     unset($fileoptions);
     // Made it this far so completed!
     pb_backupbuddy::status('message', 'Finished sending file. Took ' . round(microtime(true) - self::$_timeStart, 3) . ' seconds this round.');
     pb_backupbuddy::status('deployFileSent', 'File sent.');
     return true;
 }
Пример #5
0
 public static function remoteSendRetry(&$fileoptions_obj, $send_id, $maximumRetries = 1)
 {
     // Destination settings are stored for this destination so see if we can retry sending it (if settings permit).
     if (isset($fileoptions_obj->options['destinationSettings']) && count($fileoptions_obj->options['destinationSettings']) > 0) {
         /*
         echo '<pre>';
         print_r( $fileoptions_obj->options );
         echo '</pre>';
         */
         $destination_settings = $fileoptions_obj->options['destinationSettings'];
         // these are the latest; includes info needed for chunking too.
         //$send_id = $fileoptions_obj->options['sendID'];
         $delete_after = $fileoptions_obj->options['deleteAfter'];
         $retries = $fileoptions_obj->options['retries'];
         $file = $fileoptions_obj->options['file'];
         if ($retries < $maximumRetries) {
             pb_backupbuddy::status('details', 'Timed out remote send has not exceeded retry limit (`' . $maximumRetries . '`). Trying to send again.');
             //$fileoptions_obj->options['retries']++;
             //$fileoptions_obj->save(); // NOTE: Retry count now updates in bootstrap.php send() function. Only leaving this here temporarily to help get rid of failed resends from accumulating with old format.
             // Schedule send of this piece.
             pb_backupbuddy::status('details', 'Scheduling cron to send to this remote destination...');
             $cronArgs = array($destination_settings, $file, $send_id, $delete_after, $identifier = '', $isRetry = true);
             /*
             echo 'cronargs: ';
             echo '<pre>';
             print_r( $cronArgs );
             echo '</pre>';
             */
             $schedule_result = backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
             if ($schedule_result === FALSE) {
                 $error = 'Error scheduling file transfer. Please check your BackupBuddy error log for details. A plugin may have prevented scheduling or the database rejected it.';
                 pb_backupbuddy::status('error', $error);
                 echo $error;
             } else {
                 pb_backupbuddy::status('details', 'Cron to send to remote destination scheduled.');
             }
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             return true;
         } else {
             pb_backupbuddy::status('details', 'Maximum remote send timeout retries (`' . $maximumRetries . '`) passed to function met. Not resending.');
             return false;
         }
     }
 }
Пример #6
0
            $delete_count++;
            // Delete Rackspace file
            $container->delete_object($rsfile);
        }
    }
    if ($delete_count > 0) {
        pb_backupbuddy::alert(sprintf(_n('Deleted %d file', 'Deleted %d files', $delete_count, 'it-l10n-backupbuddy'), $delete_count));
    }
    echo '<br>';
}
// Copy Rackspace backup to the local backup files
if (!empty($_GET['cpy_file'])) {
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating Rackspace copy.');
    backupbuddy_core::schedule_single_event(time(), 'process_rackspace_copy', array($_GET['cpy_file'], $rs_username, $rs_api_key, $rs_container, $rs_server));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
// List objects in container
/*
if ( $rs_path != '' ) {
	$results = $container->get_objects( 0, NULL, 'backup-', $rs_path );
} else {
*/
$results = $container->get_objects(0, NULL, 'backup-');
/* } */
$urlPrefix = pb_backupbuddy::ajax_url('remoteClient') . '&destination_id=' . htmlentities(pb_backupbuddy::_GET('destination_id'));
?>
Пример #7
0
 function cron_next_step($spawn_cron = true, $future_offset = 0)
 {
     if ('1' == pb_backupbuddy::$options['skip_spawn_cron_call']) {
         pb_backupbuddy::status('details', 'Advanced option to skip call to spawn cron enabled. Setting to skip spawn_cron() call.');
         $spawn_cron = false;
     }
     pb_backupbuddy::status('details', 'Scheduling Cron for `' . $this->_backup['serial'] . '`.');
     // Need to make sure the database connection is active. Sometimes it goes away during long bouts doing other things -- sigh.
     // This is not essential so use include and not require (suppress any warning)
     @(include_once pb_backupbuddy::plugin_path() . '/lib/wpdbutils/wpdbutils.php');
     if (class_exists('pluginbuddy_wpdbutils')) {
         global $wpdb;
         $dbhelper = new pluginbuddy_wpdbutils($wpdb);
         if (!$dbhelper->kick()) {
             pb_backupbuddy::status('error', __('Database Server has gone away, unable to schedule next backup step. The backup cannot continue. This is most often caused by mysql running out of memory or timing out far too early. Please contact your host.', 'it-l10n-backupbuddy'));
             pb_backupbuddy::status('haltScript', '');
             // Halt JS on page.
             return false;
         }
     } else {
         pb_backupbuddy::status('details', __('Database Server connection status unverified.', 'it-l10n-backupbuddy'));
     }
     // Schedule event.
     $cron_time = time() + $future_offset;
     $cron_tag = pb_backupbuddy::cron_tag('process_backup');
     $cron_args = array($this->_backup['serial']);
     pb_backupbuddy::status('details', 'Scheduling next step to run at `' . $cron_time . '` (localized time: ' . pb_backupbuddy::$format->date(pb_backupbuddy::$format->localize_time($cron_time)) . ') with cron tag `' . $cron_tag . '` and serial arguments `' . implode(',', $cron_args) . '`.');
     $schedule_result = backupbuddy_core::schedule_single_event($cron_time, $cron_tag, $cron_args);
     if ($schedule_result === false) {
         pb_backupbuddy::status('error', 'Unable to schedule next cron step. Verify that another plugin is not preventing / conflicting.');
     } else {
         pb_backupbuddy::status('details', 'Next step scheduled.');
         pb_backupbuddy::status('startAction', 'cronPass');
         pb_backupbuddy::status('cronParams', base64_encode(json_encode(array('time' => $cron_time, 'tag' => $cron_tag, 'args' => $cron_args))));
     }
     update_option('_transient_doing_cron', 0);
     // Prevent cron-blocking for next item.
     // Spawn cron.
     if ($spawn_cron === true) {
         pb_backupbuddy::status('details', 'Calling spawn_cron().');
         spawn_cron(time() + 150);
         // Adds > 60 seconds to get around once per minute cron running limit.
     } else {
         pb_backupbuddy::status('details', 'Not calling spawn_cron().');
     }
     pb_backupbuddy::status('details', 'About to run next step. If the backup does not proceed within 15 seconds then something is interfering with the WordPress CRON system such as: server loopback issues, caching plugins, or scheduling plugins. Try disabling other plugins to see if it resolves issue.  Check the Server Information page cron section to see if the next BackupBuddy step is scheduled to run. Enable "Classic" backup mode on the "Settings" page to rule out non-cron issues.');
     return;
 }
Пример #8
0
 public static function send($settings = array(), $file, $send_id = '', $delete_after = false)
 {
     global $pb_backupbuddy_destination_errors;
     if ('1' == $settings['disabled']) {
         $pb_backupbuddy_destination_errors[] = __('Error #48933: This destination is currently disabled. Enable it under this destination\'s Advanced Settings.', 'it-l10n-backupbuddy');
         return false;
     }
     $settings = self::_init($settings);
     // Handles formatting & sanitizing settings.
     $chunkSizeBytes = $settings['max_burst'] * 1024 * 1024;
     // Send X mb at a time to limit memory usage.
     self::$_timeStart = microtime(true);
     if (pb_backupbuddy::$options['log_level'] == '3') {
         // Full logging enabled.
         pb_backupbuddy::status('details', 'Settings due to log level: `' . print_r($settings, true) . '`.');
     }
     // Initiate multipart upload.
     if ('' == $settings['_multipart_id']) {
         // New transfer. Note: All transfers are handled as presumed multiparts for ease.
         // Handle chunking of file into a multipart upload (if applicable).
         $file_size = filesize($file);
         pb_backupbuddy::status('details', 'File size of `' . pb_backupbuddy::$format->file_size($file_size) . '`.');
         if ('1' != $settings['stash_mode']) {
             // About to chunk so cleanup any previous hanging multipart transfers.
             self::multipart_cleanup($settings);
         }
         // Initiate multipart upload with S3.
         pb_backupbuddy::status('details', 'Initiating multipart transfer.');
         $thisCall = array('Bucket' => $settings['bucket'], 'Key' => $settings['directory'] . basename($file), 'StorageClass' => $settings['storage'], 'ServerSideEncryption' => 'AES256');
         if ('1' == $settings['stash_mode']) {
             $thisCall['Key'] = $settings['_stash_object'];
             unset($thisCall['StorageClass']);
         }
         try {
             $response = self::$_client->createMultipartUpload($thisCall);
         } catch (Exception $e) {
             if (pb_backupbuddy::$options['log_level'] == '3') {
                 // Full logging enabled.
                 pb_backupbuddy::status('details', 'Call details due to logging level: `' . print_r($thisCall, true) . '`.');
             }
             return self::_error('Error #389383: Unable to initiate multipart upload. Details: `' . $e->getMessage() . '`.');
         }
         // Made it here so SUCCESS initiating multipart!
         $upload_id = (string) $response['UploadId'];
         pb_backupbuddy::status('details', 'Initiated multipart upload with ID `' . $upload_id . '`.');
         $backup_type = backupbuddy_core::getBackupTypeFromFile($file);
         // Calculate multipart settings.
         $multipart_destination_settings = $settings;
         $multipart_destination_settings['_multipart_id'] = $upload_id;
         $multipart_destination_settings['_multipart_partnumber'] = 0;
         $multipart_destination_settings['_multipart_file'] = $file;
         $multipart_destination_settings['_multipart_remotefile'] = $settings['directory'] . basename($file);
         if ('1' == $settings['stash_mode']) {
             $multipart_destination_settings['_multipart_remotefile'] = $settings['_stash_object'];
         }
         $multipart_destination_settings['_multipart_counts'] = self::_get_multipart_counts($file_size, $settings['max_burst'] * 1024 * 1024);
         // Size of chunks expected to be in bytes.
         $multipart_destination_settings['_multipart_backup_type'] = $backup_type;
         $multipart_destination_settings['_multipart_backup_size'] = $file_size;
         $multipart_destination_settings['_multipart_etag_parts'] = array();
         //pb_backupbuddy::status( 'details', 'Multipart settings to pass:'******'_multipart_status'] = 'Starting send of ' . count( $multipart_destination_settings['_multipart_counts'] ) . ' parts.';
         pb_backupbuddy::status('details', 'Multipart initiated; passing over to send first chunk this run.');
         $settings = $multipart_destination_settings;
         // Copy over settings.
         unset($multipart_destination_settings);
     }
     // end initiating multipart.
     // Send parts.
     $backup_type = str_replace('/', '', $settings['_multipart_backup_type']);
     // For use later by file limiting.
     $backup_size = $settings['_multipart_backup_size'];
     $maxTime = $settings['max_time'];
     if ('' == $maxTime || !is_numeric($maxTime)) {
         pb_backupbuddy::status('details', 'Max time not set in settings so detecting server max PHP runtime.');
         $maxTime = backupbuddy_core::detectMaxExecutionTime();
     }
     pb_backupbuddy::status('details', 'Using max runtime: `' . $maxTime . '`.');
     // Open file for streaming.
     $f = @fopen($settings['_multipart_file'], 'r');
     if (false === $f) {
         return self::_error('Error #437734. Unable to open file `' . $settings['_multipart_file'] . '` to send. Did it get deleted?');
     }
     $fileDone = false;
     while (!$fileDone && !feof($f)) {
         $sendStart = microtime(true);
         if (!isset($settings['_retry_stash_confirm']) || true !== $settings['_retry_stash_confirm']) {
             // Skip send if only needing to confirm.
             // Made it here so success sending part. Increment for next part to send.
             $settings['_multipart_partnumber']++;
             if (!isset($settings['_multipart_counts'][$settings['_multipart_partnumber'] - 1]['seekTo'])) {
                 pb_backupbuddy::status('error', 'Error #8239933: Missing multipart partnumber to seek to. Settings array: `' . print_r($settings, true) . '`.');
             }
             if (-1 == fseek($f, (int) $settings['_multipart_counts'][$settings['_multipart_partnumber'] - 1]['seekTo'])) {
                 return self::_error('Error #833838: Unable to fseek file.');
             }
             pb_backupbuddy::status('details', 'Beginning upload of part `' . $settings['_multipart_partnumber'] . '` of `' . count($settings['_multipart_counts']) . '` parts of file `' . $settings['_multipart_file'] . '` to remote location `' . $settings['_multipart_remotefile'] . '` with multipart ID `' . $settings['_multipart_id'] . '`.');
             $contentLength = (int) $settings['_multipart_counts'][$settings['_multipart_partnumber'] - 1]['length'];
             $uploadArr = array('Bucket' => $settings['bucket'], 'Key' => $settings['_multipart_remotefile'], 'UploadId' => $settings['_multipart_id'], 'PartNumber' => $settings['_multipart_partnumber'], 'ContentLength' => $contentLength, 'Body' => fread($f, $contentLength));
             //pb_backupbuddy::status( 'details', 'Send array: `' . print_r( $uploadArr, true ) . '`.' );
             //error_log( print_r( $uploadArr, true ) );
             try {
                 $response = self::$_client->uploadPart($uploadArr);
             } catch (Exception $e) {
                 @fclose($f);
                 return self::_error('Error #3897923: Unable to upload file part for multipart upload of ID `' . $settings['_multipart_id'] . '`. Details: `' . $e->getMessage() . '`.');
             }
             self::$_chunksSentThisRound++;
             $settings['_multipart_etag_parts'][] = array('PartNumber' => $settings['_multipart_partnumber'], 'ETag' => $response['ETag']);
             if (pb_backupbuddy::$options['log_level'] == '3') {
                 // Full logging enabled.
                 pb_backupbuddy::status('details', 'Success sending chunk. Upload details due to log level: `' . print_r($response, true) . '`.');
             } else {
                 pb_backupbuddy::status('details', 'Success sending chunk. Enable full logging for upload result details.');
             }
             $uploaded_size = $contentLength;
             $elapseTime = microtime(true) - $sendStart;
             if (0 == $elapseTime) {
                 $elapseTime = 1;
             }
             $uploaded_speed = $uploaded_size / $elapseTime;
             pb_backupbuddy::status('details', 'Uploaded size this burst: `' . pb_backupbuddy::$format->file_size($uploaded_size) . '`, Start time: `' . $sendStart . '`. Finish time: `' . microtime(true) . '`. Elapsed: `' . (microtime(true) - $sendStart) . '`. Speed: `' . pb_backupbuddy::$format->file_size($uploaded_speed) . '`/sec.');
         }
         // Load fileoptions to the send.
         if (isset($fileoptions_obj)) {
             pb_backupbuddy::status('details', 'fileoptions already loaded from prior pass.');
         } else {
             // load fileoptions
             pb_backupbuddy::status('details', 'About to load fileoptions data.');
             require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
             pb_backupbuddy::status('details', 'Fileoptions instance #10.');
             $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
             if (true !== ($result = $fileoptions_obj->is_ok())) {
                 return self::_error(__('Fatal Error #9034.23788723. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
             }
             pb_backupbuddy::status('details', 'Fileoptions data loaded.');
             $fileoptions =& $fileoptions_obj->options;
         }
         //$update_status = 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count( $settings['_multipart_counts'] ) . '.';
         if (!isset($settings['_multipart_counts'][$settings['_multipart_partnumber']])) {
             // No more parts exist for this file. Tell S3 the multipart upload is complete and move on.
             if (isset($settings['_retry_stash_confirm']) && true === $settings['_retry_stash_confirm']) {
                 // Need to retry checking that the file confirm was a success.
                 // Grab array of files from customer's stash directory
                 $files = pb_backupbuddy_destination_stash2::listFiles($settings, $settings['_multipart_file']);
                 if (count($files) > 0) {
                     pb_backupbuddy::status('details', 'Stash confirmed upload completition was successful.');
                 } else {
                     pb_backupbuddy::status('error', 'Error #23972793: Error notifying Stash of upload success even after wait. Details: `' . print_r($response, true) . '`.');
                     return false;
                 }
             } else {
                 // Normal Stash part send.
                 $update_status = 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count($settings['_multipart_counts']) . ' parts.';
                 pb_backupbuddy::status('details', 'Getting etags and notifying of multipart upload completion.');
                 try {
                     $response = self::$_client->completeMultipartUpload(array('Bucket' => $settings['bucket'], 'UploadId' => $settings['_multipart_id'], 'Key' => $settings['_multipart_remotefile'], 'Parts' => $settings['_multipart_etag_parts']));
                 } catch (Exception $e) {
                     return self::_error('Unable to notify server of completion of all parts for multipart upload `' . $settings['_multipart_id'] . '`. Details: `' . $e->getMessage() . '`.');
                 }
                 pb_backupbuddy::status('details', 'Server notified of multipart completion.');
                 if ('1' == $settings['stash_mode']) {
                     // Stash send confirm.
                     pb_backupbuddy::status('details', 'Notifying Stash of upload completion.');
                     $additionalParams = array('upload_id' => $settings['_stash_upload_id']);
                     $response = pb_backupbuddy_destination_stash2::stashAPI($settings, 'upload-complete', $additionalParams);
                     if (!is_array($response) || !isset($response['success'])) {
                         // If not array OR success key missing. May be a timeout or waiting on AWS system to combine multipart still. Check for file later.
                         $settings['_retry_stash_confirm'] = true;
                         $settings['_multipart_counts'] = array();
                         // No more parts remain.
                         $cronTime = time() + self::STASH_CONFIRM_RETRY_DELAY;
                         $cronArgs = array($settings, $file, $send_id, $delete_after);
                         $cronHashID = md5($cronTime . serialize($cronArgs));
                         $cronArgs[] = $cronHashID;
                         $schedule_result = backupbuddy_core::schedule_single_event($cronTime, 'destination_send', $cronArgs);
                         if (true === $schedule_result) {
                             pb_backupbuddy::status('details', 'Scheduled retry attempt to confirm send in `' . self::STASH_CONFIRM_RETRY_DELAY . '` seconds.');
                         } else {
                             pb_backupbuddy::status('error', 'Scheduled retry attempt FAILED to be scheduled.');
                         }
                         /*
                          *		TODO:	Once PING API is available, request a ping in the future so we make sure this actually runs reasonably soon.
                          *				Because we need a delay we are not firing off the cron here immediately so there will be no chaining of PHP
                          *				which may result in large delays before the next process if there's little site traffic.
                          */
                         return array($settings['_multipart_id'], 'Pending multipart send confirmation.');
                     } else {
                         // Array.
                         if (isset($response['success']) && true !== $response['success']) {
                             // Success key set AND not true.
                             pb_backupbuddy::status('error', 'Error #83298932: Error notifying Stash of upload success. Details: `' . print_r($response, true) . '`.');
                             return false;
                         } else {
                             // Success.
                             pb_backupbuddy::status('details', 'Stash notified of upload completition.');
                         }
                     }
                 }
             }
             // end not a Stash confirm retry.
             pb_backupbuddy::status('details', 'No more parts left for this multipart upload. Clearing multipart instance variables.');
             $settings['_multipart_partnumber'] = 0;
             $settings['_multipart_id'] = '';
             $settings['_multipart_file'] = '';
             $settings['_multipart_remotefile'] = '';
             // Multipart completed so safe to prevent housekeeping of incomplete multipart uploads.
             $settings['_multipart_transferspeeds'][] = $uploaded_speed;
             // Overall upload speed average.
             $uploaded_speed = array_sum($settings['_multipart_transferspeeds']) / count($settings['_multipart_counts']);
             pb_backupbuddy::status('details', 'Upload speed average of all chunks: `' . pb_backupbuddy::$format->file_size($uploaded_speed) . '`.');
             $settings['_multipart_counts'] = array();
             // Update stats.
             $fileoptions['_multipart_status'] = $update_status;
             $fileoptions['finish_time'] = microtime(true);
             $fileoptions['status'] = 'success';
             if (isset($uploaded_speed)) {
                 $fileoptions['write_speed'] = $uploaded_speed;
             }
             $fileoptions_obj->save();
             unset($fileoptions);
             $fileDone = true;
             @fclose($f);
         } else {
             // Parts remain. Schedule to continue if anything is left to upload for this multipart of any individual files.
             pb_backupbuddy::status('details', 'S3 multipart upload has more parts left.');
             $update_status = '<br>';
             $totalSent = 0;
             for ($i = 0; $i < $settings['_multipart_partnumber']; $i++) {
                 $totalSent += $settings['_multipart_counts'][$i]['length'];
             }
             $percentSent = ceil($totalSent / $settings['_multipart_backup_size'] * 100);
             $update_status .= '<div class="backupbuddy-progressbar" data-percent="' . $percentSent . '"><div class="backupbuddy-progressbar-label"></div></div>';
             if ('0' != $maxTime) {
                 // Not unlimited time so see if we can send more bursts this time or if we need to chunk.
                 // If we are within X second of reaching maximum PHP runtime then stop here so that it can be picked up in another PHP process...
                 $totalSizeSent = self::$_chunksSentThisRound * $chunkSizeBytes;
                 // Total bytes sent this PHP load.
                 $bytesPerSec = $totalSizeSent / (microtime(true) - $sendStart);
                 $timeRemaining = $maxTime - (microtime(true) - self::$_timeStart + self::TIME_WIGGLE_ROOM);
                 if ($timeRemaining < 0) {
                     $timeRemaining = 0;
                 }
                 $bytesWeCouldSendWithTimeLeft = $bytesPerSec * $timeRemaining;
                 //pb_backupbuddy::status( 'details', 'Sent this burst: `' . pb_backupbuddy::$format->file_size( $totalSizeSent ) .'` in `' . (microtime(true) - $sendStart ) . '` secs. Speed: `' . pb_backupbuddy::$format->file_size( $bytesPerSec ) . '`/sec. Time Remaining (w/ wiggle): `' . $timeRemaining . '`. Size that could potentially be sent with remaining time: `' . pb_backupbuddy::$format->file_size( $bytesWeCouldSendWithTimeLeft ) . '` with chunk size of `' . pb_backupbuddy::$format->file_size( $chunkSizeBytes ) . '`.' );
                 if ($bytesWeCouldSendWithTimeLeft < $chunkSizeBytes) {
                     // We can send more than a whole chunk (including wiggle room) so send another bit.
                     pb_backupbuddy::status('message', 'Not enough time left (~`' . $timeRemaining . '`) with max time of `' . $maxTime . '` sec to send another chunk at `' . pb_backupbuddy::$format->file_size($bytesPerSec) . '` / sec. Ran for ' . round(microtime(true) - self::$_timeStart, 3) . ' sec. Proceeding to use chunking.');
                     @fclose($fs);
                     $cronTime = time();
                     $cronArgs = array($settings, $file, $send_id, $delete_after);
                     $cronHashID = md5($cronTime . serialize($cronArgs));
                     $cronArgs[] = $cronHashID;
                     $schedule_result = backupbuddy_core::schedule_single_event($cronTime, 'destination_send', $cronArgs);
                     if (true === $schedule_result) {
                         pb_backupbuddy::status('details', 'Next S3 chunk step cron event scheduled.');
                     } else {
                         pb_backupbuddy::status('error', 'Next S3 chunk step cron even FAILED to be scheduled.');
                     }
                     spawn_cron(time() + 150);
                     // Adds > 60 seconds to get around once per minute cron running limit.
                     update_option('_transient_doing_cron', 0);
                     // Prevent cron-blocking for next item.
                     @fclose($f);
                     unset($fileoptions);
                     return array($settings['_multipart_id'], 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count($settings['_multipart_counts']) . ' parts.' . $update_status);
                 } else {
                     // End if.
                     pb_backupbuddy::status('details', 'Not approaching limits. Proceeding to next burst this run.');
                 }
             } else {
                 pb_backupbuddy::status('details', 'Max time of zero (0) so assuming unlimited time.');
             }
             $fileoptions['_multipart_status'] = 'Sent part ' . $settings['_multipart_partnumber'] . ' of ' . count($settings['_multipart_counts']) . ' parts.' . $update_status;
             $fileoptions_obj->save();
             //unset( $fileoptions );
         }
         // end no more parts remain.
     }
     // End while not feof.
     /***** BEGIN FILE ARCHIVE LIMITS *****/
     if ('1' == $settings['stash_mode']) {
         // This is being wrapped by the Stash destination. Stash uses a different method of handling archive limiting due to using Stash API.
         pb_backupbuddy_destination_stash2::archiveLimit($settings, $backup_type);
     } else {
         // Normal. This is just a s32 destination.
         self::archiveLimit($settings, $backup_type);
     }
     /***** END FILE ARCHIVE LIMITS *****/
     if (isset($fileoptions_obj)) {
         unset($fileoptions_obj);
     }
     // Success if we made it this far.
     return true;
 }
Пример #9
0
    }
    echo '<br>';
}
// end deletion.
// Handle copying files to local
if (pb_backupbuddy::_GET('cpy_file') != '') {
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating Stash copy.');
    $file = base64_decode(pb_backupbuddy::_GET('cpy_file'));
    if (FALSE !== strstr($file, '?')) {
        $url = $file;
        $file = basename($file);
        $file = substr($file, 0, strpos($file, '?'));
    }
    backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('process_remote_copy'), array('stash2', $file, $settings));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
// end copying to local.
// Handle download link
if (pb_backupbuddy::_GET('downloadlink_file') != '') {
    pb_backupbuddy::alert('Download the selected backup file with <a href="' . esc_url(base64_decode(pb_backupbuddy::_GET('downloadlink_file'))) . '">this link</a>. The link is valid for one hour.');
    echo '<br>';
}
// end download link.
// Get list of files for this site.
if ('true' != pb_backupbuddy::_GET('listAll')) {
    $remotePath = 'backup-' . backupbuddy_core::backup_prefix();
Пример #10
0
 function cron_next_step($spawn_cron = true, $future_offset = 0, $next_step_title = '')
 {
     // Internal cron (optional; disabled by default).
     if ('1' == pb_backupbuddy::$options['use_internal_cron']) {
         if ($future_offset > 0) {
             // Delay requsted.
             if ($future_offset > backupbuddy_core::adjustedMaxExecutionTime()) {
                 $future_offset = 5;
                 // If huge, try 5 sec.
             }
             sleep($future_offset);
         }
         $cron_url = site_url();
         $args = array('backupbuddy_cron_action' => 'process_backup', 'backupbuddy_serial' => $this->_backup['serial'], 'backupbuddy_time' => time(), 'backupbuddy_key' => pb_backupbuddy::$options['log_serial']);
         pb_backupbuddy::status('details', 'Attempting to bypass WordPress cron and use internal cron system calling `' . $cron_url . '`. Args: `' . print_r($args, true) . '`.');
         pb_backupbuddy::flush();
         $response = wp_remote_post($cron_url, array('method' => 'POST', 'timeout' => backupbuddy_core::adjustedMaxExecutionTime(), 'redirection' => 3, 'httpversion' => '1.0', 'blocking' => false, 'headers' => array(), 'body' => $args, 'cookies' => array()));
         pb_backupbuddy::status('details', 'Cron response: `' . print_r($response, true) . '`.');
         return;
     }
     if ('1' == pb_backupbuddy::$options['skip_spawn_cron_call']) {
         pb_backupbuddy::status('details', 'Advanced option to skip call to spawn cron enabled. Setting to skip spawn_cron() call.');
         $spawn_cron = false;
     }
     pb_backupbuddy::status('details', 'Scheduling Cron for `' . $this->_backup['serial'] . '`.');
     // Need to make sure the database connection is active. Sometimes it goes away during long bouts doing other things -- sigh.
     // This is not essential so use include and not require (suppress any warning)
     @(include_once pb_backupbuddy::plugin_path() . '/lib/wpdbutils/wpdbutils.php');
     if (class_exists('pluginbuddy_wpdbutils')) {
         global $wpdb;
         $dbhelper = new pluginbuddy_wpdbutils($wpdb);
         if (!$dbhelper->kick()) {
             pb_backupbuddy::status('error', __('Database Server has gone away, unable to schedule next backup step. The backup cannot continue. This is most often caused by mysql running out of memory or timing out far too early. Please contact your host.', 'it-l10n-backupbuddy'));
             pb_backupbuddy::status('haltScript', '');
             // Halt JS on page.
             return false;
         }
     } else {
         pb_backupbuddy::status('details', __('Database Server connection status unverified.', 'it-l10n-backupbuddy'));
     }
     // Schedule event.
     $cron_time = time() + $future_offset;
     $cron_args = array($this->_backup['serial']);
     pb_backupbuddy::status('details', 'Scheduling next step to run at `' . $cron_time . '` (localized time: ' . pb_backupbuddy::$format->date(pb_backupbuddy::$format->localize_time($cron_time)) . ') with cron tag `backupbuddy_cron` to run method `process_backup` and serial arguments `' . implode(',', $cron_args) . '`.');
     $schedule_result = backupbuddy_core::schedule_single_event($cron_time, 'process_backup', $cron_args);
     if ($schedule_result === false) {
         pb_backupbuddy::status('error', 'Unable to schedule next cron step. Verify that another plugin is not preventing / conflicting.');
     } else {
         pb_backupbuddy::status('details', 'Next step scheduled.');
         pb_backupbuddy::status('startAction', 'cronPass');
         pb_backupbuddy::status('cronParams', base64_encode(json_encode(array('time' => $cron_time, 'tag' => 'backupbuddy_cron', 'method' => 'process_backup', 'args' => $cron_args))));
     }
     update_option('_transient_doing_cron', 0);
     // Prevent cron-blocking for next item.
     // Spawn cron.
     if ($spawn_cron === true) {
         pb_backupbuddy::status('details', 'Calling spawn_cron().');
         spawn_cron(time() + 150);
         // Adds > 60 seconds to get around once per minute cron running limit.
     } else {
         pb_backupbuddy::status('details', 'Not calling spawn_cron().');
     }
     $next_step_note = '';
     if ('' != $next_step_title) {
         $next_step_note = ' (' . $next_step_title . ' expected)';
     }
     pb_backupbuddy::status('details', 'About to run next step' . $next_step_note . '. If the backup does not proceed within 15 seconds then something is interfering with the WordPress CRON system such as: server loopback issues, caching plugins, or scheduling plugins. Try disabling other plugins to see if it resolves issue.  Check the Server Information page cron section to see if the next BackupBuddy step is scheduled to run. Enable "Classic" backup mode on the "Settings" page to rule out non-cron issues. Additionally you may verify no other backup processes are trying to run at the same time by verifying there is not an existing backup process listed in the cron hogging the cron process.');
     return;
 }
Пример #11
0
 public static function send($settings = array(), $files = array(), $send_id = '', $delete_remote_after = false)
 {
     self::$_timeStart = microtime(true);
     $settings = self::_normalizeSettings($settings);
     if (false === ($settings = self::_connect($settings))) {
         $error = 'Unable to connect with Google Drive. See log for details.';
         echo $error;
         pb_backupbuddy::status('error', $error);
         return false;
     }
     $chunkSizeBytes = $settings['max_burst'] * 1024 * 1024;
     // Send X mb at a time to limit memory usage.
     foreach ($files as $file) {
         $fileSize = filesize($file);
         $fileinfo = pathinfo($file);
         $fileextension = $fileinfo['extension'];
         if ('zip' == $fileextension) {
             $mimeType = 'application/zip';
         } elseif ('php' == $fileextension) {
             $mimeType = 'application/x-httpd-php';
         } else {
             $mimeType = '';
         }
         pb_backupbuddy::status('details', 'About to upload file `' . $file . '` of size `' . $fileSize . '` with mimetype `' . $mimeType . '`. Internal chunk size of `' . $chunkSizeBytes . '` bytes.');
         //Insert a file
         $driveFile = new Google_Service_Drive_DriveFile();
         $driveFile->setTitle(basename($file));
         $driveFile->setDescription('BackupBuddy file');
         $driveFile->setMimeType($mimeType);
         self::$_client->setDefer(true);
         try {
             $insertRequest = self::$_drive->files->insert($driveFile);
         } catch (Exception $e) {
             pb_backupbuddy::alert('Error #3232783268336: initiating upload. Details: ' . $e->getMessage());
             return;
         }
         // See https://developers.google.com/api-client-library/php/guide/media_upload
         try {
             $media = new Google_Http_MediaFileUpload(self::$_client, $insertRequest, $mimeType, null, true, $chunkSizeBytes);
         } catch (Exception $e) {
             pb_backupbuddy::alert('Error #3893273937: initiating upload. Details: ' . $e->getMessage());
             return;
         }
         $media->setFileSize($fileSize);
         pb_backupbuddy::status('details', 'Opening file for sending in binary mode.');
         $fs = fopen($file, 'rb');
         // If chunked resuming then seek to the correct place in the file.
         if ('' != $settings['resume_point'] && $settings['resume_point'] > 0) {
             // Resuming send of a partially transferred file.
             if (0 !== fseek($fs, $settings['resume_point'])) {
                 // Returns 0 on success.
                 pb_backupbuddy::status('error', 'Error #3872733: Failed to seek file to resume point `' . $settings['resume_point'] . '` via fseek().');
                 return false;
             }
             $prevPointer = $settings['resume_point'];
         } else {
             // New file send.
             $prevPointer = 0;
         }
         $needProcessChunking = false;
         // Set true if we need to spawn off resuming to a new PHP page load.
         $uploadStatus = false;
         while (!$uploadStatus && !feof($fs)) {
             $chunk = fread($fs, $chunkSizeBytes);
             $uploadStatus = $media->nextChunk($chunk);
             // Handle splitting up across multiple PHP page loads if needed.
             if (!feof($fs) && 0 != $settings['max_time']) {
                 // More data remains so see if we need to consider chunking to a new PHP process.
                 // If we are within X second of reaching maximum PHP runtime then stop here so that it can be picked up in another PHP process...
                 if (microtime(true) - self::$_timeStart + self::TIME_WIGGLE_ROOM >= $settings['max_time']) {
                     pb_backupbuddy::status('message', 'Approaching limit of available PHP chunking time of `' . $settings['max_time'] . '` sec. Ran for ' . round(microtime(true) - self::$_timeStart, 3) . ' sec. Proceeding to use chunking.');
                     @fclose($fs);
                     // Tells next chunk where to pick up.
                     $settings['resume_point'] = $prevPointer;
                     if (isset($chunksTotal)) {
                         $settings['chunks_total'] = $chunksTotal;
                     }
                     // Schedule cron.
                     $cronTime = time();
                     $cronArgs = array($settings, $files, $send_id, $delete_after = false);
                     $cronHashID = md5($cronTime . serialize($cronArgs));
                     $cronArgs[] = $cronHashID;
                     $schedule_result = backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
                     if (true === $schedule_result) {
                         pb_backupbuddy::status('details', 'Next Site chunk step cron event scheduled.');
                     } else {
                         pb_backupbuddy::status('error', 'Next Site chunk step cron even FAILED to be scheduled.');
                     }
                     spawn_cron(time() + 150);
                     // Adds > 60 seconds to get around once per minute cron running limit.
                     update_option('_transient_doing_cron', 0);
                     // Prevent cron-blocking for next item.
                     return array($prevPointer, 'Sent part ' . $settings['chunks_sent'] . ' of ~' . $settings['chunks_total'] . ' parts.');
                     // filepointer location, elapsed time during the import
                 } else {
                     // End if.
                     pb_backupbuddy::status('details', 'Not approaching time limit.');
                 }
             } else {
                 pb_backupbuddy::status('details', 'No more data remains (eg for chunking) so finishing up.');
             }
         }
         fclose($fs);
         self::$_client->setDefer(false);
         if (false == $uploadStatus) {
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = 'Error #84347474 sending. Details: ' . $uploadStatus;
             return false;
         } else {
             // Success.
             if (true === $delete_remote_after) {
                 self::deleteFile($settings, $uploadStatus->id);
             }
         }
     }
     // end foreach.
     // Made it this far then success.
     return true;
 }
Пример #12
0
 public static function send($settings = array(), $file, $send_id = '', $delete_after = false)
 {
     $settings = self::_init($settings);
     // Handles formatting & sanitizing settings.
     // Process multipart transfer that we already initiated in a previous runthrough.
     if ($settings['_multipart_id'] != '') {
         // Multipart upload initiated and needs parts sent.
         $backup_type = str_replace('/', '', $settings['_multipart_backup_type']);
         // For use later by file limiting.
         $backup_size = $settings['_multipart_backup_size'];
         $this_part_number = $settings['_multipart_partnumber'] + 1;
         // Open file for streaming.
         $f = @fopen($settings['_multipart_file'], 'rb');
         if (false === $f) {
             return self::_error('Error #437734. Unable to open file `' . $settings['_multipart_file'] . '` to send. Did it get deleted?');
         }
         if (-1 == @fseek($f, (int) $settings['_multipart_counts'][$settings['_multipart_partnumber']]['seekTo'])) {
             return self::_error('Error #833838: Unable to fseek file.');
         }
         $sendStart = time(true);
         pb_backupbuddy::status('details', 'Beginning upload of part `' . $this_part_number . '` of `' . count($settings['_multipart_counts']) . '` parts of file `' . $settings['_multipart_file'] . '` to remote location `' . $settings['_multipart_remotefile'] . '` with multipart ID `' . $settings['_multipart_id'] . '`.');
         try {
             $response = self::$_client->uploadPart(array('Bucket' => $settings['bucket'], 'Key' => $settings['_multipart_remotefile'], 'UploadId' => $settings['_multipart_id'], 'PartNumber' => $this_part_number, 'ContentLength' => (int) $settings['_multipart_counts'][$settings['_multipart_partnumber']]['length'], 'Body' => $f));
         } catch (Exception $e) {
             @fclose($f);
             return self::_error('Unable to upload file part for multipart upload `' . $settings['_multipart_id'] . '`. Details: `' . $e->getMessage() . '`.');
         }
         @fclose($f);
         pb_backupbuddy::status('details', 'Success sending chunk. Upload details: `' . print_r($response, true) . '`.');
         $uploaded_size = $backup_size;
         $uploaded_speed = time(true) - $sendStart;
         pb_backupbuddy::status('details', 'Uploaded size: ' . pb_backupbuddy::$format->file_size($uploaded_size) . ', Speed: ' . pb_backupbuddy::$format->file_size($uploaded_speed) . '/sec.');
         // Load fileoptions to the send.
         pb_backupbuddy::status('details', 'About to load fileoptions data.');
         require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
         pb_backupbuddy::status('details', 'Fileoptions instance #10.');
         $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
         if (true !== ($result = $fileoptions_obj->is_ok())) {
             return self::_error(__('Fatal Error #9034.2344848. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
         }
         pb_backupbuddy::status('details', 'Fileoptions data loaded.');
         $fileoptions =& $fileoptions_obj->options;
         $update_status = 'Sent part ' . $this_part_number . ' of ' . count($settings['_multipart_counts']) . '.';
         // Made it here so success sending part. Increment for next part to send.
         $settings['_multipart_partnumber']++;
         if (!isset($settings['_multipart_counts'][$settings['_multipart_partnumber']])) {
             // No more parts exist for this file. Tell S3 the multipart upload is complete and move on.
             pb_backupbuddy::status('details', 'S3 getting parts with etags to notify S3 of completed multipart send.');
             try {
                 $response = self::$_client->listParts(array('Bucket' => $settings['bucket'], 'UploadId' => $settings['_multipart_id'], 'Key' => $settings['_multipart_remotefile']));
                 $etag_parts = $etag_parts->Parts;
             } catch (Exception $e) {
                 return self::_error('Error #8332893: Unable to list parts on server. Details: `' . $e->getMessage() . '`.');
             }
             pb_backupbuddy::status('details', 'Got parts list. Details: ' . print_r($etag_parts, true));
             pb_backupbuddy::status('details', 'Notifying server of multipart upload completion.');
             try {
                 $response = self::$_client->completeMultipartUpload(array('Bucket' => $settings['bucket'], 'UploadId' => $settings['_multipart_id'], 'Key' => $settings['_multipart_remotefile'], 'Parts' => $etag_parts));
             } catch (Exception $e) {
                 return self::_error('Unable to notify server of completion of all parts for multipart upload `' . $settings['_multipart_id'] . '`. Details: `' . $e->getMessage() . '`.');
             }
             pb_backupbuddy::status('details', 'Server notified of multipart completion.');
             pb_backupbuddy::status('details', 'No more parts left for this multipart upload. Clearing multipart instance variables.');
             $settings['_multipart_partnumber'] = 0;
             $settings['_multipart_id'] = '';
             $settings['_multipart_file'] = '';
             $settings['_multipart_remotefile'] = '';
             // Multipart completed so safe to prevent housekeeping of incomplete multipart uploads.
             $settings['_multipart_transferspeeds'][] = $uploaded_speed;
             // Overall upload speed average.
             $uploaded_speed = array_sum($settings['_multipart_transferspeeds']) / count($settings['_multipart_counts']);
             pb_backupbuddy::status('details', 'Upload speed average of all chunks: `' . pb_backupbuddy::$format->file_size($uploaded_speed) . '`.');
             $settings['_multipart_counts'] = array();
             // Update stats.
             $fileoptions['_multipart_status'] = $update_status;
             $fileoptions['finish_time'] = time();
             $fileoptions['status'] = 'success';
             if (isset($uploaded_speed)) {
                 $fileoptions['write_speed'] = $uploaded_speed;
             }
             $fileoptions_obj->save();
             unset($fileoptions);
         }
         // Schedule to continue if anything is left to upload for this multipart of any individual files.
         if ($settings['_multipart_id'] != '') {
             pb_backupbuddy::status('details', 'S3 multipart upload has more parts left. Scheduling next part send.');
             $cronTime = time();
             $cronArgs = array($settings, $file, $send_id, $delete_after);
             $cronHashID = md5($cronTime . serialize($cronArgs));
             $cronArgs[] = $cronHashID;
             $schedule_result = backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
             if (true === $schedule_result) {
                 pb_backupbuddy::status('details', 'Next S3 chunk step cron event scheduled.');
             } else {
                 pb_backupbuddy::status('error', 'Next S3 chunk step cron even FAILED to be scheduled.');
             }
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             return array($settings['_multipart_id'], 'Sent part ' . $this_part_number . ' of ' . count($settings['_multipart_counts']) . ' parts.');
         }
     } else {
         // not multipart continuation
         // Handle chunking of file into a multipart upload (if applicable).
         $file_size = filesize($file);
         if ($settings['max_chunk_size'] >= self::MINIMUM_CHUNK_SIZE && $file_size / 1024 / 1024 > $settings['max_chunk_size']) {
             // minimum chunk size is 5mb. Anything under 5mb we will not chunk.
             pb_backupbuddy::status('details', 'File size of ' . pb_backupbuddy::$format->file_size($file_size) . ' exceeds max chunk size of ' . $settings['max_chunk_size'] . 'MB set in settings for sending file as multipart upload.');
             // About to chunk so cleanup any previous hanging multipart transfers.
             self::multipart_cleanup($settings, $lessLogs = false);
             // Initiate multipart upload with S3.
             pb_backupbuddy::status('details', 'Initiating multipart transfer.');
             try {
                 $response = self::$_client->createMultipartUpload(array('Bucket' => $settings['bucket'], 'Key' => $settings['directory'] . basename($file), 'StorageClass' => $settings['storage'], 'ServerSideEncryption' => 'AES256'));
             } catch (Exception $e) {
                 return self::_error('Error #389383: Unable to initiate multipart upload. Details: `' . $e->getMessage() . '`.');
             }
             // Made it here so SUCCESS initiating multipart!
             $upload_id = (string) $response['UploadId'];
             pb_backupbuddy::status('details', 'Initiated multipart upload with ID `' . $upload_id . '`.');
             $backup_type = backupbuddy_core::getBackupTypeFromFile($file);
             // Calculate multipart settings.
             $multipart_destination_settings = $settings;
             $multipart_destination_settings['_multipart_id'] = $upload_id;
             $multipart_destination_settings['_multipart_partnumber'] = 0;
             $multipart_destination_settings['_multipart_file'] = $file;
             $multipart_destination_settings['_multipart_remotefile'] = $settings['directory'] . basename($file);
             $multipart_destination_settings['_multipart_counts'] = self::_get_multipart_counts($file_size, $settings['max_chunk_size'] * 1024 * 1024);
             // Size of chunks expected to be in bytes.
             $multipart_destination_settings['_multipart_backup_type'] = $backup_type;
             $multipart_destination_settings['_multipart_backup_size'] = $file_size;
             pb_backupbuddy::status('details', 'Multipart settings to pass:'******'details', 'Scheduling send of next part.');
             $cronTime = time();
             $cronArgs = array($multipart_destination_settings, $file, $send_id, $delete_after);
             $cronHashID = md5($cronTime . serialize($cronArgs));
             $cronArgs[] = $cronHashID;
             backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             pb_backupbuddy::status('details', 'Scheduled send of next part(s). Done for this cycle.');
             return array($upload_id, 'Starting send of ' . count($multipart_destination_settings['_multipart_counts']) . ' parts.');
         } else {
             // did not meet chunking criteria.
             if ($settings['max_chunk_size'] != '0') {
                 if ($file_size / 1024 / 1024 > self::MINIMUM_CHUNK_SIZE) {
                     pb_backupbuddy::status('details', 'File size of ' . pb_backupbuddy::$format->file_size($file_size) . ' is less than the max chunk size of ' . $settings['max_chunk_size'] . 'MB; not chunking into multipart upload.');
                 } else {
                     pb_backupbuddy::status('details', 'File size of ' . pb_backupbuddy::$format->file_size($file_size) . ' is less than the minimum allowed chunk size of ' . self::MINIMUM_CHUNK_SIZE . 'MB; not chunking into multipart upload.');
                 }
             } else {
                 pb_backupbuddy::status('details', 'Max chunk size set to zero so not chunking into multipart upload.');
             }
             // Open file for streaming.
             $f = @fopen($file, 'rb');
             if (false === $f) {
                 return self::_error('Error #2379327. Unable to open file `' . $file . '` to send. Did it get deleted?');
             }
             // Initiate SINGLE PART upload.
             $startSend = time(true);
             pb_backupbuddy::status('details', 'Initiating non-chunked transfer.');
             try {
                 $response = self::$_client->upload($settings['bucket'], $settings['directory'] . basename($file), $f, 'private', array('StorageClass' => $settings['storage'], 'ServerSideEncryption' => 'AES256'));
             } catch (Exception $e) {
                 return self::_error('Error #389383: Unable to initiate non-chunked upload. Details: `' . $e->getMessage() . '`.');
             }
             @fclose($f);
             // Made it here so SUCCESS sending.
             $uploaded_size = $file_size;
             $uploaded_speed = $file_size / (time(true) - $startSend);
             pb_backupbuddy::status('details', 'Success uploading file `' . basename($file) . '`. Upload details: `' . print_r($response, true) . '`. Uploaded size: ' . pb_backupbuddy::$format->file_size($uploaded_size) . ', Speed: ' . pb_backupbuddy::$format->file_size($uploaded_speed) . '/sec.');
             // Load destination fileoptions.
             pb_backupbuddy::status('details', 'About to load fileoptions data.');
             require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
             pb_backupbuddy::status('details', 'Fileoptions instance #882.');
             $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
             if (true !== ($result = $fileoptions_obj->is_ok())) {
                 return self::_error(__('Fatal Error #9034.23737. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
             }
             pb_backupbuddy::status('details', 'Fileoptions data loaded.');
             $fileoptions =& $fileoptions_obj->options;
             // Save stats.
             if (isset($uploaded_speed)) {
                 $fileoptions['write_speed'] = $uploaded_speed;
                 $fileoptions_obj->save();
             }
             unset($fileoptions_obj);
         }
         // End non-chunked upload.
     }
     // end not multipart continuation.
     // BEGIN FILE LIMIT PROCESSING. Enforce archive limits if applicable.
     if ($backup_type == 'full') {
         $limit = $full_archive_limit;
         pb_backupbuddy::status('details', 'Full backup archive limit of `' . $limit . '` of type `full` based on destination settings.');
     } elseif ($backup_type == 'db') {
         $limit = $db_archive_limit;
         pb_backupbuddy::status('details', 'Database backup archive limit of `' . $limit . '` of type `db` based on destination settings.');
     } elseif ($backup_type == 'files') {
         $limit = $db_archive_limit;
         pb_backupbuddy::status('details', 'Database backup archive limit of `' . $limit . '` of type `files` based on destination settings.');
     } else {
         $limit = 0;
         pb_backupbuddy::status('warning', 'Warning #237332. Unable to determine backup type (reported: `' . $backup_type . '`) so archive limits NOT enforced for this backup.');
     }
     if ($limit > 0) {
         pb_backupbuddy::status('details', 'Archive limit enforcement beginning.');
         // Get file listing.
         try {
             $response_manage = self::$_client->listObjects(array('Bucket' => $settings['bucket'], 'Prefix' => $settings['directory'] . 'backup-' . backup_prefix()));
             // List all users files in this directory that are a backup for this site (limited by prefix).
         } catch (Exception $e) {
             self::_error('Error #9338292: Unable to list files for archive limiting. Details: `' . $e->getMessage() . '`.');
         }
         // List backups associated with this site by date.
         $backups = array();
         foreach ($response_manage->Contents as $object) {
             $file = str_replace($settings['directory'], '', $object['Key']);
             $backups[$file] = strtotime($object['LastModified']);
         }
         arsort($backups);
         pb_backupbuddy::status('details', 'Stash found `' . count($backups) . '` backups of this type when checking archive limits.');
         if (count($backups) > $limit) {
             pb_backupbuddy::status('details', 'More archives (' . count($backups) . ') than limit (' . $limit . ') allows. Trimming...');
             $i = 0;
             $delete_fail_count = 0;
             foreach ($backups as $buname => $butime) {
                 $i++;
                 if ($i > $limit) {
                     pb_backupbuddy::status('details', 'Trimming excess file `' . $buname . '`...');
                     try {
                         $response = self::$_client->deleteObject(array('Bucket' => $settings['bucket'], 'Key' => $settings['directory'] . $buname));
                     } catch (Exception $e) {
                         self::_error('Unable to delete excess Stash file `' . $buname . '`. Details: `' . $e->getMessage() . '`.');
                         $delete_fail_count++;
                     }
                 }
             }
             pb_backupbuddy::status('details', 'Finished trimming excess backups.');
             if ($delete_fail_count !== 0) {
                 $error_message = 'Stash remote limit could not delete ' . $delete_fail_count . ' backups.';
                 pb_backupbuddy::status('error', $error_message);
                 backupbuddy_core::mail_error($error_message);
             }
         }
         pb_backupbuddy::status('details', 'Stash completed archive limiting.');
     } else {
         pb_backupbuddy::status('details', 'No Stash archive file limit to enforce.');
     }
     // End remote backup limit
     if (isset($fileoptions_obj)) {
         unset($fileoptions_obj);
     }
     // Success if we made it this far.
     return true;
 }
Пример #13
0
    $response = pb_backupbuddy_destination_stash2::deleteFiles($settings, $deleteFiles);
    if (true === $response) {
        pb_backupbuddy::alert('Deleted ' . implode(', ', $deleteFiles) . '.');
    } else {
        pb_backupbuddy::alert('Failed to delete one or more files. Details: `' . $response . '`.');
    }
    echo '<br>';
}
// end deletion.
// Handle copying files to local
if (pb_backupbuddy::_GET('cpy_file') != '') {
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating Stash copy.');
    $file = base64_decode(pb_backupbuddy::_GET('cpy_file'));
    backupbuddy_core::schedule_single_event(time(), 'process_remote_copy', array('stash2', $file, $settings));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
// end copying to local.
// Handle download link
if (pb_backupbuddy::_GET('downloadlink_file') != '') {
    pb_backupbuddy::alert('Download the selected backup file with <a href="' . esc_url(base64_decode(pb_backupbuddy::_GET('downloadlink_file'))) . '">this link</a>. The link is valid for one hour.');
    echo '<br>';
}
// end download link.
// Get list of files for this site.
if ('true' != pb_backupbuddy::_GET('listAll')) {
    // NOT listing all sites.
         pb_backupbuddy::status('details', 'Waiting for the pre-backup initialization for serial `' . $serial . '` to complete: ' . $init_wait_retry_count, $serial);
         pb_backupbuddy::status('wait_init', '', $serial);
     }
 }
 //***** Process any specialAction methods.
 if ('checkSchedule' == $specialAction) {
     if (FALSE === ($next_scheduled = wp_next_scheduled('pb_backupbuddy_process_backup', array($serial)))) {
         //pb_backupbuddy::status( 'details', print_r( pb_backupbuddy::_POST(), true ), $serial );
         pb_backupbuddy::status('warning', 'WordPress reports the next step is not currently scheduled. It is either in the process of running or went missing. Consider enabled advanced setting missing cron rescheduling if this persists.', $serial, null, $echoNotWrite = true);
         if ('1' == pb_backupbuddy::$options['backup_cron_rescheduling']) {
             pb_backupbuddy::status('details', 'Missing cron rescheduling enabled. Attempting to add the missing schedule back in.', $serial);
             // Schedule event.
             $cron_time = time();
             $cron_args = array($serial);
             pb_backupbuddy::status('details', 'Scheduling next step to run at `' . $cron_time . '` (localized time: ' . pb_backupbuddy::$format->date(pb_backupbuddy::$format->localize_time($cron_time)) . ') with cron tag `backupbuddy_cron` to run method `process_backup` and serial arguments `' . implode(',', $cron_args) . '`.', $serial);
             $schedule_result = backupbuddy_core::schedule_single_event($cron_time, 'process_backup', $cron_args);
             if ($schedule_result === false) {
                 pb_backupbuddy::status('error', 'Unable to reschedule missing cron step. Verify that another plugin is not preventing / conflicting.', $serial);
             } else {
                 pb_backupbuddy::status('details', 'Next step rescheduled.', $serial);
                 pb_backupbuddy::status('startAction', 'cronPass', $serial);
                 // Resets the time this action began so we will not attempt re-scheduling a second time for a bit.
                 pb_backupbuddy::status('cronParams', base64_encode(json_encode(array('time' => $cron_time, 'tag' => 'backupbuddy_cron', 'method' => 'process_backup', 'args' => $cron_args))), $serial);
             }
         }
     } else {
         $timeFromNow = $next_scheduled - time();
         pb_backupbuddy::status('details', 'Checked cron schedule. Next run: `' . $next_scheduled . '`. ' . $timeFromNow . ' seconds from now.', $serial, null, $echoNotWrite = true);
         if ($timeFromNow < 0) {
             // Time cron was to run is in the past.
             $missedTime = abs($timeFromNow);
Пример #15
0
<?php

backupbuddy_core::verifyAjaxAccess();
pb_backupbuddy::load();
// Schedule to run.
$cronArgs = array($schedule_results = false, $force_run = true);
$schedule_result = backupbuddy_core::schedule_single_event(time(), 'php_runtime_test', $cronArgs);
if (true === $schedule_result) {
    pb_backupbuddy::status('details', 'PHP runtime test cron event scheduled.');
} else {
    pb_backupbuddy::status('error', 'PHP runtime test cron event FAILED to be scheduled.');
}
if ('1' != pb_backupbuddy::$options['skip_spawn_cron_call']) {
    pb_backupbuddy::status('details', 'Spawning cron now.');
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
}
die(__('This may take a few minutes...', 'it-l10n-backupbuddy'));
Пример #16
0
        // close this connection
        ftp_close($conn_id);
    }
    if ($delete_count > 0) {
        pb_backupbuddy::alert(sprintf(_n('Deleted %d file.', 'Deleted %d files.', $delete_count, 'it-l10n-backupbuddy'), $delete_count));
    } else {
        pb_backupbuddy::alert(__('No backups were deleted.', 'it-l10n-backupbuddy'));
    }
    echo '<br>';
}
// Copy ftp backups to the local backup files
if (!empty($_GET['cpy_file'])) {
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating ftp copy.');
    backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('process_ftp_copy'), array($_GET['cpy_file'], $ftp_server, $ftp_username, $ftp_password, $ftp_directory, $port, $ftps));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
// Connect to server
if ($ftps == '1') {
    // Connect with FTPs.
    if (function_exists('ftp_ssl_connect')) {
        $conn_id = ftp_ssl_connect($ftp_server, $port);
        if ($conn_id === false) {
            pb_backupbuddy::status('details', 'Unable to connect to FTPS  `' . $ftp_server . '` on port `' . $port . '` (check address/FTPS support and that server can connect to this address via this port).', 'error');
            return false;
        } else {
            pb_backupbuddy::status('details', 'Connected to FTPs.');
Пример #17
0
         pb_backupbuddy::status('wait_init', '', $serial);
     }
 }
 //***** Process any specialAction methods.
 if ('checkSchedule' == $specialAction) {
     if (FALSE === ($next_scheduled = wp_next_scheduled('pb_backupbuddy_process_backup', array($serial)))) {
         //pb_backupbuddy::status( 'details', print_r( pb_backupbuddy::_POST(), true ), $serial );
         pb_backupbuddy::status('warning', 'WordPress reports the next step is not currently scheduled. It is either in the process of running or went missing. Consider enabled advanced setting missing cron rescheduling if this persists.', $serial, null, $echoNotWrite = true);
         if ('1' == pb_backupbuddy::$options['backup_cron_rescheduling']) {
             pb_backupbuddy::status('details', 'Missing cron rescheduling enabled. Attempting to add the missing schedule back in.', $serial);
             // Schedule event.
             $cron_time = time();
             $cron_tag = pb_backupbuddy::cron_tag('process_backup');
             $cron_args = array($serial);
             pb_backupbuddy::status('details', 'Scheduling next step to run at `' . $cron_time . '` (localized time: ' . pb_backupbuddy::$format->date(pb_backupbuddy::$format->localize_time($cron_time)) . ') with cron tag `' . $cron_tag . '` and serial arguments `' . implode(',', $cron_args) . '`.', $serial);
             $schedule_result = backupbuddy_core::schedule_single_event($cron_time, $cron_tag, $cron_args);
             if ($schedule_result === false) {
                 pb_backupbuddy::status('error', 'Unable to reschedule missing cron step. Verify that another plugin is not preventing / conflicting.', $serial);
             } else {
                 pb_backupbuddy::status('details', 'Next step rescheduled.', $serial);
                 pb_backupbuddy::status('startAction', 'cronPass', $serial);
                 // Resets the time this action began so we will not attempt re-scheduling a second time for a bit.
                 pb_backupbuddy::status('cronParams', base64_encode(json_encode(array('time' => $cron_time, 'tag' => $cron_tag, 'args' => $cron_args))), $serial);
             }
         }
     } else {
         $timeFromNow = $next_scheduled - time();
         pb_backupbuddy::status('details', 'Checked cron schedule. Next run: `' . $next_scheduled . '`. ' . $timeFromNow . ' seconds from now.', $serial, null, $echoNotWrite = true);
         if ($timeFromNow < 0) {
             // Time cron was to run is in the past.
             $missedTime = abs($timeFromNow);
Пример #18
0
    foreach ($meta_data['contents'] as &$backup) {
        $backup['modified'] = strtotime($backup['modified']);
    }
    // Custom sort function for multidimension array usage.
    function backupbuddy_number_sort($a, $b)
    {
        return $a['modified'] < $b['modified'];
    }
    // Sort by modified using custom sort function above.
    usort($meta_data['contents'], 'backupbuddy_number_sort');
}
// Copy dropbox backups to the local backup files
if (!empty($_GET['cpy_file'])) {
    pb_backupbuddy::alert(__('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.', 'it-l10n-backupbuddy'));
    pb_backupbuddy::status('details', 'Scheduling Cron for creating Dropbox copy.');
    backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('process_dropbox_copy'), array($_GET['destination_id'], $_GET['cpy_file']));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
//stecho '<h3>', __('Viewing', 'it-l10n-backupbuddy' ),' `' . $destination['title'] . '` (' . $destination['type'] . ')</h3>';
?>

<div>
<form id="posts-filter" enctype="multipart/form-data" method="post" action="<?php 
echo pb_backupbuddy::ajax_url('remoteClient') . '&custom=' . pb_backupbuddy::_GET('custom') . '&destination_id=' . pb_backupbuddy::_GET('destination_id');
?>
">
	<div class="tablenav">
		<div class="alignleft actions">
Пример #19
0
 public static function send($settings = array(), $files = array(), $send_id = '', $delete_after = false)
 {
     if (!is_array($files)) {
         $files = array($files);
     }
     pb_backupbuddy::status('details', 'Dropbox2 send function started. Remote send id: `' . $send_id . '`.');
     // Normalize settings, apply defaults, etc.
     $settings = self::_normalizeSettings($settings);
     // Connect to Dropbox.
     if (false === self::_connect($settings['access_token'])) {
         // Try to connect. Return false if fail.
         return false;
     }
     $max_chunk_size_bytes = $settings['max_chunk_size'] * 1024 * 1024;
     /***** BEGIN MULTIPART CHUNKED CONTINUE *****/
     // Continue Multipart Chunked Upload
     if ($settings['_chunk_upload_id'] != '') {
         $file = $settings['_chunk_file'];
         pb_backupbuddy::status('details', 'Dropbox (PHP 5.3+) preparing to send chunked multipart upload part ' . ($settings['_chunk_sent_count'] + 1) . ' of ' . $settings['_chunk_total_count'] . ' with set chunk size of `' . $settings['max_chunk_size'] . '` MB. Dropbox Upload ID: `' . $settings['_chunk_upload_id'] . '`.');
         pb_backupbuddy::status('details', 'Opening file `' . basename($file) . '` to send.');
         $f = @fopen($file, 'rb');
         if (false === $f) {
             pb_backupbuddy::status('error', 'Error #87954435. Unable to open file `' . $file . '` to send to Dropbox.');
             return false;
         }
         // Seek to next chunk location.
         pb_backupbuddy::status('details', 'Seeking file to byte `' . $settings['_chunk_next_offset'] . '`.');
         if (0 != fseek($f, $settings['_chunk_next_offset'])) {
             // return of 0 is success.
             pb_backupbuddy::status('error', 'Unable to seek file to proper location offset `' . $settings['_chunk_next_offset'] . '`.');
         } else {
             pb_backupbuddy::status('details', 'Seek success.');
         }
         // Read this file chunk into memory.
         pb_backupbuddy::status('details', 'Reading chunk into memory.');
         try {
             $data = self::readFully($f, $settings['_chunk_maxsize']);
         } catch (\Exception $e) {
             pb_backupbuddy::status('error', 'Dropbox Error #484938376: ' . $e->getMessage());
             return false;
         }
         pb_backupbuddy::status('details', 'About to put chunk to Dropbox for continuation.');
         $send_time = -microtime(true);
         try {
             $result = self::$_dbxClient->chunkedUploadContinue($settings['_chunk_upload_id'], $settings['_chunk_next_offset'], $data);
         } catch (\Exception $e) {
             pb_backupbuddy::status('error', 'Dropbox Error #8754646: ' . $e->getMessage());
             return false;
         }
         // Examine response from Dropbox.
         if (true === $result) {
             // Upload success.
             pb_backupbuddy::status('details', 'Chunk upload continuation success with valid offset.');
         } elseif (false === $result) {
             // Failed.
             pb_backupbuddy::status('error', 'Chunk upload continuation failed at offset `' . $settings['_chunk_next_offset'] . '`.');
             return false;
         } elseif (is_numeric($result)) {
             // offset wrong. Update to use this.
             pb_backupbuddy::status('details', 'Chunk upload continuation received an updated offset response of `' . $result . '` when we tried `' . $settings['_chunk_next_offset'] . '`.');
             $settings['_chunk_next_offset'] = $result;
             // Try resending with corrected offset.
             try {
                 $result = self::$_dbxClient->chunkedUploadContinue($settings['_chunk_upload_id'], $settings['_chunk_next_offset'], $data);
             } catch (\Exception $e) {
                 pb_backupbuddy::status('error', 'Dropbox Error #8263836: ' . $e->getMessage());
                 return false;
             }
         }
         $send_time += microtime(true);
         $data_length = strlen($data);
         unset($data);
         // Calculate some stats to log.
         $chunk_transfer_speed = $data_length / $send_time;
         pb_backupbuddy::status('details', 'Dropbox chunk transfer stats - Sent: `' . pb_backupbuddy::$format->file_size($data_length) . '`, Transfer duration: `' . $send_time . '`, Speed: `' . pb_backupbuddy::$format->file_size($chunk_transfer_speed) . '`.');
         // Set options for subsequent step chunks.
         $chunked_destination_settings = $settings;
         $chunked_destination_settings['_chunk_offset'] = $data_length;
         $chunked_destination_settings['_chunk_sent_count']++;
         $chunked_destination_settings['_chunk_next_offset'] = $data_length * $chunked_destination_settings['_chunk_sent_count'];
         // First chunk was sent initiationg multipart send.
         $chunked_destination_settings['_chunk_transfer_speeds'][] = $chunk_transfer_speed;
         // Load destination fileoptions.
         pb_backupbuddy::status('details', 'About to load fileoptions data.');
         require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
         pb_backupbuddy::status('details', 'Fileoptions instance #15.');
         $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
         if (true !== ($result = $fileoptions_obj->is_ok())) {
             pb_backupbuddy::status('error', __('Fatal Error #9034.84838. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
             return false;
         }
         pb_backupbuddy::status('details', 'Fileoptions data loaded.');
         $fileoptions =& $fileoptions_obj->options;
         // Multipart send completed. Send finished signal to Dropbox to seal the deal.
         if (true === feof($f)) {
             pb_backupbuddy::status('details', 'At end of file. Finishing transfer and notifying Dropbox of file transfer completion.');
             $chunked_destination_settings['_chunk_upload_id'] = '';
             // Unset since chunking finished.
             try {
                 $result = self::$_dbxClient->chunkedUploadFinish($settings['_chunk_upload_id'], $settings['directory'] . '/' . basename($file), dbx\WriteMode::add());
             } catch (\Exception $e) {
                 pb_backupbuddy::status('error', 'Dropbox Error #549838979: ' . $e->getMessage());
                 return false;
             }
             pb_backupbuddy::status('details', 'Chunked upload finish results: `' . print_r($result, true) . '`.');
             if (filesize($settings['_chunk_file']) != $result['bytes']) {
                 pb_backupbuddy::status('error', 'Error #8958944. Dropbox reported file size differs from local size. The file upload may have been corrupted.');
                 return false;
             }
             $fileoptions['write_speed'] = array_sum($chunked_destination_settings['_chunk_transfer_speeds']) / $chunked_destination_settings['_chunk_sent_count'];
             $fileoptions['_multipart_status'] = 'Sent part ' . $chunked_destination_settings['_chunk_sent_count'] . ' of ' . $chunked_destination_settings['_chunk_total_count'] . '.';
             $fileoptions['finish_time'] = time();
             $fileoptions['status'] = 'success';
             $fileoptions_obj->save();
             unset($fileoptions_obj);
         }
         fclose($f);
         pb_backupbuddy::status('details', 'Sent chunk number `' . $chunked_destination_settings['_chunk_sent_count'] . '` to Dropbox with upload ID: `' . $chunked_destination_settings['_chunk_upload_id'] . '`. Next offset: `' . $chunked_destination_settings['_chunk_next_offset'] . '`.');
         // Schedule to continue if anything is left to upload for this multipart of any individual files.
         if ($chunked_destination_settings['_chunk_upload_id'] != '' || count($files) > 0) {
             pb_backupbuddy::status('details', 'Dropbox multipart upload has more parts left. Scheduling next part send.');
             $cronTime = time();
             $cronArgs = array($chunked_destination_settings, $files, $send_id, $delete_after);
             $cronHashID = md5($cronTime . serialize($cronArgs));
             $cronArgs[] = $cronHashID;
             $schedule_result = backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
             if (true === $schedule_result) {
                 pb_backupbuddy::status('details', 'Next Dropbox chunk step cron event scheduled.');
             } else {
                 pb_backupbuddy::status('error', 'Next Dropbox chunk step cron even FAILED to be scheduled.');
             }
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             return array($chunked_destination_settings['_chunk_upload_id'], 'Sent ' . $chunked_destination_settings['_chunk_sent_count'] . ' of ' . $chunked_destination_settings['_chunk_total_count'] . ' parts.');
         }
     }
     // end continue multipart chunked upload.
     /***** END MULTIPART CHUNKED CONTINUE *****/
     pb_backupbuddy::status('details', 'Looping through files to send to Dropbox.');
     foreach ($files as $file_id => $file) {
         $file_size = filesize($file);
         pb_backupbuddy::status('details', 'Opening file `' . basename($file) . '` to send.');
         $f = @fopen($file, 'rb');
         if (false === $f) {
             pb_backupbuddy::status('error', 'Error #8457573. Unable to open file `' . $file . '` to send to Dropbox.');
             return false;
         }
         if ($settings['max_chunk_size'] >= 5 && $file_size / 1024 / 1024 > $settings['max_chunk_size']) {
             // chunked send.
             pb_backupbuddy::status('details', 'File exceeds chunking limit of `' . $settings['max_chunk_size'] . '` MB. Using chunked upload for this file transfer.');
             // Read first file chunk into memory.
             pb_backupbuddy::status('details', 'Reading first chunk into memory.');
             try {
                 $data = self::readFully($f, $max_chunk_size_bytes);
             } catch (\Exception $e) {
                 pb_backupbuddy::status('error', 'Dropbox Error #5684574373: ' . $e->getMessage());
                 return false;
             }
             // Start chunk upload to get upload ID. Sends first chunk piece.
             $send_time = -microtime(true);
             pb_backupbuddy::status('details', 'About to start chunked upload & put first chunk of file `' . basename($file) . '` to Dropbox (PHP 5.3+).');
             try {
                 $result = self::$_dbxClient->chunkedUploadStart($data);
             } catch (\Exception $e) {
                 pb_backupbuddy::status('error', 'Dropbox Error: ' . $e->getMessage());
                 return false;
             }
             $send_time += microtime(true);
             @fclose($f);
             $data_length = strlen($data);
             unset($data);
             // Calculate some stats to log.
             $chunk_transfer_speed = $data_length / $send_time;
             pb_backupbuddy::status('details', 'Dropbox chunk transfer stats - Sent: `' . pb_backupbuddy::$format->file_size($data_length) . '`, Transfer duration: `' . $send_time . '`, Speed: `' . pb_backupbuddy::$format->file_size($chunk_transfer_speed) . '`.');
             // Set options for subsequent step chunks.
             $chunked_destination_settings = $settings;
             $chunked_destination_settings['_chunk_file'] = $file;
             $chunked_destination_settings['_chunk_maxsize'] = $max_chunk_size_bytes;
             $chunked_destination_settings['_chunk_upload_id'] = $result;
             $chunked_destination_settings['_chunk_offset'] = $data_length;
             $chunked_destination_settings['_chunk_next_offset'] = $data_length;
             // First chunk was sent initiationg multipart send.
             $chunked_destination_settings['_chunk_sent_count'] = 1;
             $chunked_destination_settings['_chunk_total_count'] = ceil($file_size / $max_chunk_size_bytes);
             $chunked_destination_settings['_chunk_transfer_speeds'][] = $chunk_transfer_speed;
             pb_backupbuddy::status('details', 'Sent first chunk to Dropbox with upload ID: `' . $chunked_destination_settings['_chunk_upload_id'] . '`. Offset: `' . $chunked_destination_settings['_chunk_offset'] . '`.');
             // Remove this file from list to send before passing $files to schedule next cron. Multipart will handle this from here on out.
             unset($files[$file_id]);
             // Schedule next chunk to send.
             pb_backupbuddy::status('details', 'Dropbox (PHP 5.3+) scheduling send of next part(s).');
             $cronTime = time();
             $cronArgs = array($chunked_destination_settings, $files, $send_id, $delete_after);
             $cronHashID = md5($cronTime . serialize($cronArgs));
             $cronArgs[] = $cronHashID;
             if (false === backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs)) {
                 pb_backupbuddy::status('error', 'Error #948844: Unable to schedule next Dropbox2 cron chunk.');
                 return false;
             } else {
                 pb_backupbuddy::status('details', 'Success scheduling next cron chunk.');
             }
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             pb_backupbuddy::status('details', 'Dropbox (PHP 5.3+) scheduled send of next part(s). Done for this cycle.');
             return array($chunked_destination_settings['_chunk_upload_id'], 'Sent 1 of ' . $chunked_destination_settings['_chunk_total_count'] . ' parts.');
         } else {
             // normal (non-chunked) send.
             pb_backupbuddy::status('details', 'Dropbox send not set to be chunked.');
             pb_backupbuddy::status('details', 'About to put file `' . basename($file) . '` (' . pb_backupbuddy::$format->file_size($file_size) . ') to Dropbox (PHP 5.3+).');
             $send_time = -microtime(true);
             try {
                 $result = self::$_dbxClient->uploadFile($settings['directory'] . '/' . basename($file), dbx\WriteMode::add(), $f);
             } catch (\Exception $e) {
                 pb_backupbuddy::status('error', 'Dropbox Error: ' . $e->getMessage());
                 return false;
             }
             $send_time += microtime(true);
             @fclose($f);
             pb_backupbuddy::status('details', 'About to load fileoptions data.');
             require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
             pb_backupbuddy::status('details', 'Fileoptions instance #14.');
             $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
             if (true !== ($result = $fileoptions_obj->is_ok())) {
                 pb_backupbuddy::status('error', __('Fatal Error #9034.2344848. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
                 return false;
             }
             pb_backupbuddy::status('details', 'Fileoptions data loaded.');
             $fileoptions =& $fileoptions_obj->options;
             // Calculate some stats to log.
             $data_length = $file_size;
             $transfer_speed = $data_length / $send_time;
             pb_backupbuddy::status('details', 'Dropbox (non-chunked) transfer stats - Sent: `' . pb_backupbuddy::$format->file_size($data_length) . '`, Transfer duration: `' . $send_time . '`, Speed: `' . pb_backupbuddy::$format->file_size($transfer_speed) . '/sec`.');
             $fileoptions['write_speed'] = $transfer_speed;
             $fileoptions_obj->save();
             unset($fileoptions_obj);
         }
         // end normal (non-chunked) send.
         pb_backupbuddy::status('message', 'Success sending `' . basename($file) . '` to Dropbox!');
         // Start remote backup limit
         if ($settings['archive_limit'] > 0) {
             pb_backupbuddy::status('details', 'Dropbox file limit in place. Proceeding with enforcement.');
             $meta_data = self::$_dbxClient->getMetadataWithChildren($settings['directory']);
             // Create array of backups and organize by date
             $bkupprefix = backupbuddy_core::backup_prefix();
             $backups = array();
             foreach ((array) $meta_data['contents'] as $looping_file) {
                 if ($looping_file['is_dir'] == '1') {
                     // JUST IN CASE. IGNORE anything that is a directory.
                     continue;
                 }
                 // check if file is backup
                 if (strpos($looping_file['path'], 'backup-' . $bkupprefix . '-') !== false) {
                     // Appears to be a backup file.
                     $backups[$looping_file['path']] = strtotime($looping_file['modified']);
                 }
             }
             arsort($backups);
             if (count($backups) > $settings['archive_limit']) {
                 pb_backupbuddy::status('details', 'Dropbox backup file count of `' . count($backups) . '` exceeds limit of `' . $settings['archive_limit'] . '`.');
                 $i = 0;
                 $delete_fail_count = 0;
                 foreach ($backups as $buname => $butime) {
                     $i++;
                     if ($i > $settings['archive_limit']) {
                         if (!self::$_dbxClient->delete($buname)) {
                             // Try to delete backup on Dropbox. Increment failure count if unable to.
                             pb_backupbuddy::status('details', 'Unable to delete excess Dropbox file: `' . $buname . '`');
                             $delete_fail_count++;
                         } else {
                             pb_backupbuddy::status('details', 'Deleted excess Dropbox file: `' . $buname . '`');
                         }
                     }
                 }
                 if ($delete_fail_count !== 0) {
                     backupbuddy_core::mail_error(sprintf(__('Dropbox remote limit could not delete %s backups.', 'it-l10n-backupbuddy'), $delete_fail_count));
                 }
             }
         } else {
             pb_backupbuddy::status('details', 'No Dropbox file limit to enforce.');
         }
         // End remote backup limit
     }
     // end foreach.
     pb_backupbuddy::status('details', 'All files sent.');
     return true;
     // Success if made it this far.
 }
Пример #20
0
 public static function send($settings = array(), $files = array(), $send_id = '', $delete_after = false, $delete_remote_after = false)
 {
     global $pb_backupbuddy_destination_errors;
     if ('1' == $settings['disabled']) {
         $pb_backupbuddy_destination_errors[] = __('Error #48933: This destination is currently disabled. Enable it under this destination\'s Advanced Settings.', 'it-l10n-backupbuddy');
         return false;
     }
     if (!is_array($files)) {
         $files = array($files);
     }
     pb_backupbuddy::status('details', 'Google Drive send() function started. Settings: `' . print_r($settings, true) . '`.');
     self::$_timeStart = microtime(true);
     $settings = self::_normalizeSettings($settings);
     if (false === ($settings = self::_connect($settings))) {
         // $settings =
         return self::_error('Error #38923923: Unable to connect with Google Drive. See log for details.');
     }
     $folderID = $settings['folderID'];
     if ('' == $folderID) {
         $folderID = 'root';
     }
     $chunkSizeBytes = $settings['max_burst'] * 1024 * 1024;
     // Send X mb at a time to limit memory usage.
     foreach ($files as $file) {
         // Determine backup type for limiting later.
         $backup_type = '';
         if (stristr($file, '-db-') !== false) {
             $backup_type = 'db';
         } elseif (stristr($file, '-full-') !== false) {
             $backup_type = 'full';
         } elseif (stristr($file, '-files-') !== false) {
             $backup_type = 'files';
         } elseif (stristr($file, '-export-') !== false) {
             $backup_type = 'export';
         }
         if (!file_exists($file)) {
             return self::_error('Error #37792: File selected to send not found: `' . $file . '`.');
         }
         $fileSize = filesize($file);
         $fileinfo = pathinfo($file);
         $fileextension = $fileinfo['extension'];
         if ('zip' == $fileextension) {
             $mimeType = 'application/zip';
         } elseif ('php' == $fileextension) {
             $mimeType = 'application/x-httpd-php';
         } else {
             $mimeType = '';
         }
         pb_backupbuddy::status('details', 'About to upload file `' . $file . '` of size `' . $fileSize . '` with mimetype `' . $mimeType . '` into folder `' . $folderID . '`. Internal chunk size of `' . $chunkSizeBytes . '` bytes.');
         if ($fileSize > $chunkSizeBytes) {
             pb_backupbuddy::status('details', 'File size `' . pb_backupbuddy::$format->file_size($fileSize) . '` exceeds max burst size `' . $settings['max_burst'] . ' MB` so this will be sent in bursts. If time limit nears then send will be chunked across multiple PHP loads.');
             $settings['_chunks_total'] = ceil($fileSize / $chunkSizeBytes);
         }
         if (0 == $settings['_chunks_total']) {
             $settings['_chunks_total'] = 1;
         }
         //Insert a file
         $driveFile = new Google_Service_Drive_DriveFile();
         $driveFile->setTitle(basename($file));
         $driveFile->setDescription('BackupBuddy file');
         $driveFile->setMimeType($mimeType);
         // Set the parent folder.
         if ('root' != $folderID) {
             $parentsCollectionData = new Google_Service_Drive_ParentReference();
             $parentsCollectionData->setId($folderID);
             $driveFile->setParents(array($parentsCollectionData));
         }
         self::$_client->setDefer(true);
         try {
             $insertRequest = self::$_drive->files->insert($driveFile);
         } catch (Exception $e) {
             pb_backupbuddy::alert('Error #3232783268336: initiating upload. Details: ' . $e->getMessage());
             return false;
         }
         // Handle getting resume information to see if resuming is still an option.
         $resumable = false;
         if ('' != $settings['_media_resumeUri']) {
             $headers = array('content-range' => 'bytes */' . $fileSize);
             $request = new Google_Http_Request($settings['_media_resumeUri'], 'PUT', $headers, '');
             $response = self::$_client->getIo()->makeRequest($request);
             if (308 == $response->getResponseHttpCode()) {
                 $range = $response->getResponseHeader('range');
                 if (!empty($range) && preg_match('/bytes=0-(\\d+)$/', $range, $matches)) {
                     $resumable = true;
                     pb_backupbuddy::status('details', 'Last send reported next byte to be `' . $settings['_media_progress'] . '`.');
                     $settings['_media_progress'] = $matches[1] + 1;
                     pb_backupbuddy::status('details', 'Google Drive resuming is available. Google Drive reports next byte to be `' . $settings['_media_progress'] . '`. Range: `' . $range . '`.');
                 }
             }
             if (!$resumable) {
                 pb_backupbuddy::status('details', 'Google Drive could not resume. Too much time may have passed or some other cause.');
             }
             if ($settings['_media_progress'] >= $fileSize) {
                 pb_backupbuddy::status('details', 'Google Drive resuming not needed. Remote file meets or exceeds file size. Completed.');
                 return true;
             }
         }
         // See https://developers.google.com/api-client-library/php/guide/media_upload
         try {
             $media = new Google_Http_MediaFileUpload(self::$_client, $insertRequest, $mimeType, null, true, $chunkSizeBytes);
         } catch (Exception $e) {
             pb_backupbuddy::alert('Error #3893273937: initiating upload. Details: ' . $e->getMessage());
             return;
         }
         $media->setFileSize($fileSize);
         // Reset these internal variables. NOTE: These are by default private. Must modify MediaFileUpload.php to make this possible by setting these vars public. Thanks Google!
         if ('' != $settings['_media_resumeUri']) {
             $media->resumeUri = $settings['_media_resumeUri'];
             $media->progress = $settings['_media_progress'];
         }
         pb_backupbuddy::status('details', 'Opening file for sending in binary mode.');
         $fs = fopen($file, 'rb');
         // If chunked resuming then seek to the correct place in the file.
         if ('' != $settings['_media_progress'] && $settings['_media_progress'] > 0) {
             // Resuming send of a partially transferred file.
             if (0 !== fseek($fs, $settings['_media_progress'])) {
                 // Go off the resume point as given by Google in case it didnt all make it. //$settings['resume_point'] ) ) { // Returns 0 on success.
                 pb_backupbuddy::status('error', 'Error #3872733: Failed to seek file to resume point `' . $settings['_media_progress'] . '` via fseek().');
                 return false;
             }
             $prevPointer = $settings['_media_progress'];
             //$settings['resume_point'];
         } else {
             // New file send.
             $prevPointer = 0;
         }
         $needProcessChunking = false;
         // Set true if we need to spawn off resuming to a new PHP page load.
         $uploadStatus = false;
         while (!$uploadStatus && !feof($fs)) {
             $chunk = fread($fs, $chunkSizeBytes);
             pb_backupbuddy::status('details', 'Chunk of size `' . pb_backupbuddy::$format->file_size($chunkSizeBytes) . '` read into memory. Total bytes summed: `' . ($settings['_media_progress'] + strlen($chunk)) . '` of filesize: `' . $fileSize . '`.');
             pb_backupbuddy::status('details', 'Sending burst file data next. If next message is not "Burst file data sent" then the send likely timed out. Try reducing burst size. Sending now...');
             // Send chunk of data.
             try {
                 $uploadStatus = $media->nextChunk($chunk);
             } catch (Exception $e) {
                 global $pb_backupbuddy_destination_errors;
                 $pb_backupbuddy_destination_errors[] = $e->getMessage();
                 $error = $e->getMessage();
                 pb_backupbuddy::status('error', 'Error #8239832: Error sending burst data. Details: `' . $error . '`.');
                 return false;
             }
             $settings['_chunks_sent']++;
             self::$_chunksSentThisRound++;
             pb_backupbuddy::status('details', 'Burst file data sent.');
             $maxTime = $settings['max_time'];
             if ('' == $maxTime || !is_numeric($maxTime)) {
                 pb_backupbuddy::status('details', 'Max time not set in settings so detecting server max PHP runtime.');
                 $maxTime = backupbuddy_core::detectMaxExecutionTime();
             }
             //return;
             // Handle splitting up across multiple PHP page loads if needed.
             if (!feof($fs) && 0 != $maxTime) {
                 // More data remains so see if we need to consider chunking to a new PHP process.
                 // If we are within X second of reaching maximum PHP runtime then stop here so that it can be picked up in another PHP process...
                 $totalSizeSent = self::$_chunksSentThisRound * $chunkSizeBytes;
                 // Total bytes sent this PHP load.
                 $bytesPerSec = $totalSizeSent / (microtime(true) - self::$_timeStart);
                 $timeRemaining = $maxTime - (microtime(true) - self::$_timeStart + self::TIME_WIGGLE_ROOM);
                 if ($timeRemaining < 0) {
                     $timeRemaining = 0;
                 }
                 $bytesWeCouldSendWithTimeLeft = $bytesPerSec * $timeRemaining;
                 pb_backupbuddy::status('details', 'Total sent: `' . pb_backupbuddy::$format->file_size($totalSizeSent) . '`. Speed (per sec): `' . pb_backupbuddy::$format->file_size($bytesPerSec) . '`. Time Remaining (w/ wiggle): `' . $timeRemaining . '`. Size that could potentially be sent with remaining time: `' . pb_backupbuddy::$format->file_size($bytesWeCouldSendWithTimeLeft) . '` with chunk size of `' . pb_backupbuddy::$format->file_size($chunkSizeBytes) . '`.');
                 if ($bytesWeCouldSendWithTimeLeft < $chunkSizeBytes) {
                     // We can send more than a whole chunk (including wiggle room) so send another bit.
                     pb_backupbuddy::status('message', 'Not enough time left (~`' . $timeRemaining . '`) with max time of `' . $maxTime . '` sec to send another chunk at `' . pb_backupbuddy::$format->file_size($bytesPerSec) . '` / sec. Ran for ' . round(microtime(true) - self::$_timeStart, 3) . ' sec. Proceeding to use chunking.');
                     @fclose($fs);
                     // Tells next chunk where to pick up.
                     if (isset($chunksTotal)) {
                         $settings['_chunks_total'] = $chunksTotal;
                     }
                     // Grab these vars from the class.  Note that we changed these vars from private to public to make chunked resuming possible.
                     $settings['_media_resumeUri'] = $media->resumeUri;
                     $settings['_media_progress'] = $media->progress;
                     // Schedule cron.
                     $cronTime = time();
                     $cronArgs = array($settings, $files, $send_id, $delete_after);
                     $cronHashID = md5($cronTime . serialize($cronArgs));
                     $cronArgs[] = $cronHashID;
                     $schedule_result = backupbuddy_core::schedule_single_event($cronTime, 'destination_send', $cronArgs);
                     if (true === $schedule_result) {
                         pb_backupbuddy::status('details', 'Next Site chunk step cron event scheduled.');
                     } else {
                         pb_backupbuddy::status('error', 'Next Site chunk step cron even FAILED to be scheduled.');
                     }
                     spawn_cron(time() + 150);
                     // Adds > 60 seconds to get around once per minute cron running limit.
                     update_option('_transient_doing_cron', 0);
                     // Prevent cron-blocking for next item.
                     return array($prevPointer, 'Sent part ' . $settings['_chunks_sent'] . ' of ~' . $settings['_chunks_total'] . ' parts.');
                     // filepointer location, elapsed time during the import
                 } else {
                     // End if.
                     pb_backupbuddy::status('details', 'Not approaching limits.');
                 }
             } else {
                 pb_backupbuddy::status('details', 'No more data remains (eg for chunking) so finishing up.');
                 if ('' != $send_id) {
                     require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
                     $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
                     if (true !== ($result = $fileoptions_obj->is_ok())) {
                         pb_backupbuddy::status('error', __('Fatal Error #9034.397237. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
                         return false;
                     }
                     pb_backupbuddy::status('details', 'Fileoptions data loaded.');
                     $fileoptions =& $fileoptions_obj->options;
                     $fileoptions['_multipart_status'] = 'Sent part ' . $settings['_chunks_sent'] . ' of ~' . $settings['_chunks_total'] . ' parts.';
                     $fileoptions['finish_time'] = microtime(true);
                     $fileoptions['status'] = 'success';
                     $fileoptions_obj->save();
                     unset($fileoptions_obj);
                 }
             }
         }
         fclose($fs);
         self::$_client->setDefer(false);
         if (false == $uploadStatus) {
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = 'Error #84347474 sending. Details: ' . $uploadStatus;
             return false;
         } else {
             // Success.
             if (true === $delete_remote_after) {
                 self::deleteFile($settings, $uploadStatus->id);
             }
         }
     }
     // end foreach.
     $db_archive_limit = $settings['db_archive_limit'];
     $full_archive_limit = $settings['full_archive_limit'];
     $files_archive_limit = $settings['files_archive_limit'];
     // BEGIN FILE LIMIT PROCESSING. Enforce archive limits if applicable.
     if ($backup_type == 'full') {
         $limit = $full_archive_limit;
     } elseif ($backup_type == 'db') {
         $limit = $db_archive_limit;
     } elseif ($backup_type == 'files') {
         $limit = $files_archive_limit;
     } else {
         $limit = 0;
         pb_backupbuddy::status('warning', 'Warning #34352453244. Google Drive was unable to determine backup type (reported: `' . $backup_type . '`) so archive limits NOT enforced for this backup.');
     }
     pb_backupbuddy::status('details', 'Google Drive database backup archive limit of `' . $limit . '` of type `' . $backup_type . '` based on destination settings.');
     if ($limit > 0) {
         pb_backupbuddy::status('details', 'Google Drive archive limit enforcement beginning.');
         // Get file listing.
         $searchCount = 1;
         $remoteFiles = array();
         while (count($remoteFiles) == 0 && $searchCount < 5) {
             pb_backupbuddy::status('details', 'Checking archive limits. Attempt ' . $searchCount . '.');
             $remoteFiles = pb_backupbuddy_destination_gdrive::listFiles($settings, "title contains 'backup-' AND title contains '-" . $backup_type . "-' AND '" . $folderID . "' IN parents AND trashed=false");
             //"title contains 'backup' and trashed=false" );
             sleep(1);
             $searchCount++;
         }
         // List backups associated with this site by date.
         $backups = array();
         $prefix = backupbuddy_core::backup_prefix();
         foreach ($remoteFiles as $remoteFile) {
             if ('application/vnd.google-apps.folder' == $remoteFile->mimeType) {
                 // Ignore folders.
                 continue;
             }
             if (strpos($remoteFile->originalFilename, 'backup-' . $prefix . '-') !== false) {
                 // Appears to be a backup file for this site.
                 $backups[$remoteFile->id] = strtotime($remoteFile->modifiedDate);
             }
         }
         arsort($backups);
         pb_backupbuddy::status('details', 'Google Drive found `' . count($backups) . '` backups of this type when checking archive limits.');
         if (count($backups) > $limit) {
             pb_backupbuddy::status('details', 'More archives (' . count($backups) . ') than limit (' . $limit . ') allows. Trimming...');
             $i = 0;
             $delete_fail_count = 0;
             foreach ($backups as $buname => $butime) {
                 $i++;
                 if ($i > $limit) {
                     pb_backupbuddy::status('details', 'Trimming excess file `' . $buname . '`...');
                     if (true !== self::deleteFile($settings, $buname)) {
                         pb_backupbuddy::status('details', 'Unable to delete excess Google Drive file `' . $buname . '`. Details: `' . print_r($pb_backupbuddy_destination_errors, true) . '`.');
                         $delete_fail_count++;
                     }
                 }
             }
             pb_backupbuddy::status('details', 'Finished trimming excess backups.');
             if ($delete_fail_count !== 0) {
                 $error_message = 'Google Drive remote limit could not delete ' . $delete_fail_count . ' backups.';
                 pb_backupbuddy::status('error', $error_message);
                 backupbuddy_core::mail_error($error_message);
             }
         }
         pb_backupbuddy::status('details', 'Google Drive completed archive limiting.');
     } else {
         pb_backupbuddy::status('details', 'No Google Drive archive file limit to enforce.');
     }
     // End remote backup limit
     // Made it this far then success.
     return true;
 }
Пример #21
0
    }
    if ($backup_file_size + $stash_quota['quota_used'] > $stash_quota['quota_total']) {
        echo "You do not have enough Stash storage space to send this file. Please upgrade your Stash storage or delete files to make space.\n\n";
        echo 'Attempting to send file of size ' . pb_backupbuddy::$format->file_size($backup_file_size) . ' but you only have ' . $stash_quota['quota_available_nice'] . ' available. ';
        echo 'Currently using ' . $stash_quota['quota_used_nice'] . ' of ' . $stash_quota['quota_total_nice'] . ' (' . $stash_quota['quota_used_percent'] . '%).';
        die;
    } else {
        if (isset($stash_quota['quota_warning']) && $stash_quota['quota_warning'] != '') {
            echo '1Warning: ' . $stash_quota['quota_warning'] . "\n\n";
            $success_output = true;
        }
    }
}
// end if Stash.
pb_backupbuddy::status('details', 'Scheduling cron to send to this remote destination...');
$schedule_result = backupbuddy_core::schedule_single_event(time(), 'remote_send', array($destination_id, $backup_file, pb_backupbuddy::_POST('trigger'), $send_importbuddy, $delete_after));
if ($schedule_result === FALSE) {
    $error = 'Error scheduling file transfer. Please check your BackupBuddy error log for details. A plugin may have prevented scheduling or the database rejected it.';
    pb_backupbuddy::status('error', $error);
    echo $error;
} else {
    pb_backupbuddy::status('details', 'Cron to send to remote destination scheduled.');
}
spawn_cron(time() + 150);
// Adds > 60 seconds to get around once per minute cron running limit.
update_option('_transient_doing_cron', 0);
// Prevent cron-blocking for next item.
// SEE cron.php remote_send() for sending function that we pass to via the cron above.
if ($success_output === false) {
    echo 1;
}
Пример #22
0
            $deleted_files[] = $item;
        } else {
            pb_backupbuddy::alert('Error: Unable to delete `' . $item . '`. Verify permissions.');
        }
    }
    if (count($deleted_files) > 0) {
        pb_backupbuddy::alert('Deleted ' . implode(', ', $deleted_files) . '.');
    }
    echo '<br>';
}
// Handle copying files to local
if (pb_backupbuddy::_GET('cpy_file') != '') {
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating S3 copy.');
    backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('process_remote_copy'), array('s3', pb_backupbuddy::_GET('cpy_file'), $settings));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
// Handle download link
if (pb_backupbuddy::_GET('downloadlink_file') != '') {
    $link = $s3->get_object($manage_data['bucket'], $remote_path . pb_backupbuddy::_GET('downloadlink_file'), array('preauth' => time() + 3600));
    pb_backupbuddy::alert('You may download this backup (' . pb_backupbuddy::_GET('downloadlink_file') . ') with <a href="' . $link . '">this link</a>. The link is valid for one hour.');
    echo '<br>';
}
$prefix = backupbuddy_core::backup_prefix();
// Get file listing.
$response = $s3->list_objects($manage_data['bucket'], array('prefix' => $remote_path));
// list all the files in the subscriber account
Пример #23
0
 public function remote_send()
 {
     $success_output = false;
     // Set to true onece a leading 1 has been sent to the javascript to indicate success.
     $destination_id = pb_backupbuddy::_POST('destination_id');
     if (pb_backupbuddy::_POST('file') != 'importbuddy.php') {
         $backup_file = backupbuddy_core::getBackupDirectory() . pb_backupbuddy::_POST('file');
         if (!file_exists($backup_file)) {
             // Error if file to send did not exist!
             $error_message = 'Unable to find file `' . $backup_file . '` to send. File does not appear to exist. You can try again in a moment or turn on full error logging and try again to log for support.';
             pb_backupbuddy::status('error', $error_message);
             pb_backupbuddy::alert($error_message, true);
             die;
         }
     } else {
         $backup_file = '';
     }
     // Send ImportBuddy along-side?
     if (pb_backupbuddy::_POST('send_importbuddy') == '1') {
         $send_importbuddy = true;
         pb_backupbuddy::status('details', 'Cron send to be scheduled with importbuddy sending.');
     } else {
         $send_importbuddy = false;
         pb_backupbuddy::status('details', 'Cron send to be scheduled WITHOUT importbuddy sending.');
     }
     // Delete local copy after send completes?
     if (pb_backupbuddy::_POST('delete_after') == 'true') {
         $delete_after = true;
         pb_backupbuddy::status('details', 'Remote send set to delete after successful send.');
     } else {
         $delete_after = false;
         pb_backupbuddy::status('details', 'Remote send NOT set to delete after successful send.');
     }
     // For Stash we will check the quota prior to initiating send.
     if (pb_backupbuddy::$options['remote_destinations'][$destination_id]['type'] == 'stash') {
         // Pass off to destination handler.
         require_once pb_backupbuddy::plugin_path() . '/destinations/bootstrap.php';
         $send_result = pb_backupbuddy_destinations::get_info('stash');
         // Used to kick the Stash destination into life.
         $stash_quota = pb_backupbuddy_destination_stash::get_quota(pb_backupbuddy::$options['remote_destinations'][$destination_id], true);
         if (isset($stash_quota['error'])) {
             echo ' Error accessing Stash account. Send aborted. Details: `' . implode(' - ', $stash_quota['error']) . '`.';
             die;
         }
         if ($backup_file != '') {
             $backup_file_size = filesize($backup_file);
         } else {
             $backup_file_size = 50000;
         }
         if ($backup_file_size + $stash_quota['quota_used'] > $stash_quota['quota_total']) {
             echo "You do not have enough Stash storage space to send this file. Please upgrade your Stash storage or delete files to make space.\n\n";
             echo 'Attempting to send file of size ' . pb_backupbuddy::$format->file_size($backup_file_size) . ' but you only have ' . $stash_quota['quota_available_nice'] . ' available. ';
             echo 'Currently using ' . $stash_quota['quota_used_nice'] . ' of ' . $stash_quota['quota_total_nice'] . ' (' . $stash_quota['quota_used_percent'] . '%).';
             die;
         } else {
             if (isset($stash_quota['quota_warning']) && $stash_quota['quota_warning'] != '') {
                 echo '1Warning: ' . $stash_quota['quota_warning'] . "\n\n";
                 $success_output = true;
             }
         }
     }
     // end if Stash.
     pb_backupbuddy::status('details', 'Scheduling cron to send to this remote destination...');
     $schedule_result = backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('remote_send'), array($destination_id, $backup_file, pb_backupbuddy::_POST('trigger'), $send_importbuddy, $delete_after));
     if ($schedule_result === FALSE) {
         $error = 'Error scheduling file transfer. Please check your BackupBuddy error log for details. A plugin may have prevented scheduling or the database rejected it.';
         pb_backupbuddy::status('error', $error);
         echo $error;
     } else {
         pb_backupbuddy::status('details', 'Cron to send to remote destination scheduled.');
     }
     spawn_cron(time() + 150);
     // Adds > 60 seconds to get around once per minute cron running limit.
     update_option('_transient_doing_cron', 0);
     // Prevent cron-blocking for next item.
     // SEE cron.php remote_send() for sending function that we pass to via the cron above.
     if ($success_output === false) {
         echo 1;
     }
     die;
 }
Пример #24
0
    pb_backupbuddy::$options['remote_destinations'][$destination_id]['pause_continuous'] = '1';
    $saving = true;
}
/***** END CONTINOUS *****/
/***** BEGIN PERIODIC *****/
if (false === $pause_periodic) {
    // Unpause.
    $prior_periodic_status = pb_backupbuddy::$options['remote_destinations'][$destination_id]['pause_periodic'];
    pb_backupbuddy::$options['remote_destinations'][$destination_id]['pause_periodic'] = '0';
    if ('1' == $prior_periodic_status) {
        // Was paused, now unpaused, so check if we need to run now.
        if (true === $start_run) {
            pb_backupbuddy::save();
            // Must save prior to spawning.
            $cronArgs = array();
            $schedule_result = backupbuddy_core::schedule_single_event(time(), 'live_periodic', $cronArgs);
            if (true === $schedule_result) {
                pb_backupbuddy::status('details', 'Next Live Periodic chunk step cron event scheduled.');
            } else {
                pb_backupbuddy::status('error', 'Next Live Periodic chunk step cron event FAILED to be scheduled.');
            }
            if ('1' != pb_backupbuddy::$options['skip_spawn_cron_call']) {
                pb_backupbuddy::status('details', 'Spawning cron now.');
                update_option('_transient_doing_cron', 0);
                // Prevent cron-blocking for next item.
                spawn_cron(time() + 150);
                // Adds > 60 seconds to get around once per minute cron running limit.
            }
        }
    }
    $saving = true;
Пример #25
0
<?php

// @author Dustin Bolton, July 2013.
// Incoming variables: $destination
//pb_backupbuddy::$ui->title( 'Dropbox destination "' . htmlentities( $destination['title'] ) . '"' );
// Copy remote file down to local.
if ('' != pb_backupbuddy::_GET('cpy')) {
    // Copy dropbox backups to the local backup files
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating Dropbox copy.');
    backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('process_destination_copy'), array($destination, pb_backupbuddy::_GET('cpy')));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
// Delete selected dropbox backup(s) from form submission.
if ('delete_backup' == pb_backupbuddy::_POST('bulk_action')) {
    pb_backupbuddy::verify_nonce();
    if (is_array(pb_backupbuddy::_POST('items'))) {
        if (true === ($result = pb_backupbuddy_destinations::delete($destination, pb_backupbuddy::_POST('items')))) {
            pb_backupbuddy::alert(__('Selected file(s) deleted.', 'it-l10n-backupbuddy'));
        } else {
            pb_backupbuddy::alert(__('Unable to delete one or more files. Details: ', 'it-l10n-backupbuddy') . $result);
        }
        echo '<br>';
    }
}
$files_result = pb_backupbuddy_destinations::listFiles($destination);
$backup_files = array();
Пример #26
0
 public static function send($settings = array(), $files = array(), $send_id = '', $delete_after = false)
 {
     if (!is_array($files)) {
         $files = array($files);
     }
     global $pb_backupbuddy_destination_errors;
     $backup_type_dir = '';
     $region = '';
     $settings['bucket'] = strtolower($settings['bucket']);
     // Buckets must be lowercase.
     if (!is_array($files)) {
         $files = array($files);
     }
     $limit = $settings['archive_limit'];
     $max_chunk_size = $settings['max_chunk_size'];
     $remote_path = self::get_remote_path($settings['directory']);
     // Has leading and trailng slashes.
     if ($settings['ssl'] == '0') {
         $disable_ssl = true;
     } else {
         $disable_ssl = false;
     }
     $multipart_id = $settings['_multipart_id'];
     $multipart_counts = $settings['_multipart_counts'];
     pb_backupbuddy::status('details', 'S3 remote path set to `' . $remote_path . '`.');
     pb_backupbuddy::status('details', 'Loading S3 SDK library file...');
     require_once dirname(dirname(__FILE__)) . '/_s3lib/aws-sdk/sdk.class.php';
     pb_backupbuddy::status('details', 'S3 SDK file loaded.');
     // S3 API talk.
     $manage_data = pb_backupbuddy_destination_s3::get_credentials($settings);
     // Process multipart transfer that we already initiated in a previous PHP load.
     if ($multipart_id != '') {
         // Multipart upload initiated and needs parts sent.
         // Create S3 instance.
         pb_backupbuddy::status('details', 'Creating S3 instance.');
         $s3 = new AmazonS3($manage_data);
         // the key, secret, token
         if ($disable_ssl === true) {
             @$s3->disable_ssl(true);
         }
         pb_backupbuddy::status('details', 'S3 instance created.');
         // Verify bucket exists; create if not. Also set region to the region bucket exists in.
         if (false === self::_prepareBucketAndRegion($s3, $settings)) {
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = 'Could not prepare bucket.';
             return false;
         }
         $this_part_number = $settings['_multipart_partnumber'] + 1;
         pb_backupbuddy::status('details', 'S3 beginning upload of part `' . $this_part_number . '` of `' . count($settings['_multipart_counts']) . '` parts of file `' . $settings['_multipart_file'] . '` to remote location `' . $settings['_multipart_remotefile'] . '` with multipart ID `' . $settings['_multipart_id'] . '`.');
         $response = $s3->upload_part($manage_data['bucket'], $settings['_multipart_remotefile'], $settings['_multipart_id'], array('expect' => '100-continue', 'fileUpload' => $settings['_multipart_file'], 'partNumber' => $this_part_number, 'seekTo' => (int) $settings['_multipart_counts'][$settings['_multipart_partnumber']]['seekTo'], 'length' => (int) $settings['_multipart_counts'][$settings['_multipart_partnumber']]['length']));
         if (!$response->isOK()) {
             $this_error = 'S3 unable to upload file part for multipart upload `' . $settings['_multipart_id'] . '`. Details: `' . print_r($response, true) . '`.';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         } else {
             // Send success.
             pb_backupbuddy::status('details', 'Success sending chunk. Upload details: `' . print_r($response, true) . '`.');
             $uploaded_size = $response->header['_info']['size_upload'];
             $uploaded_speed = $response->header['_info']['speed_upload'];
             pb_backupbuddy::status('details', 'Uploaded size: ' . pb_backupbuddy::$format->file_size($uploaded_size) . ', Speed: ' . pb_backupbuddy::$format->file_size($uploaded_speed) . '/sec.');
         }
         // Load fileoptions to the send.
         pb_backupbuddy::status('details', 'About to load fileoptions data.');
         require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
         pb_backupbuddy::status('details', 'Fileoptions instance #10.');
         $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
         if (true !== ($result = $fileoptions_obj->is_ok())) {
             pb_backupbuddy::status('error', __('Fatal Error #9034.2344848. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = '#9034.2344848';
             return false;
         }
         pb_backupbuddy::status('details', 'Fileoptions data loaded.');
         $fileoptions =& $fileoptions_obj->options;
         $update_status = 'Sent part ' . $this_part_number . ' of ' . count($settings['_multipart_counts']) . '.';
         // Made it here so success sending part. Increment for next part to send.
         $settings['_multipart_partnumber']++;
         if (!isset($settings['_multipart_counts'][$settings['_multipart_partnumber']])) {
             // No more parts exist for this file. Tell S3 the multipart upload is complete and move on.
             pb_backupbuddy::status('details', 'S3 getting parts with etags to notify S3 of completed multipart send.');
             $etag_parts = $s3->list_parts($manage_data['bucket'], $settings['_multipart_remotefile'], $settings['_multipart_id']);
             pb_backupbuddy::status('details', 'S3 got parts list. Details: ' . print_r($etag_parts, true));
             pb_backupbuddy::status('details', 'Notifying S3 of multipart upload completion.');
             $response = $s3->complete_multipart_upload($manage_data['bucket'], $settings['_multipart_remotefile'], $settings['_multipart_id'], $etag_parts);
             if (!$response->isOK()) {
                 $this_error = 'S3 unable to notify S3 of completion of all parts for multipart upload `' . $settings['_multipart_id'] . '`.';
                 global $pb_backupbuddy_destination_errors;
                 $pb_backupbuddy_destination_errors[] = $this_error;
                 pb_backupbuddy::status('error', $this_error);
                 return false;
             } else {
                 pb_backupbuddy::status('details', 'S3 notified S3 of multipart completion.');
             }
             pb_backupbuddy::status('details', 'S3 has no more parts left for this multipart upload. Clearing multipart instance variables.');
             $settings['_multipart_partnumber'] = 0;
             $settings['_multipart_id'] = '';
             $settings['_multipart_file'] = '';
             $settings['_multipart_remotefile'] = '';
             // Multipart completed so safe to prevent housekeeping of incomplete multipart uploads.
             $settings['_multipart_transferspeeds'][] = $uploaded_speed;
             // Overall upload speed average.
             $uploaded_speed = array_sum($settings['_multipart_transferspeeds']) / count($settings['_multipart_counts']);
             pb_backupbuddy::status('details', 'Upload speed average of all chunks: `' . pb_backupbuddy::$format->file_size($uploaded_speed) . '`.');
             $settings['_multipart_counts'] = array();
             // Update stats.
             $fileoptions['_multipart_status'] = $update_status;
             $fileoptions['finish_time'] = time();
             $fileoptions['status'] = 'success';
             if (isset($uploaded_speed)) {
                 $fileoptions['write_speed'] = $uploaded_speed;
             }
             $fileoptions_obj->save();
             unset($fileoptions);
         }
         // Schedule to continue if anything is left to upload for this multipart of any individual files.
         if ($settings['_multipart_id'] != '' || count($files) > 0) {
             pb_backupbuddy::status('details', 'S3 multipart upload has more parts left. Scheduling next part send.');
             $cronTime = time();
             $cronArgs = array($settings, $files, $send_id, $delete_after);
             $cronHashID = md5($cronTime . serialize($cronArgs));
             $cronArgs[] = $cronHashID;
             $schedule_result = backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
             if (true === $schedule_result) {
                 pb_backupbuddy::status('details', 'Next S3 chunk step cron event scheduled.');
             } else {
                 pb_backupbuddy::status('error', 'Next S3 chunk step cron even FAILED to be scheduled.');
             }
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             return array($settings['_multipart_id'], 'Sent part ' . $this_part_number . ' of ' . count($settings['_multipart_counts']) . ' parts.');
         }
     }
     // end if multipart continuation.
     require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
     // Upload each file.
     foreach ($files as $file_id => $file) {
         // Determine backup type directory (if zip).
         $backup_type_dir = '';
         $backup_type = '';
         if (stristr($file, '.zip') !== false) {
             // If a zip try to determine backup type.
             pb_backupbuddy::status('details', 'S3: Zip file. Detecting backup type if possible.');
             $serial = backupbuddy_core::get_serial_from_file($file);
             // See if we can get backup type from fileoptions data.
             pb_backupbuddy::status('details', 'Fileoptions instance #9.');
             $backup_options = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/' . $serial . '.txt', $read_only = true, $ignore_lock = true);
             if (true !== ($result = $backup_options->is_ok())) {
                 pb_backupbuddy::status('error', 'Unable to open fileoptions file `' . backupbuddy_core::getLogDirectory() . 'fileoptions/' . $serial . '.txt' . '`.');
             } else {
                 if (isset($backup_options->options['integrity']['detected_type'])) {
                     pb_backupbuddy::status('details', 'S3: Detected backup type as `' . $backup_options->options['integrity']['detected_type'] . '` via integrity check data.');
                     //$backup_type_dir = $backup_options->options['integrity']['detected_type'] . '/';
                     $backup_type = $backup_options->options['integrity']['detected_type'];
                 }
             }
             // If still do not know backup type then attempt to deduce it from filename.
             if ($backup_type == '') {
                 if (stristr($file, '-db-') !== false) {
                     pb_backupbuddy::status('details', 'S3: Detected backup type as `db` via filename.');
                     //$backup_type_dir = 'db/';
                     $backup_type = 'db';
                 } elseif (stristr($file, '-full-') !== false) {
                     pb_backupbuddy::status('details', 'S3: Detected backup type as `full` via filename.');
                     //$backup_type_dir = 'full/';
                     $backup_type = 'full';
                 } else {
                     pb_backupbuddy::status('details', 'S3: Could not detect backup type via integrity details nor filename.');
                 }
             }
         }
         $credentials = pb_backupbuddy_destination_s3::get_credentials($settings);
         // Create S3 instance.
         pb_backupbuddy::status('details', 'Creating S3 instance.');
         $s3 = new AmazonS3($credentials);
         // the key, secret, token
         if ($disable_ssl === true) {
             @$s3->disable_ssl(true);
         }
         pb_backupbuddy::status('details', 'S3 instance created.');
         // Verify bucket exists; create if not. Also set region to the region bucket exists in.
         if (false === self::_prepareBucketAndRegion($s3, $settings)) {
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = 'Could not prepare bucket.';
             return false;
         }
         // Handle chunking of file into a multipart upload (if applicable).
         $file_size = filesize($file);
         if ($max_chunk_size >= self::MINIMUM_CHUNK_SIZE && $file_size / 1024 / 1024 > $max_chunk_size) {
             // minimum chunk size is 5mb. Anything under 5mb we will not chunk.
             // About to chunk so cleanup any previous hanging multipart transfers.
             self::multipart_cleanup($settings, $lessLogs = false);
             pb_backupbuddy::status('details', 'S3 file size of ' . pb_backupbuddy::$format->file_size($file_size) . ' exceeds max chunk size of ' . $max_chunk_size . 'MB set in settings for sending file as multipart upload.');
             // Initiate multipart upload with S3.
             pb_backupbuddy::status('details', 'Initiating S3 multipart upload.');
             $response = $s3->initiate_multipart_upload($settings['bucket'], $remote_path . $backup_type_dir . basename($file), array('encryption' => 'AES256'));
             if (!$response->isOK()) {
                 $this_error = 'S3 was unable to initiate multipart upload.';
                 global $pb_backupbuddy_destination_errors;
                 $pb_backupbuddy_destination_errors[] = $this_error;
                 pb_backupbuddy::status('error', $this_error);
                 return false;
             } else {
                 $upload_id = (string) $response->body->UploadId;
                 pb_backupbuddy::status('details', 'S3 initiated multipart upload with ID `' . $upload_id . '`.');
             }
             // Get chunk parts for multipart transfer.
             pb_backupbuddy::status('details', 'S3 getting multipart counts.');
             $parts = $s3->get_multipart_counts($file_size, $max_chunk_size * 1024 * 1024);
             // Size of chunks expected to be in bytes.
             $multipart_destination_settings = $settings;
             $multipart_destination_settings['_multipart_id'] = $upload_id;
             $multipart_destination_settings['_multipart_partnumber'] = 0;
             $multipart_destination_settings['_multipart_file'] = $file;
             $multipart_destination_settings['_multipart_remotefile'] = $remote_path . basename($file);
             $multipart_destination_settings['_multipart_counts'] = $parts;
             pb_backupbuddy::status('details', 'S3 multipart settings to pass:'******'details', 'S3 scheduling send of next part(s).');
             $cronTime = time();
             $cronArgs = array($multipart_destination_settings, $files, $send_id, $delete_after);
             $cronHashID = md5($cronTime . serialize($cronArgs));
             $cronArgs[] = $cronHashID;
             backupbuddy_core::schedule_single_event($cronTime, pb_backupbuddy::cron_tag('destination_send'), $cronArgs);
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             pb_backupbuddy::status('details', 'S3 scheduled send of next part(s). Done for this cycle.');
             return array($upload_id, 'Starting send of ' . count($multipart_destination_settings['_multipart_counts']) . ' parts.');
         } else {
             // did not meet chunking criteria.
             if ($max_chunk_size != '0') {
                 if ($file_size / 1024 / 1024 > self::MINIMUM_CHUNK_SIZE) {
                     pb_backupbuddy::status('details', 'File size of ' . pb_backupbuddy::$format->file_size($file_size) . ' is less than the max chunk size of ' . $max_chunk_size . 'MB; not chunking into multipart upload.');
                 } else {
                     pb_backupbuddy::status('details', 'File size of ' . pb_backupbuddy::$format->file_size($file_size) . ' is less than the minimum allowed chunk size of ' . self::MINIMUM_CHUNK_SIZE . 'MB; not chunking into multipart upload.');
                 }
             } else {
                 pb_backupbuddy::status('details', 'Max chunk size set to zero so not chunking into multipart upload.');
             }
         }
         // SEND file.
         if ('standard' == $settings['storage']) {
             $storageVal = AmazonS3::STORAGE_STANDARD;
         } elseif ('reduced' == $settings['storage']) {
             $storageVal = AmazonS3::STORAGE_REDUCED;
         } else {
             pb_backupbuddy::status('error', 'Error #854784: Unknown S3 storage type: `' . $settings['storage'] . '`.');
         }
         pb_backupbuddy::status('details', 'About to put (upload) object to S3: `' . $remote_path . $backup_type_dir . basename($file) . '`. Storage type: `' . $settings['storage'] . ' (' . $storageVal . ')`.');
         $response = $s3->create_object($settings['bucket'], $remote_path . $backup_type_dir . basename($file), array('fileUpload' => $file, 'encryption' => 'AES256', 'storage' => $storageVal));
         unset($storageVal);
         // Validate response. On failure notify S3 API that things went wrong.
         if (!$response->isOK()) {
             // Send FAILED.
             $this_error = 'Failure uploading file to S3 storage. Failure details: `' . print_r($response, true) . '`';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         } else {
             // Send SUCCESS.
             pb_backupbuddy::status('details', 'Success uploading file to S3 storage. Upload details: `' . print_r($response, true) . '`.');
             $uploaded_size = $response->header['_info']['size_upload'];
             $uploaded_speed = $response->header['_info']['speed_upload'];
             pb_backupbuddy::status('details', 'Uploaded size: ' . pb_backupbuddy::$format->file_size($uploaded_size) . ', Speed: ' . pb_backupbuddy::$format->file_size($uploaded_speed) . '/sec.');
         }
         unset($files[$file_id]);
         // Remove from list of files we have not sent yet.
         pb_backupbuddy::status('details', 'S3 success sending file `' . basename($file) . '`. File uploaded and reported to S3 as completed.');
         // Load destination fileoptions.
         pb_backupbuddy::status('details', 'About to load fileoptions data.');
         require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
         pb_backupbuddy::status('details', 'Fileoptions instance #8.');
         $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
         if (true !== ($result = $fileoptions_obj->is_ok())) {
             pb_backupbuddy::status('error', __('Fatal Error #9034.84838. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = '#9034.84838';
             return false;
         }
         pb_backupbuddy::status('details', 'Fileoptions data loaded.');
         $fileoptions =& $fileoptions_obj->options;
         // Save stats.
         if (isset($uploaded_speed)) {
             $fileoptions['write_speed'] = $uploaded_speed;
             $fileoptions_obj->save();
         }
         unset($fileoptions_obj);
     }
     // end foreach.
     // BEGIN backup limits.
     if ($limit > 0) {
         pb_backupbuddy::status('details', 'S3 archive limit enforcement to `' . $limit . '` archives beginning.');
         // S3 object for managing files.
         $s3_manage = new AmazonS3($manage_data);
         if ($disable_ssl === true) {
             @$s3_manage->disable_ssl(true);
         }
         if (false === self::_prepareBucketAndRegion($s3_manage, $settings)) {
             global $pb_backupbuddy_destination_errors;
             $pb_backupbuddy_destination_errors[] = 'Could not prepare bucket.';
             return false;
         }
         // Get file listing.
         $response_manage = $s3_manage->list_objects($manage_data['bucket'], array('prefix' => $remote_path . $backup_type_dir));
         // list all the files in the subscriber account
         // Create array of backups and organize by date
         $prefix = backupbuddy_core::backup_prefix();
         // List backups associated with this site by date.
         $backups = array();
         foreach ($response_manage->body->Contents as $object) {
             $file = str_replace($remote_path . $backup_type_dir, '', $object->Key);
             if (FALSE !== stristr($file, '/')) {
                 // CRITICAL CODE! Subdir found due to slash. Do NOT display any files within a deeper subdirectory. Without this files could be deleted not belonging to this destination!
                 continue;
             }
             if (!preg_match(self::BACKUP_FILENAME_PATTERN, $file)) {
                 // CRITICAL CODE! Safety against accidental deletion of non-BB files. Do NOT delete files that do not look like a BackupBuddy backup filename.
                 continue;
             }
             if (FALSE === strpos($file, 'backup-' . $prefix . '-')) {
                 // Not a backup for THIS site. Skip interacting with for limits.
                 continue;
             }
             // S3 stores files in a directory per site so no need to check prefix here! if ( false !== strpos( $file, 'backup-' . $prefix . '-' ) ) { // if backup has this site prefix...
             $backups[$file] = strtotime($object->LastModified);
         }
         arsort($backups);
         pb_backupbuddy::status('details', 'S3 found `' . count($backups) . '` backups when checking archive limits.');
         if (count($backups) > $limit) {
             pb_backupbuddy::status('details', 'More archives (' . count($backups) . ') than limit (' . $limit . ') allows. Trimming...');
             $i = 0;
             $delete_fail_count = 0;
             foreach ($backups as $buname => $butime) {
                 $i++;
                 if ($i > $limit) {
                     pb_backupbuddy::status('details', 'Trimming excess file `' . $buname . '`...');
                     $response = $s3_manage->delete_object($manage_data['bucket'], $remote_path . $backup_type_dir . $buname);
                     if (!$response->isOK()) {
                         pb_backupbuddy::status('details', 'Unable to delete excess S3 file `' . $buname . '`. Details: `' . print_r($response, true) . '`.');
                         $delete_fail_count++;
                     }
                 }
             }
             pb_backupbuddy::status('details', 'Finished trimming excess backups.');
             if ($delete_fail_count !== 0) {
                 $error_message = 'S3 remote limit could not delete ' . $delete_fail_count . ' backups.';
                 pb_backupbuddy::status('error', $error_message);
                 backupbuddy_core::mail_error($error_message);
             }
         }
         pb_backupbuddy::status('details', 'S3 completed archive limiting.');
     } else {
         pb_backupbuddy::status('details', 'No S3 archive file limit to enforce.');
     }
     // End remote backup limit
     // END backup limits.
     if (isset($fileoptions_obj)) {
         unset($fileoptions_obj);
     }
     // Success if we made it this far.
     return true;
 }
Пример #27
0
if ('' != pb_backupbuddy::_GET('downloadlink_file')) {
    $fileMeta = pb_backupbuddy_destination_gdrive::getFileMeta($settings, pb_backupbuddy::_GET('downloadlink_file'));
    pb_backupbuddy::alert('<a href="' . $fileMeta->alternateLink . '" target="_new">Click here</a> to view & download this file from Google Drive. You must log in to Google to access it.');
}
// Copy file to local
if ('' != pb_backupbuddy::_GET('cpy_file')) {
    $destinationFile = $fileMeta = pb_backupbuddy_destination_gdrive::getFileMeta($settings, pb_backupbuddy::_GET('cpy_file'));
    /*
    echo '<pre>';
    print_r( $fileMeta );
    echo '</pre>';
    */
    pb_backupbuddy::alert('The remote file is now being copied to your local backups. If the backup gets marked as bad during copying, please wait a bit then click the `Refresh` icon to rescan after the transfer is complete.');
    echo '<br>';
    pb_backupbuddy::status('details', 'Scheduling Cron for creating Google Drive copy.');
    backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('process_destination_copy'), array($destination, $fileMeta->originalFilename, pb_backupbuddy::_GET('cpy_file')));
    spawn_cron(time() + 150);
    // Adds > 60 seconds to get around once per minute cron running limit.
    update_option('_transient_doing_cron', 0);
    // Prevent cron-blocking for next item.
}
?>


<span id="backupbuddy_gdrive_loading"><h3><img src="<?php 
echo pb_backupbuddy::plugin_url();
?>
/images/loading.gif" alt="' . __('Loading...', 'it-l10n-backupbuddy' ) . '" title="' . __('Loading...', 'it-l10n-backupbuddy' ) . '" width="16" height="16" style="vertical-align: -3px;"> <?php 
_e('Loading...', 'it-l10n-backupbuddy');
?>
</h3></span>
Пример #28
0
 function cron_next_step($spawn_cron = true, $future_offset = 0)
 {
     pb_backupbuddy::status('details', 'Scheduling Cron for `' . $this->_backup['serial'] . '`.');
     // Need to make sure the database connection is active. Sometimes it goes away during long bouts doing other things -- sigh.
     // This is not essential so use include and not require (suppress any warning)
     pb_backupbuddy::status('details', 'Loading DB kicker in case database has gone away.');
     @(include_once pb_backupbuddy::plugin_path() . '/lib/wpdbutils/wpdbutils.php');
     if (class_exists('pluginbuddy_wpdbutils')) {
         // This is the database object we want to use
         global $wpdb;
         // Get our helper object and let it use us to output status messages
         $dbhelper = new pluginbuddy_wpdbutils($wpdb);
         // If we cannot kick the database into life then signal the error and return false which will stop the backup
         // Otherwise all is ok and we can just fall through and let the function return true
         if (!$dbhelper->kick()) {
             pb_backupbuddy::status('error', __('Database Server has gone away, unable to schedule next backup step. The backup cannot continue. This is most often caused by mysql running out of memory or timing out far too early. Please contact your host.', 'it-l10n-backupbuddy'));
             pb_backupbuddy::status('action', 'halt_script');
             // Halt JS on page.
             return false;
         } else {
             pb_backupbuddy::status('details', 'Database seems to still be connected.');
         }
     } else {
         // Utils not available so cannot verify database connection status - just notify
         pb_backupbuddy::status('details', __('Database Server connection status unverified.', 'it-l10n-backupbuddy'));
     }
     // Schedule event.
     $cron_time = time() + $future_offset;
     $cron_tag = pb_backupbuddy::cron_tag('process_backup');
     $cron_args = array($this->_backup['serial']);
     pb_backupbuddy::status('details', 'Scheduling next step to run at `' . $cron_time . '` (localized time: ' . pb_backupbuddy::$format->date(pb_backupbuddy::$format->localize_time($cron_time)) . ') with cron tag `' . $cron_tag . '` and serial arguments `' . implode(',', $cron_args) . '`.');
     $schedule_result = backupbuddy_core::schedule_single_event($cron_time, $cron_tag, $cron_args);
     if ($schedule_result === false) {
         pb_backupbuddy::status('error', 'Unable to schedule next cron step. Verify that another plugin is not preventing / conflicting.');
     } else {
         pb_backupbuddy::status('details', 'Next step scheduled.');
     }
     // Spawn cron.
     if ($spawn_cron === true) {
         spawn_cron(time() + 150);
         // Adds > 60 seconds to get around once per minute cron running limit.
     }
     update_option('_transient_doing_cron', 0);
     // Prevent cron-blocking for next item.
     pb_backupbuddy::status('details', 'About to run next step. If the backup stalls at this point then something is interfering with the WordPress CRON system such as a caching or scheduling plugin. Try disabling other plugins to see if it resolves issue.  Check the Server Information page cron section to see if the next BackupBuddy step is scheduled to run. Enable "Classic" backup mode on the "Settings" page to rule out non-cron issues.');
     return;
 }
Пример #29
0
 public static function send($settings = array(), $files = array(), $send_id = '', $clear_uploads = false)
 {
     global $pb_backupbuddy_destination_errors;
     if (!is_array($files)) {
         $files = array($files);
     }
     if ($clear_uploads === false) {
         // Uncomment the following line to override and always clear.
         //$clear_uploads = true;
     }
     $itxapi_username = $settings['itxapi_username'];
     $itxapi_password = $settings['itxapi_password'];
     $db_archive_limit = $settings['db_archive_limit'];
     $full_archive_limit = $settings['full_archive_limit'];
     $files_archive_limit = $settings['files_archive_limit'];
     $max_chunk_size = $settings['max_chunk_size'];
     $remote_path = self::get_remote_path($settings['directory']);
     // Has leading and trailng slashes.
     if ($settings['ssl'] == '0') {
         $disable_ssl = true;
     } else {
         $disable_ssl = false;
     }
     $multipart_id = $settings['_multipart_id'];
     $multipart_counts = $settings['_multipart_counts'];
     pb_backupbuddy::status('details', 'Stash remote path set to `' . $remote_path . '`.');
     require_once dirname(__FILE__) . '/lib/class.itx_helper.php';
     require_once dirname(dirname(__FILE__)) . '/_s3lib/aws-sdk/sdk.class.php';
     // Stash API talk.
     $stash = new ITXAPI_Helper(pb_backupbuddy_destination_stash::ITXAPI_KEY, pb_backupbuddy_destination_stash::ITXAPI_URL, $itxapi_username, $itxapi_password);
     $manage_data = pb_backupbuddy_destination_stash::get_manage_data($settings);
     if (!is_array($manage_data['credentials'])) {
         pb_backupbuddy::status('error', 'Error #8484383b: Your authentication credentials for Stash failed. Verify your login and password to Stash. You may need to update the Stash destination settings. Perhaps you recently changed your password?');
         return false;
     }
     // Wipe all current uploads.
     if ($clear_uploads === true) {
         pb_backupbuddy::status('details', 'Clearing any current uploads via Stash call to `abort-all`.');
         $abort_url = $stash->get_upload_url(null, 'abort-all');
         $request = new RequestCore($abort_url);
         $response = $request->send_request(true);
     }
     // Process multipart transfer that we already initiated in a previous PHP load.
     if ($multipart_id != '') {
         // Multipart upload initiated and needs parts sent.
         // Create S3 instance.
         pb_backupbuddy::status('details', 'Creating Stash S3 instance.');
         $s3 = new AmazonS3($settings['_multipart_upload_data']['credentials']);
         // the key, secret, token
         if ($disable_ssl === true) {
             @$s3->disable_ssl(true);
         }
         pb_backupbuddy::status('details', 'Stash S3 instance created.');
         $backup_type = str_replace('/', '', $settings['_multipart_backup_type_dir']);
         // For use later by file limiting.
         $this_part_number = $settings['_multipart_partnumber'] + 1;
         pb_backupbuddy::status('details', 'Stash beginning upload of part `' . $this_part_number . '` of `' . count($settings['_multipart_counts']) . '` parts of file `' . $settings['_multipart_file'] . '` with multipart ID `' . $settings['_multipart_id'] . '`.');
         $response = $s3->upload_part($settings['_multipart_upload_data']['bucket'], $settings['_multipart_upload_data']['object'], $settings['_multipart_id'], array('expect' => '100-continue', 'fileUpload' => $settings['_multipart_file'], 'partNumber' => $this_part_number, 'seekTo' => (int) $settings['_multipart_counts'][$settings['_multipart_partnumber']]['seekTo'], 'length' => (int) $settings['_multipart_counts'][$settings['_multipart_partnumber']]['length']));
         if (!$response->isOK()) {
             $this_error = 'Stash unable to upload file part for multipart upload `' . $settings['_multipart_id'] . '`. Details: `' . print_r($response, true) . '`.';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         } else {
             $uploaded_size = $response->header['_info']['size_upload'];
             $uploaded_speed = $response->header['_info']['speed_upload'];
             pb_backupbuddy::status('details', 'Uploaded size: ' . pb_backupbuddy::$format->file_size($uploaded_size) . ', Speed: ' . pb_backupbuddy::$format->file_size($uploaded_speed) . '/sec.');
         }
         // Load fileoptions to the send.
         pb_backupbuddy::status('details', 'About to load fileoptions data.');
         require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
         $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
         if (true !== ($result = $fileoptions_obj->is_ok())) {
             pb_backupbuddy::status('error', __('Fatal Error #9034.2344848. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
             return false;
         }
         pb_backupbuddy::status('details', 'Fileoptions data loaded.');
         $fileoptions =& $fileoptions_obj->options;
         $update_status = 'Sent part ' . $this_part_number . ' of ' . count($settings['_multipart_counts']) . '.';
         // Made it here so success sending part. Increment for next part to send.
         $settings['_multipart_partnumber']++;
         if (!isset($settings['_multipart_counts'][$settings['_multipart_partnumber']])) {
             // No more parts exist for this file. Tell S3 the multipart upload is complete and move on.
             pb_backupbuddy::status('details', 'Stash getting parts with etags to notify S3 of completed multipart send.');
             $etag_parts = $s3->list_parts($settings['_multipart_upload_data']['bucket'], $settings['_multipart_upload_data']['object'], $settings['_multipart_id']);
             pb_backupbuddy::status('details', 'Stash got parts list. Notifying S3 of multipart upload completion.');
             $response = $s3->complete_multipart_upload($settings['_multipart_upload_data']['bucket'], $settings['_multipart_upload_data']['object'], $settings['_multipart_id'], $etag_parts);
             if (!$response->isOK()) {
                 $this_error = 'Stash unable to notify S3 of completion of all parts for multipart upload `' . $settings['_multipart_id'] . '`.';
                 $pb_backupbuddy_destination_errors[] = $this_error;
                 pb_backupbuddy::status('error', $this_error);
                 return false;
             } else {
                 pb_backupbuddy::status('details', 'Stash notified S3 of multipart completion.');
             }
             $backup_type_dir = $settings['_multipart_backup_type_dir'];
             // Notify Stash API that things were succesful.
             $done_url = $stash->get_upload_url($settings['_multipart_file'], 'done', $remote_path . $backup_type_dir . basename($settings['_multipart_file']));
             pb_backupbuddy::status('details', 'Notifying Stash of completed multipart upload with done url `' . $done_url . '`.');
             $request = new RequestCore($done_url);
             $response = $request->send_request(true);
             if (!$response->isOK()) {
                 $this_error = 'Error #756834682. Could not finalize Stash upload. Response code: `' . $response->get_response_code() . '`; Response body: `' . $response->get_response_body() . '`; Response headers: `' . $response->get_response_header() . '`.';
                 $pb_backupbuddy_destination_errors[] = $this_error;
                 pb_backupbuddy::status('error', $this_error);
                 return false;
             } else {
                 // Good server response.
                 // See if we got an optional json response.
                 $upload_data = @json_decode($response->body, true);
                 if (isset($upload_data['error'])) {
                     $this_error = 'Stash error(s): `' . implode(' - ', $upload_data['error']) . '`.';
                     $pb_backupbuddy_destination_errors[] = $this_error;
                     pb_backupbuddy::status('error', $this_error);
                     return false;
                 }
                 pb_backupbuddy::status('details', 'Stash success sending file `' . basename($settings['_multipart_file']) . '`. File uploaded via multipart across `' . $this_part_number . '` parts and reported to Stash as completed.');
             }
             pb_backupbuddy::status('details', 'Stash has no more parts left for this multipart upload. Clearing multipart instance variables.');
             $settings['_multipart_partnumber'] = 0;
             $settings['_multipart_id'] = '';
             $settings['_multipart_file'] = '';
             $settings['_multipart_upload_data'] = array();
             $settings['_multipart_transferspeeds'][] = $uploaded_speed;
             // Overall upload speed average.
             $uploaded_speed = array_sum($settings['_multipart_transferspeeds']) / count($settings['_multipart_counts']);
             pb_backupbuddy::status('details', 'Upload speed average of all chunks: `' . pb_backupbuddy::$format->file_size($uploaded_speed) . '`.');
             $settings['_multipart_counts'] = array();
             // Update stats.
             $fileoptions['_multipart_status'] = $update_status;
             $fileoptions['finish_time'] = time();
             $fileoptions['status'] = 'success';
             if (isset($uploaded_speed)) {
                 $fileoptions['write_speed'] = $uploaded_speed;
             }
             $fileoptions_obj->save();
             unset($fileoptions);
         }
         delete_transient('pb_backupbuddy_stashquota_' . $settings['itxapi_username']);
         // Delete quota transient since it probably has changed now.
         // Schedule to continue if anything is left to upload for this multipart of any individual files.
         if ($settings['_multipart_id'] != '' || count($files) > 0) {
             pb_backupbuddy::status('details', 'Stash multipart upload has more parts left. Scheduling next part send.');
             $schedule_result = backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('destination_send'), array($settings, $files, $send_id));
             if (true === $schedule_result) {
                 pb_backupbuddy::status('details', 'Next Stash chunk step cron event scheduled.');
             } else {
                 pb_backupbuddy::status('error', 'Next Stash chunk step cron even FAILED to be scheduled.');
             }
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             return array($settings['_multipart_id'], 'Sent part ' . $this_part_number . ' of ' . count($settings['_multipart_counts']) . ' parts.');
         }
     }
     // end if multipart continuation.
     require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
     // Upload each file.
     foreach ($files as $file_id => $file) {
         // Determine backup type directory (if zip).
         $backup_type_dir = '';
         $backup_type = '';
         if (stristr($file, '.zip') !== false) {
             // If a zip try to determine backup type.
             pb_backupbuddy::status('details', 'Stash: Zip file. Detecting backup type if possible.');
             $serial = backupbuddy_core::get_serial_from_file($file);
             // See if we can get backup type from fileoptions data.
             $backup_options = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/' . $serial . '.txt', $read_only = true, $ignore_lock = true);
             if (true !== ($result = $backup_options->is_ok())) {
                 pb_backupbuddy::status('error', 'Unable to open fileoptions file `' . backupbuddy_core::getLogDirectory() . 'fileoptions/' . $serial . '.txt' . '`.');
             } else {
                 if (isset($backup_options->options['integrity']['detected_type'])) {
                     pb_backupbuddy::status('details', 'Stash: Detected backup type as `' . $backup_options->options['integrity']['detected_type'] . '` via integrity check data.');
                     $backup_type_dir = $backup_options->options['integrity']['detected_type'] . '/';
                     $backup_type = $backup_options->options['integrity']['detected_type'];
                 }
             }
             // If still do not know backup type then attempt to deduce it from filename.
             if ($backup_type == '') {
                 if (stristr($file, '-db-') !== false) {
                     pb_backupbuddy::status('details', 'Stash: Detected backup type as `db` via filename.');
                     $backup_type_dir = 'db/';
                     $backup_type = 'db';
                 } elseif (stristr($file, '-full-') !== false) {
                     pb_backupbuddy::status('details', 'Stash: Detected backup type as `full` via filename.');
                     $backup_type_dir = 'full/';
                     $backup_type = 'full';
                 } elseif (stristr($file, '-files-') !== false) {
                     pb_backupbuddy::status('details', 'Stash: Detected backup type as `files` via filename.');
                     $backup_type_dir = 'files/';
                     $backup_type = 'files';
                 } else {
                     pb_backupbuddy::status('details', 'Stash: Could not detect backup type via integrity details nor filename.');
                 }
             }
         }
         // Interact with Stash API.
         pb_backupbuddy::status('details', 'Determining Stash upload URL for `' . $file . '`.` with destination remote path `' . $remote_path . $backup_type_dir . basename($file) . '`.');
         $upload_url = $stash->get_upload_url($file, 'request', $remote_path . $backup_type_dir . basename($file));
         pb_backupbuddy::status('details', 'Determined upload url: `' . $upload_url . '`.');
         $request = new RequestCore($upload_url);
         pb_backupbuddy::status('details', 'Sending Stash API request.');
         $response = $request->send_request(true);
         // Validate response.
         if (!$response->isOK()) {
             $this_error = 'Stash request for upload credentials failed.';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         }
         if (!($upload_data = json_decode($response->body, true))) {
             $this_error = 'Stash API did not give a valid JSON response.';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         }
         if (isset($upload_data['error'])) {
             $this_error = 'Stash error(s): `' . implode(' - ', $upload_data['error']) . '`.';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         }
         // Create S3 instance.
         pb_backupbuddy::status('details', 'Creating Stash S3 instance.');
         $s3 = new AmazonS3($upload_data['credentials']);
         // the key, secret, token
         if ($disable_ssl === true) {
             @$s3->disable_ssl(true);
         }
         pb_backupbuddy::status('details', 'Stash S3 instance created.');
         // Handle chunking of file into a multipart upload (if applicable).
         $file_size = filesize($file);
         if ($max_chunk_size >= self::MINIMUM_CHUNK_SIZE && $file_size / 1024 / 1024 > $max_chunk_size) {
             // minimum chunk size is 5mb. Anything under 5mb we will not chunk.
             pb_backupbuddy::status('details', 'Stash file size of ' . pb_backupbuddy::$format->file_size($file_size) . ' exceeds max chunk size of ' . $max_chunk_size . 'MB set in settings for sending file as multipart upload.');
             // Initiate multipart upload with S3.
             pb_backupbuddy::status('details', 'Initiating Stash multipart upload.');
             $response = $s3->initiate_multipart_upload($upload_data['bucket'], $upload_data['object'], array('encryption' => 'AES256'));
             if (!$response->isOK()) {
                 $this_error = 'Stash was unable to initiate multipart upload.';
                 $pb_backupbuddy_destination_errors[] = $this_error;
                 pb_backupbuddy::status('error', $this_error);
                 return false;
             } else {
                 $upload_id = (string) $response->body->UploadId;
                 pb_backupbuddy::status('details', 'Stash initiated multipart upload with ID `' . $upload_id . '`.');
             }
             // Get chunk parts for multipart transfer.
             pb_backupbuddy::status('details', 'Stash getting multipart counts.');
             $parts = $s3->get_multipart_counts($file_size, $max_chunk_size * 1024 * 1024);
             // Size of chunks expected to be in bytes.
             $multipart_destination_settings = $settings;
             $multipart_destination_settings['_multipart_id'] = $upload_id;
             $multipart_destination_settings['_multipart_partnumber'] = 0;
             $multipart_destination_settings['_multipart_file'] = $file;
             $multipart_destination_settings['_multipart_counts'] = $parts;
             $multipart_destination_settings['_multipart_upload_data'] = $upload_data;
             $multipart_destination_settings['_multipart_backup_type_dir'] = $backup_type_dir;
             pb_backupbuddy::status('details', 'Stash multipart settings to pass:'******'details', 'Stash scheduling send of next part(s).');
             backupbuddy_core::schedule_single_event(time(), pb_backupbuddy::cron_tag('destination_send'), array($multipart_destination_settings, $files, $send_id));
             spawn_cron(time() + 150);
             // Adds > 60 seconds to get around once per minute cron running limit.
             update_option('_transient_doing_cron', 0);
             // Prevent cron-blocking for next item.
             pb_backupbuddy::status('details', 'Stash scheduled send of next part(s). Done for this cycle.');
             return array($upload_id, 'Starting send of ' . count($multipart_destination_settings['_multipart_counts']) . ' parts.');
         } else {
             // did not meet chunking criteria.
             if ($max_chunk_size != '0') {
                 if ($file_size / 1024 / 1024 > self::MINIMUM_CHUNK_SIZE) {
                     pb_backupbuddy::status('details', 'File size of ' . pb_backupbuddy::$format->file_size($file_size) . ' is less than the max chunk size of ' . $max_chunk_size . 'MB; not chunking into multipart upload.');
                 } else {
                     pb_backupbuddy::status('details', 'File size of ' . pb_backupbuddy::$format->file_size($file_size) . ' is less than the minimum allowed chunk size of ' . self::MINIMUM_CHUNK_SIZE . 'MB; not chunking into multipart upload.');
                 }
             } else {
                 pb_backupbuddy::status('details', 'Max chunk size set to zero so not chunking into multipart upload.');
             }
         }
         // SEND file.
         pb_backupbuddy::status('details', 'About to put (upload) object to Stash.');
         $response = $s3->create_object($upload_data['bucket'], $upload_data['object'], array('fileUpload' => $file, 'encryption' => 'AES256'));
         // Validate response. On failure notify Stash API that things went wrong.
         if (!$response->isOK()) {
             // Send FAILED.
             pb_backupbuddy::status('details', 'Sending upload abort.');
             $request = new RequestCore($abort_url);
             $response = $request->send_request(true);
             $this_error = 'Could not upload to Stash, attempt aborted.';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         } else {
             // Send SUCCESS.
             pb_backupbuddy::status('details', 'Success uploading file to Stash storage. Notifying Stash API next. Upload details: `' . print_r($response, true) . '`.');
             $uploaded_size = $response->header['_info']['size_upload'];
             $uploaded_speed = $response->header['_info']['speed_upload'];
             pb_backupbuddy::status('details', 'Uploaded size: ' . pb_backupbuddy::$format->file_size($uploaded_size) . ', Speed: ' . pb_backupbuddy::$format->file_size($uploaded_speed) . '/sec.');
         }
         delete_transient('pb_backupbuddy_stashquota_' . $settings['itxapi_username']);
         // Delete quota transient since it probably has changed now.
         // Notify Stash API that things were succesful.
         $done_url = $stash->get_upload_url($file, 'done', $remote_path . $backup_type_dir . basename($file));
         pb_backupbuddy::status('details', 'Notifying Stash of completed upload with done url `' . $done_url . '`.');
         $request = new RequestCore($done_url);
         $response = $request->send_request(true);
         if (!$response->isOK()) {
             $this_error = 'Error #247568834682. Could not finalize Stash upload. Response code: `' . $response->get_response_code() . '`; Response body: `' . $response->get_response_body() . '`; Response headers: `' . $response->get_response_header() . '`.';
             $pb_backupbuddy_destination_errors[] = $this_error;
             pb_backupbuddy::status('error', $this_error);
             return false;
         } else {
             // Good server response.
             // See if we got an optional json response.
             $upload_data = @json_decode($response->body, true);
             if (isset($upload_data['error'])) {
                 // Some kind of error.
                 $this_error = 'Stash error(s): `' . implode(' - ', $upload_data['error']) . '`.';
                 $pb_backupbuddy_destination_errors[] = $this_error;
                 pb_backupbuddy::status('error', $this_error);
                 return false;
             }
             unset($files[$file_id]);
             // Remove from list of files we have not sent yet.
             pb_backupbuddy::status('details', 'Stash success sending file `' . basename($file) . '`. File uploaded and reported to Stash as completed.');
             // Load destination fileoptions.
             pb_backupbuddy::status('details', 'About to load fileoptions data.');
             require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
             $fileoptions_obj = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/send-' . $send_id . '.txt', $read_only = false, $ignore_lock = false, $create_file = false);
             if (true !== ($result = $fileoptions_obj->is_ok())) {
                 pb_backupbuddy::status('error', __('Fatal Error #9034.84838. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
                 return false;
             }
             pb_backupbuddy::status('details', 'Fileoptions data loaded.');
             $fileoptions =& $fileoptions_obj->options;
             // Save stats.
             if (isset($uploaded_speed)) {
                 $fileoptions['write_speed'] = $uploaded_speed;
                 $fileoptions_obj->save();
             }
             //$fileoptions['finish_time'] = time();
             //$fileoptions['status'] = 'success';
             unset($fileoptions_obj);
         }
     }
     // end foreach.
     // BEGIN FILE LIMIT PROCESSING. Enforce archive limits if applicable.
     if ($backup_type == 'full') {
         $limit = $full_archive_limit;
         pb_backupbuddy::status('details', 'Stash full backup archive limit of `' . $limit . '` of type `full` based on destination settings.');
     } elseif ($backup_type == 'db') {
         $limit = $db_archive_limit;
         pb_backupbuddy::status('details', 'Stash database backup archive limit of `' . $limit . '` of type `db` based on destination settings.');
     } elseif ($backup_type == 'files') {
         $limit = $db_archive_limit;
         pb_backupbuddy::status('details', 'Stash database backup archive limit of `' . $limit . '` of type `files` based on destination settings.');
     } else {
         $limit = 0;
         pb_backupbuddy::status('warning', 'Warning #54854895. Stash was unable to determine backup type (reported: `' . $backup_type . '`) so archive limits NOT enforced for this backup.');
     }
     if ($limit > 0) {
         pb_backupbuddy::status('details', 'Stash archive limit enforcement beginning.');
         // S3 object for managing files.
         $s3_manage = new AmazonS3($manage_data['credentials']);
         if ($disable_ssl === true) {
             @$s3_manage->disable_ssl(true);
         }
         // Get file listing.
         $response_manage = $s3_manage->list_objects($manage_data['bucket'], array('prefix' => $manage_data['subkey'] . $remote_path . $backup_type_dir));
         // list all the files in the subscriber account
         // Create array of backups and organize by date
         $prefix = backupbuddy_core::backup_prefix();
         // List backups associated with this site by date.
         $backups = array();
         foreach ($response_manage->body->Contents as $object) {
             $file = str_replace($manage_data['subkey'] . $remote_path . $backup_type_dir, '', $object->Key);
             // Stash stores files in a directory per site so no need to check prefix here! if ( false !== strpos( $file, 'backup-' . $prefix . '-' ) ) { // if backup has this site prefix...
             $backups[$file] = strtotime($object->LastModified);
         }
         arsort($backups);
         pb_backupbuddy::status('details', 'Stash found `' . count($backups) . '` backups of this type when checking archive limits.');
         if (count($backups) > $limit) {
             pb_backupbuddy::status('details', 'More archives (' . count($backups) . ') than limit (' . $limit . ') allows. Trimming...');
             $i = 0;
             $delete_fail_count = 0;
             foreach ($backups as $buname => $butime) {
                 $i++;
                 if ($i > $limit) {
                     pb_backupbuddy::status('details', 'Trimming excess file `' . $buname . '`...');
                     $response = $s3_manage->delete_object($manage_data['bucket'], $manage_data['subkey'] . $remote_path . $backup_type_dir . $buname);
                     if (!$response->isOK()) {
                         pb_backupbuddy::status('details', 'Unable to delete excess Stash file `' . $buname . '`. Details: `' . print_r($response, true) . '`.');
                         $delete_fail_count++;
                     }
                 }
             }
             pb_backupbuddy::status('details', 'Finished trimming excess backups.');
             if ($delete_fail_count !== 0) {
                 $error_message = 'Stash remote limit could not delete ' . $delete_fail_count . ' backups.';
                 pb_backupbuddy::status('error', $error_message);
                 backupbuddy_core::mail_error($error_message);
             }
         }
         pb_backupbuddy::status('details', 'Stash completed archive limiting.');
     } else {
         pb_backupbuddy::status('details', 'No Stash archive file limit to enforce.');
     }
     // End remote backup limit
     if (isset($fileoptions_obj)) {
         unset($fileoptions_obj);
     }
     // END FILE LIMIT PROCESSING.
     // Success if we made it this far.
     return true;
 }
Пример #30
0
 public static function _step_run_remote_snapshot()
 {
     if (false === self::_load_state()) {
         return false;
     }
     // If not all files have uploaded, skip snapshot for now.
     if (self::$_state['stats']['files_pending_send'] > 0 || self::$_state['stats']['tables_pending_send'] > 0) {
         pb_backupbuddy::status('details', '`' . self::$_state['stats']['files_pending_send'] . '` files and `' . self::$_state['stats']['tables_pending_send'] . '` database tables are still pending transfer. Waiting for transfers to finish before creating Snapshot.');
         self::$_state['stats']['wait_on_transfers_start'] = microtime(true);
         backupbuddy_live::queue_step($step = 'wait_on_transfers', $args = array(), $skip_run_now = true);
         return true;
     }
     if (0 == self::$_state['stats']['files_total_count'] || 0 == self::$_state['stats']['tables_total_count']) {
         $error = 'Error #3489349834: Made it to the snapshot stage but there are zero files and/or tables. Halting to protect backup integrity. Files: `' . self::$_state['stats']['files_total_count'] . '`. Tables: `' . self::$_state['stats']['tables_total_count'] . '`.';
         backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $error);
         return $error;
     }
     if (false !== self::$_state['stats']['manual_snapshot']) {
         pb_backupbuddy::status('details', 'Manual snapshot requested at `' . pb_backupbuddy::$format->date(pb_backupbuddy::$format->localize_time(self::$_state['stats']['manual_snapshot'])) . '` (' . pb_backupbuddy::$format->time_ago(self::$_state['stats']['manual_snapshot']) . ' ago). Triggering remote snapshot now.');
         $trigger = 'manual';
     } else {
         $trigger = 'automatic';
         $destination_settings = self::get_destination_settings();
         $schedule_times = wp_get_schedules();
         if (!isset($schedule_times[$destination_settings['remote_snapshot_period']])) {
             pb_backupbuddy::status('error', 'Error #383927494: Invalid schedule interval/period `' . $destination_settings['remote_snapshot_period'] . '`. Not found in wp_get_schedules().');
             return false;
         }
         $delay_between_runs = $schedule_times[$destination_settings['remote_snapshot_period']]['interval'];
         $adjusted_delay_between_runs = $delay_between_runs - self::REMOTE_SNAPSHOT_PERIOD_WIGGLE_ROOM;
         $time_since_last_run = microtime(true) - self::$_state['stats']['last_remote_snapshot'];
         pb_backupbuddy::status('details', 'Period between remote snapshots: `' . $destination_settings['remote_snapshot_period'] . '` (`' . $delay_between_runs . '` seconds). Time since last run: `' . $time_since_last_run . '`. Allowed to run `' . self::REMOTE_SNAPSHOT_PERIOD_WIGGLE_ROOM . '` secs early. Adjusted min delay between runs: `' . $adjusted_delay_between_runs . '`.');
         if ($time_since_last_run < $adjusted_delay_between_runs) {
             pb_backupbuddy::status('details', 'Not enough time has passed since last remote snapshot. Skipping this pass.');
             return true;
         }
         // Made it here so trigger remote snapshot.
         pb_backupbuddy::status('details', 'Enough time has passed since last remote snapshot. Triggering remote snapshot now.');
     }
     $response = backupbuddy_live_periodic::_run_remote_snapshot($trigger);
     if (!is_array($response)) {
         $error = 'Error #2397734: Unable to initiate Live snapshot. See log above for details or here: `' . $response . '`.';
         pb_backupbuddy::status('error', $error);
         backupbuddy_core::addNotification('live_error', 'BackupBuddy Stash Live Error', $error);
         return false;
     } else {
         // Either triggered snapshot or one already running.
         if (true === $response['success']) {
             // Triggered new snapshot.
             $snapshot_id = $response['snapshot'];
             backupbuddy_live_periodic::update_last_remote_snapshot_time($snapshot_id);
             pb_backupbuddy::status('details', 'Triggered new remote snapshot with ID `' . $snapshot_id . '`.');
             // TODO: Keeping in place until new tmtrim-settings and passing tmtrim data with snapshot trigger is verified. Deprecating as of 7.0.5.5.
             // Schedule to run trim cleanup.
             $cronArgs = array();
             $schedule_result = backupbuddy_core::schedule_single_event(time() + 60 * 60, 'live_after_snapshot', $cronArgs);
             // 1hr
             if (true === $schedule_result) {
                 pb_backupbuddy::status('details', 'Next Live trim cron event scheduled.');
             } else {
                 pb_backupbuddy::status('error', 'Next Live trim cron event FAILED to be scheduled.');
             }
             if ('1' != pb_backupbuddy::$options['skip_spawn_cron_call']) {
                 pb_backupbuddy::status('details', 'Spawning cron now.');
                 update_option('_transient_doing_cron', 0);
                 // Prevent cron-blocking for next item.
                 spawn_cron(time() + 150);
                 // Adds > 60 seconds to get around once per minute cron running limit.
             }
             return true;
         } elseif (false === $response['success']) {
             // Failed to trigger new snapshot. Most likely one is already in progress.
             if (isset($response['snapshot'])) {
                 pb_backupbuddy::status('details', 'Did NOT trigger a new snapshot. One is already in progress with ID `' . $response['snapshot'] . '`.');
                 return true;
             } else {
                 pb_backupbuddy::status('error', 'Error #2898923: Something went wrong triggering snapshot. Details: `' . print_r($response) . '`.');
                 return false;
             }
         } else {
             pb_backupbuddy::status('error', 'Error #3832792397: Something went wrong triggering snapshot. Details: `' . print_r($response) . '`.');
             return false;
         }
     }
     pb_backupbuddy::status('error', 'Error #8028434. This should never happen. This code should not be reached.');
     return false;
 }