public function calculateArchiveFilename($serial, $type)
 {
     // Prepare some values for setting up the backup data.
     $siteurl_stripped = backupbuddy_core::backup_prefix();
     // Calculate customizable section of archive filename (date vs date+time).
     if (pb_backupbuddy::$options['archive_name_format'] == 'datetime') {
         // "datetime" = Date + time.
         $backupfile_datetime = date(self::ARCHIVE_NAME_FORMAT_DATETIME, pb_backupbuddy::$format->localize_time(time()));
     } else {
         // "date" = date only (the default).
         $backupfile_datetime = date(self::ARCHIVE_NAME_FORMAT_DATE, pb_backupbuddy::$format->localize_time(time()));
     }
     $archiveFile = backupbuddy_core::getBackupDirectory() . 'backup-' . $siteurl_stripped . '-' . $backupfile_datetime . '-' . $type . '-' . $serial . '.zip';
     pb_backupbuddy::status('details', 'Calculated archive file: `' . $archiveFile . '`.');
     return $archiveFile;
 }
Esempio n. 2
0
    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(), '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
// Get list of files.
$backup_list_temp = array();
foreach ($response->body->Contents as $object) {
    $file = str_ireplace($remote_path, '', $object->Key);
    if (FALSE !== stristr($file, '/')) {
        // Do NOT display any files within a deeper subdirectory.
        continue;
    }
    if (!preg_match(pb_backupbuddy_destination_s3::BACKUP_FILENAME_PATTERN, $file) && 'importbuddy.php' !== $file) {
        // Do not display any files that do not appear to be a BackupBuddy backup file (except importbuddy.php).
        continue;
    }
Esempio n. 3
0
 public static function send($settings = array(), $files = array(), $send_id = '')
 {
     $rs_username = $settings['username'];
     $rs_api_key = $settings['api_key'];
     $rs_container = $settings['container'];
     $limit = $settings['archive_limit'];
     $rs_server = $settings['server'];
     require_once dirname(__FILE__) . '/lib/rackspace/cloudfiles.php';
     $auth = new CF_Authentication($rs_username, $rs_api_key, NULL, $rs_server);
     $auth->authenticate();
     $conn = new CF_Connection($auth);
     // Set container
     @$conn->create_container($rs_container);
     // Create container if it does not exist.
     $container = $conn->get_container($rs_container);
     // Get container.
     foreach ($files as $rs_file) {
         pb_backupbuddy::status('details', 'About to create object on Rackspace...');
         // Put file to Rackspace.
         $sendbackup = $container->create_object(basename($rs_file));
         pb_backupbuddy::status('details', 'Object created. About to stream actual file `' . $rs_file . '`...');
         if ($sendbackup->load_from_filename($rs_file)) {
             pb_backupbuddy::status('details', 'Send succeeded.');
             // Start remote backup limit
             if ($limit > 0) {
                 pb_backupbuddy::status('details', 'Archive limit of `' . $limit . '` in settings.');
                 $bkupprefix = backupbuddy_core::backup_prefix();
                 $results = $container->get_objects(0, NULL, 'backup-' . $bkupprefix . '-');
                 // Create array of backups and organize by date
                 $backups = array();
                 foreach ($results as $backup) {
                     $backups[$backup->name] = $backup->last_modified;
                 }
                 arsort($backups);
                 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 (!$container->delete_object($buname)) {
                                 pb_backupbuddy::status('details', 'Unable to delete excess Rackspace file `' . $buname . '`');
                                 $delete_fail_count++;
                             }
                         }
                     }
                     if ($delete_fail_count !== 0) {
                         $error_message = 'Rackspace remote limit could not delete `' . $delete_fail_count . '` backups.';
                         pb_backupbuddy::status('error', $error_message);
                         backupbuddy_core::mail_error($error_message);
                     }
                 }
             } else {
                 pb_backupbuddy::status('details', 'No Rackspace file limit to enforce.');
             }
             // End remote backup limit
             return true;
             // Success.
         } else {
             // Failed.
             $error_message = 'ERROR #9025: Connected to Rackspace but unable to put file. Verify Rackspace settings included Rackspace permissions.' . "\n\n" . 'http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#9025';
             pb_backupbuddy::status('details', $error_message, 'error');
             backupbuddy_core::mail_error(__($error_message, 'it-l10n-backupbuddy'));
             return false;
             // Failed.
         }
     }
     // end foreach.
 }
Esempio n. 4
0
 public static function send($settings = array(), $files = array(), $send_id = '')
 {
     $limit = $settings['archive_limit'];
     $path = $settings['path'];
     if (!file_exists($settings['path'])) {
         pb_backupbuddy::$filesystem->mkdir($settings['path']);
     }
     $total_transfer_time = 0;
     $total_transfer_size = 0;
     foreach ($files as $file) {
         pb_backupbuddy::status('details', 'Starting send to `' . $path . '`.');
         $filesize = filesize($file);
         $total_transfer_size += $filesize;
         $send_time = -microtime(true);
         if (true !== @copy($file, $path . '/' . basename($file))) {
             pb_backupbuddy::status('error', 'Unable to copy file `' . $file . '` of size `' . pb_backupbuddy::$format->file_size($filesize) . '` to local path `' . $path . '`. Please verify the directory exists and permissions permit writing.');
             backupbuddy_core::mail_error($error_message);
             return false;
         } else {
             pb_backupbuddy::status('details', 'Send success.');
         }
         $send_time += microtime(true);
         $total_transfer_time += $send_time;
         // Start remote backup limit
         if ($limit > 0) {
             pb_backupbuddy::status('details', 'Archive limit of `' . $limit . '` in settings.');
             pb_backupbuddy::status('details', 'path: ' . $path . '*.zip');
             $remote_files = glob($path . '/*.zip');
             if (!is_array($remote_files)) {
                 $remote_files = array();
             }
             usort($remote_files, create_function('$a,$b', 'return filemtime($a) - filemtime($b);'));
             pb_backupbuddy::status('details', 'Found `' . count($remote_files) . '` backups.');
             // Create array of backups and organize by date
             $bkupprefix = backupbuddy_core::backup_prefix();
             foreach ($remote_files as $file_key => $remote_file) {
                 if (false === stripos($remote_file, 'backup-' . $bkupprefix . '-')) {
                     pb_backupbuddy::status('details', 'backup-' . $bkupprefix . '-' . 'not in file: ' . $remote_file);
                     unset($backups[$file_key]);
                 }
             }
             arsort($remote_files);
             pb_backupbuddy::status('details', 'Found `' . count($remote_files) . '` backups.');
             if (count($remote_files) > $limit) {
                 pb_backupbuddy::status('details', 'More archives (' . count($remote_files) . ') than limit (' . $limit . ') allows. Trimming...');
                 $i = 0;
                 $delete_fail_count = 0;
                 foreach ($remote_files as $remote_file) {
                     $i++;
                     if ($i > $limit) {
                         pb_backupbuddy::status('details', 'Trimming excess file `' . $remote_file . '`...');
                         if (!unlink($remote_file)) {
                             pb_backupbuddy::status('details', 'Unable to delete excess local file `' . $remote_file . '`.');
                             $delete_fail_count++;
                         }
                     }
                 }
                 pb_backupbuddy::status('details', 'Finished trimming excess backups.');
                 if ($delete_fail_count !== 0) {
                     $error_message = 'Local remote limit could not delete ' . $delete_fail_count . ' backups.';
                     pb_backupbuddy::status('error', $error_message);
                     backupbuddy_core::mail_error($error_message);
                 }
             }
         } else {
             pb_backupbuddy::status('details', 'No local destination file limit to enforce.');
         }
         // End remote backup limit
     }
     // end foreach.
     // 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 #11.');
     $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;
     $fileoptions['write_speed'] = $total_transfer_time / $total_transfer_size;
     return true;
 }
Esempio n. 5
0
File: init.php Progetto: russtx/tac
 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.
 }
Esempio n. 6
0
 public static function calculateArchiveFilename($serial, $type, $profile)
 {
     // Prepare some values for setting up the backup data.
     $siteurl_stripped = backupbuddy_core::backup_prefix();
     // Add profile to filename if set in options and exists
     if (empty(pb_backupbuddy::$options['archive_name_profile']) || empty($profile['title'])) {
         $backupfile_profile = '';
     } else {
         $backupfile_profile = sanitize_file_name(strtolower($profile['title'])) . '-';
         $backupfile_profile = str_replace('/', '_', $backupfile_profile);
         $backupfile_profile = str_replace('\\', '_', $backupfile_profile);
         $backupfile_profile = str_replace('.', '_', $backupfile_profile);
         $backupfile_profile = str_replace(' ', '_', $backupfile_profile);
         $backupfile_profile = str_replace('-', '_', $backupfile_profile);
     }
     // Calculate customizable section of archive filename (date vs date+time).
     if (pb_backupbuddy::$options['archive_name_format'] == 'datetime') {
         // "datetime" = Date + time.
         $backupfile_datetime = date(backupbuddy_constants::ARCHIVE_NAME_FORMAT_DATETIME, pb_backupbuddy::$format->localize_time(time()));
     } elseif (pb_backupbuddy::$options['archive_name_format'] == 'datetime24') {
         // "datetime" = Date + time in 24hr format.
         $backupfile_datetime = date(backupbuddy_constants::ARCHIVE_NAME_FORMAT_DATETIME24, pb_backupbuddy::$format->localize_time(time()));
     } elseif (pb_backupbuddy::$options['archive_name_format'] == 'timestamp') {
         // "datetime" = Date + time in 24hr format.
         $backupfile_datetime = pb_backupbuddy::$format->localize_time(time());
     } else {
         // "date" = date only (the default).
         $backupfile_datetime = date(backupbuddy_constants::ARCHIVE_NAME_FORMAT_DATE, pb_backupbuddy::$format->localize_time(time()));
     }
     $archiveFile = backupbuddy_core::getBackupDirectory() . 'backup-' . $siteurl_stripped . '-' . $backupfile_datetime . '-' . $backupfile_profile . $type . '-' . $serial . '.zip';
     pb_backupbuddy::status('details', 'Calculated archive file: `' . $archiveFile . '`.');
     return $archiveFile;
 }
<?php

backupbuddy_core::verifyAjaxAccess();
// Directory exclusions picker for settings page.
/*	download_archive()
*	
*	Handle allowing download of archive.
*	
*	@param		
*	@return		
*/
if (is_multisite() && !current_user_can('manage_network')) {
    // If a Network and NOT the superadmin must make sure they can only download the specific subsite backups for security purposes.
    // Only allow downloads of their own backups.
    if (!strstr(pb_backupbuddy::_GET('backupbuddy_backup'), backupbuddy_core::backup_prefix())) {
        die('Access Denied. You may only download backups specific to your Multisite Subsite. Only Network Admins may download backups for another subsite in the network.');
    }
}
// Make sure file exists we are trying to get.
if (!file_exists(backupbuddy_core::getBackupDirectory() . pb_backupbuddy::_GET('backupbuddy_backup'))) {
    // Does not exist.
    die('Error #548957857584784332. The requested backup file does not exist. It may have already been deleted.');
}
$abspath = str_replace('\\', '/', ABSPATH);
// Change slashes to handle Windows as we store backup_directory with Linux-style slashes even on Windows.
$backup_dir = str_replace('\\', '/', backupbuddy_core::getBackupDirectory());
// Make sure file to download is in a publicly accessible location (beneath WP web root technically).
if (FALSE === stristr($backup_dir, $abspath)) {
    die('Error #5432532. You cannot download backups stored outside of the WordPress web root. Please use FTP or other means.');
}
// Made it this far so download dir is within this WP install.
Esempio n. 8
0
 public static function send($settings = array(), $files = array(), $send_id = '')
 {
     pb_backupbuddy::status('details', 'FTP class send() function started.');
     if ($settings['active_mode'] == '0') {
         $active_mode = false;
     } else {
         $active_mode = true;
     }
     $server = $settings['address'];
     $username = $settings['username'];
     $password = $settings['password'];
     $path = $settings['path'];
     $ftps = $settings['ftps'];
     $limit = $settings['archive_limit'];
     $active = $settings['active_mode'];
     $port = '21';
     // Default FTP port.
     if (strstr($server, ':')) {
         // Handle custom FTP port.
         $server_params = explode(':', $server);
         $server = $server_params[0];
         $port = $server_params[1];
     }
     // Connect to server.
     if ($ftps == '1') {
         // Connect with FTPs.
         if (function_exists('ftp_ssl_connect')) {
             $conn_id = ftp_ssl_connect($server, $port);
             if ($conn_id === false) {
                 pb_backupbuddy::status('details', 'Unable to connect to FTPS  `' . $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.');
             }
         } else {
             pb_backupbuddy::status('details', 'Your web server doesnt support FTPS in PHP.', 'error');
             return false;
         }
     } else {
         // Connect with FTP (normal).
         if (function_exists('ftp_connect')) {
             $conn_id = ftp_connect($server, $port);
             if ($conn_id === false) {
                 pb_backupbuddy::status('details', 'ERROR: Unable to connect to FTP server `' . $server . '` on port `' . $port . '` (check address and that server can connect to this address via this port).', 'error');
                 return false;
             } else {
                 pb_backupbuddy::status('details', 'Connected to FTP.');
             }
         } else {
             pb_backupbuddy::status('details', 'Your web server doesnt support FTP in PHP.', 'error');
             return false;
         }
     }
     // Log in.
     $login_result = @ftp_login($conn_id, $username, $password);
     if ($login_result === false) {
         backupbuddy_core::mail_error('ERROR #9011 ( http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#9011 ).  FTP/FTPs login failed on scheduled FTP.');
         return false;
     } else {
         pb_backupbuddy::status('details', 'Logged in. Sending backup via FTP/FTPs ...');
     }
     if ($active_mode === true) {
         // do nothing, active is default.
         pb_backupbuddy::status('details', 'Active FTP mode based on settings.');
     } elseif ($active_mode === false) {
         // Turn passive mode on.
         pb_backupbuddy::status('details', 'Passive FTP mode based on settings.');
         ftp_pasv($conn_id, true);
     } else {
         pb_backupbuddy::status('error', 'Unknown FTP active/passive mode: `' . $active_mode . '`.');
     }
     // Create directory if it does not exist.
     @ftp_mkdir($conn_id, $path);
     // Change to directory.
     pb_backupbuddy::status('details', 'Entering FTP directory `' . $path . '`.');
     ftp_chdir($conn_id, $path);
     // Upload files.
     $total_transfer_size = 0;
     $total_transfer_time = 0;
     foreach ($files as $file) {
         if (!file_exists($file)) {
             pb_backupbuddy::status('error', 'Error #859485495. Could not upload local file `' . $file . '` to send to FTP as it does not exist. Verify the file exists, permissions of file, parent directory, and that ownership is correct. You may need suphp installed on the server.');
         }
         if (!is_readable($file)) {
             pb_backupbuddy::status('error', 'Error #8594846548. Could not read local file `' . $file . '` to sendto FTP as it is not readable. Verify permissions of file, parent directory, and that ownership is correct. You may need suphp installed on the server.');
         }
         $filesize = filesize($file);
         $total_transfer_size += $filesize;
         $destination_file = basename($file);
         // Using chdir() so path not needed. $path . '/' . basename( $file );
         pb_backupbuddy::status('details', 'About to put to FTP local file `' . $file . '` of size `' . pb_backupbuddy::$format->file_size($filesize) . '` to remote file `' . $destination_file . '`.');
         $send_time = -microtime(true);
         $upload = ftp_put($conn_id, $destination_file, $file, FTP_BINARY);
         $send_time += microtime(true);
         $total_transfer_time += $send_time;
         if ($upload === false) {
             $error_message = 'ERROR #9012 ( http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#9012 ).  FTP/FTPs file upload failed. Check file permissions & disk quota.';
             pb_backupbuddy::status('error', $error_message);
             backupbuddy_core::mail_error($error_message);
             return false;
         } else {
             pb_backupbuddy::status('details', 'Success completely sending `' . basename($file) . '` to destination.');
             // Start remote backup limit
             if ($limit > 0) {
                 pb_backupbuddy::status('details', 'Getting contents of backup directory.');
                 ftp_chdir($conn_id, $path);
                 $contents = ftp_nlist($conn_id, '');
                 // Create array of backups
                 $bkupprefix = backupbuddy_core::backup_prefix();
                 $backups = array();
                 foreach ($contents as $backup) {
                     // check if file is backup
                     $pos = strpos($backup, 'backup-' . $bkupprefix . '-');
                     if ($pos !== FALSE) {
                         array_push($backups, $backup);
                     }
                 }
                 arsort($backups);
                 // some ftp servers seem to not report in proper order so reversing insufficiently reliable. need to reverse sort by filename. array_reverse( (array)$backups );
                 if (count($backups) > $limit) {
                     $delete_fail_count = 0;
                     $i = 0;
                     foreach ($backups as $backup) {
                         $i++;
                         if ($i > $limit) {
                             if (!ftp_delete($conn_id, $backup)) {
                                 pb_backupbuddy::status('details', 'Unable to delete excess FTP file `' . $backup . '` in path `' . $path . '`.');
                                 $delete_fail_count++;
                             }
                         }
                     }
                     if ($delete_fail_count !== 0) {
                         backupbuddy_core::mail_error(sprintf(__('FTP remote limit could not delete %s backups. Please check and verify file permissions.', 'it-l10n-backupbuddy'), $delete_fail_count));
                     }
                 }
             } else {
                 pb_backupbuddy::status('details', 'No FTP file limit to enforce.');
             }
             // End remote backup limit
         }
     }
     // end $files loop.
     // 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 #13.');
     $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.
     $fileoptions['write_speed'] = $total_transfer_size / $total_transfer_time;
     //$fileoptions['finish_time'] = time();
     //$fileoptions['status'] = 'success';
     $fileoptions_obj->save();
     unset($fileoptions_obj);
     ftp_close($conn_id);
     return true;
 }
Esempio n. 9
0
 public static function send($settings = array(), $files = array(), $send_id = '')
 {
     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);
     }
     $token =& $settings['token'];
     $directory = '/' . ltrim($settings['directory'], '/\\');
     $limit = $settings['archive_limit'];
     // Normalize picky dropbox directory.
     $directory = trim($directory, '\\/');
     pb_backupbuddy::status('details', 'About to load Dropbuddy library...');
     require_once pb_backupbuddy::plugin_path() . '/destinations/dropbox/lib/dropbuddy/dropbuddy.php';
     pb_backupbuddy::status('details', 'Dropbuddy loaded.');
     //pb_backupbuddy::status( 'details', 'Authenticating to dropbox with token: `' . implode( ';', $token ) . '`.' );
     $dropbuddy = new pb_backupbuddy_dropbuddy($token);
     pb_backupbuddy::status('details', 'Dropbuddy object created.');
     if ($dropbuddy->authenticate() !== true) {
         pb_backupbuddy::status('details', 'Dropbox authentication failed in send().');
         return false;
     } else {
         pb_backupbuddy::status('details', 'Authenticated to Dropbox.');
     }
     $memory = pb_backupbuddy_destination_dropbox::memory_guesstimate();
     pb_backupbuddy::status('details', 'Dropbox limitation estimated to be max transfer size of ' . round($memory['hypothesis'], 0) . 'MB based on PHP memory limit of ' . $memory['limit'] . 'MB & current loaded WordPress plugins.');
     pb_backupbuddy::status('details', 'Looping through files to send to Dropbox.');
     foreach ($files as $file) {
         pb_backupbuddy::status('details', 'About to put file `' . basename($file) . '` (' . pb_backupbuddy::$format->file_size(filesize($file)) . ') to Dropbox (v1).');
         try {
             $status = $dropbuddy->put_file($directory . '/' . basename($file), $file);
         } catch (Dropbox_Exception $e) {
             pb_backupbuddy::status('error', 'Dropbox exception caught. Error #8954785: ' . $e->getMessage());
             return false;
         }
         if ($status === true) {
             pb_backupbuddy::status('details', 'SUCCESS sending to Dropbox!');
         } else {
             pb_backupbuddy::status('details', 'Dropbox file send FAILURE. HTTP Status: ' . $status['httpStatus'] . '; Body: ' . $status['body'], 'error');
             return false;
         }
         // Start remote backup limit
         if ($limit > 0) {
             pb_backupbuddy::status('details', 'Dropbox file limit in place. Proceeding with enforcement.');
             $meta_data = $dropbuddy->get_meta_data($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 ('1' == $looping_file['is_dir']) {
                     // Additional safety layer to ignore subdirectory.
                     continue;
                 }
                 // check if file is backup
                 if (strpos($looping_file['path'], 'backup-' . $bkupprefix . '-') !== false) {
                     $backups[$looping_file['path']] = strtotime($looping_file['modified']);
                 }
             }
             arsort($backups);
             if (count($backups) > $limit) {
                 pb_backupbuddy::status('details', 'Dropbox backup file count of `' . count($backups) . '` exceeds limit of `' . $limit . '`.');
                 $i = 0;
                 $delete_fail_count = 0;
                 foreach ($backups as $buname => $butime) {
                     $i++;
                     if ($i > $limit) {
                         if (!$dropbuddy->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++;
                         }
                     }
                 }
                 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.
 }
Esempio n. 10
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;
 }
Esempio n. 11
0
    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') != '') {
    $link = pb_backupbuddy_destination_s32::getFileURL($settings, pb_backupbuddy::_GET('downloadlink_file'));
    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>';
}
// end download link.
// Get list of files for this site.
if ('true' != pb_backupbuddy::_GET('listAll')) {
    $remotePath = $settings['directory'] . 'backup-' . backupbuddy_core::backup_prefix();
} else {
    $remotePath = $settings['directory'];
}
$files = pb_backupbuddy_destination_s32::listFiles($settings, $remotePath);
if (!is_array($files)) {
    die('Error listing files: `' . $files . '`.');
}
$backup_list_temp = array();
foreach ($files as $object) {
    $file = str_ireplace($settings['directory'], '', $object['Key']);
    if (FALSE !== stristr($file, '/')) {
        // Do NOT display any files within a deeper subdirectory.
        continue;
    }
    if (!preg_match(pb_backupbuddy_destination_s32::BACKUP_FILENAME_PATTERN, $file) && 'importbuddy.php' !== $file) {
        if ('0' == $destination['disable_file_management']) {
            $stashDestination = $destination_id;
            break;
        } else {
            pb_backupbuddy::alert('A Stash destination was found but deployment functionality has been disabled for it. It is not available for deployment features.');
        }
    }
}
$deployments = array(array('siteurl' => 'http://destsite.com/', 'destination' => 0, 'importSettings' => array()));
if ('' != pb_backupbuddy::_GET('deploy')) {
    if (!wp_verify_nonce(pb_backupbuddy::_GET('_wpnonce'), 'backupbuddy_deploy_toggle')) {
        die('Access Denied. Invalid NONCE.');
    }
    if ('enable' == pb_backupbuddy::_GET('deploy')) {
        $identifier = pb_backupbuddy::random_string(12);
        $deployFile = backupbuddy_core::getTempDirectory() . 'deploy-' . backupbuddy_core::backup_prefix() . '.dat';
        // . '-' . $identifier .
        $meta = array('siteurl' => site_url(), 'deployEnabled' => time());
        $deployFileContents = json_encode($meta);
        pb_backupbuddy::anti_directory_browsing(backupbuddy_core::getTempDirectory(), $die = false);
        if (false === file_put_contents($deployFile, $deployFileContents)) {
            pb_backupbuddy::alert('Error #848383: Unable to write temporary deployment file `' . $deployFile . '`. Verify permissions on the directory.');
        } else {
            $destinationSettings = pb_backupbuddy::$options['remote_destinations'][$stashDestination];
            $destinationSettings['meta'] = $meta;
            $destinationSettings['forceRootUpload'] = true;
            require_once pb_backupbuddy::plugin_path() . '/destinations/bootstrap.php';
            $send_result = pb_backupbuddy_destinations::send($destinationSettings, array($deployFile), $identifier, $delete_after = true);
            if (true === $send_result) {
                pb_backupbuddy::$options['deployment_allowed'] = '1';
                pb_backupbuddy::save();
Esempio n. 13
0
    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();
} else {
    $remotePath = '';
}
$files = pb_backupbuddy_destination_stash2::listFiles($settings, $remotePath);
if (!is_array($files)) {
    pb_backupbuddy::alert('Error: ' . $files);
    die;
}
$backup_list_temp = array();
foreach ((array) $files as $file) {
    /*
    echo '<br><pre>';
    print_r( $file );
    echo '</pre>';
    */
<?php

backupbuddy_core::verifyAjaxAccess();
require pb_backupbuddy::plugin_path() . '/destinations/live/_troubleshooting.php';
backupbuddy_live_troubleshooting::run();
$output = "**File best viewed with wordwrap OFF**\n\n" . print_r(backupbuddy_live_troubleshooting::get_raw_results(), true);
header('Content-Description: File Transfer');
header('Content-Type: text/plain; name=backupbuddy-live_troubleshooting-' . backupbuddy_core::backup_prefix() . '.txt');
header('Content-Disposition: attachment; filename=backupbuddy-live_troubleshooting-' . backupbuddy_core::backup_prefix() . '.txt');
header('Expires: 0');
header('Content-Length: ' . strlen($output));
pb_backupbuddy::flush();
echo $output;
pb_backupbuddy::flush();
die;
Esempio n. 15
0
 public static function archiveLimit($settings, $backup_type)
 {
     $settings = self::_init($settings);
     pb_backupbuddy::status('error', 'Error #8339832893: TODO archiveLimit().');
     if ($backup_type == 'full') {
         $limit = $settings['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 = $settings['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 = $settings['files_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.
         $files = self::listFiles($settings, $prefix = '');
         if (!is_array($files)) {
             pb_backupbuddy::status('Error #3892383: Unable to list files. Skipping archive limiting.');
             return false;
         }
         $remotePath = 'backup-' . backupbuddy_core::backup_prefix();
         $prefixLen = strlen(backupbuddy_core::backup_prefix());
         // List backups associated with this site by date.
         $backups = array();
         foreach ($files as $file) {
             if ($file['backup_type'] != $backup_type) {
                 continue;
             }
             if (!backupbuddy_core::startsWith(basename($file['filename']), $remotePath)) {
                 // Only show backups for this site unless set to show all.
                 continue;
             }
             $backups[$file['filename']] = $file['uploaded_timestamp'];
         }
         unset($files);
         arsort($backups);
         pb_backupbuddy::status('details', '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 . '`...');
                     $delete_response = self::deleteFile($settings, substr($buname, $prefixLen + 1));
                     if (true !== $delete_response) {
                         self::_error('Unable to delete excess Stash file `' . $buname . '`. Details: `' . $delete_response . '`.');
                         $delete_fail_count++;
                     }
                 }
             }
             // end foreach.
             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
     return true;
 }
Esempio n. 16
0
File: init.php Progetto: russtx/tac
 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;
 }
Esempio n. 17
0
 public function download_archive()
 {
     if (is_multisite() && !current_user_can('manage_network')) {
         // If a Network and NOT the superadmin must make sure they can only download the specific subsite backups for security purposes.
         // Only allow downloads of their own backups.
         if (!strstr(pb_backupbuddy::_GET('backupbuddy_backup'), backupbuddy_core::backup_prefix())) {
             die('Access Denied. You may only download backups specific to your Multisite Subsite. Only Network Admins may download backups for another subsite in the network.');
         }
     }
     // Make sure file exists we are trying to get.
     if (!file_exists(backupbuddy_core::getBackupDirectory() . pb_backupbuddy::_GET('backupbuddy_backup'))) {
         // Does not exist.
         die('Error #548957857584784332. The requested backup file does not exist. It may have already been deleted.');
     }
     $abspath = str_replace('\\', '/', ABSPATH);
     // Change slashes to handle Windows as we store backup_directory with Linux-style slashes even on Windows.
     $backup_dir = str_replace('\\', '/', backupbuddy_core::getBackupDirectory());
     // Make sure file to download is in a publicly accessible location (beneath WP web root technically).
     if (FALSE === stristr($backup_dir, $abspath)) {
         die('Error #5432532. You cannot download backups stored outside of the WordPress web root. Please use FTP or other means.');
     }
     // Made it this far so download dir is within this WP install.
     $sitepath = str_replace($abspath, '', $backup_dir);
     $download_url = rtrim(site_url(), '/\\') . '/' . trim($sitepath, '/\\') . '/' . pb_backupbuddy::_GET('backupbuddy_backup');
     if (pb_backupbuddy::$options['lock_archives_directory'] == '1') {
         // High security mode.
         if (file_exists(backupbuddy_core::getBackupDirectory() . '.htaccess')) {
             $unlink_status = @unlink(backupbuddy_core::getBackupDirectory() . '.htaccess');
             if ($unlink_status === false) {
                 die('Error #844594. Unable to temporarily remove .htaccess security protection on archives directory to allow downloading. Please verify permissions of the BackupBuddy archives directory or manually download via FTP.');
             }
         }
         header('Location: ' . $download_url);
         ob_clean();
         flush();
         sleep(8);
         // Wait 8 seconds before creating security file.
         $htaccess_creation_status = @file_put_contents(backupbuddy_core::getBackupDirectory() . '.htaccess', 'deny from all');
         if ($htaccess_creation_status === false) {
             die('Error #344894545. Security Warning! Unable to create security file (.htaccess) in backups archive directory. This file prevents unauthorized downloading of backups should someone be able to guess the backup location and filenames. This is unlikely but for best security should be in place. Please verify permissions on the backups directory.');
         }
     } else {
         // Normal mode.
         header('Location: ' . $download_url);
     }
     die;
 }
Esempio n. 18
0
 function pre_backup($serial, $profile, $trigger, $pre_backup = array(), $post_backup = array(), $schedule_title = '', $export_plugins = array())
 {
     pb_backupbuddy::status('action', 'start_function^pre_backup^Getting ready to backup');
     $type = $profile['type'];
     // Log some status information.
     pb_backupbuddy::status('details', __('Performing pre-backup procedures.', 'it-l10n-backupbuddy'));
     if ($type == 'full') {
         pb_backupbuddy::status('message', __('Full backup mode.', 'it-l10n-backupbuddy'));
     } elseif ($type == 'db') {
         pb_backupbuddy::status('message', __('Database only backup mode.', 'it-l10n-backupbuddy'));
     } elseif ($type == 'files') {
         pb_backupbuddy::status('message', __('Files only backup mode.', 'it-l10n-backupbuddy'));
         //$profile['skip_database_dump'] = '1';
     } elseif ($type == 'export') {
         pb_backupbuddy::status('message', __('Multisite Site Export mode.', 'it-l10n-backupbuddy'));
     } else {
         pb_backupbuddy::status('error', __('Error #8587383: Unknown backup mode.', 'it-l10n-backupbuddy')) . 'Supplied backup type: `' . htmlentities($type) . '`.';
     }
     if ('1' == pb_backupbuddy::$options['prevent_flush']) {
         pb_backupbuddy::status('details', 'Flushing will be skipped based on advanced settings.');
     } else {
         pb_backupbuddy::status('details', 'Flushing will not be skipped (default).');
     }
     // Schedule daily housekeeping.
     if (false === wp_next_scheduled(pb_backupbuddy::cron_tag('housekeeping'))) {
         // if schedule does not exist...
         backupbuddy_core::schedule_event(time() + 60 * 60 * 2, 'daily', pb_backupbuddy::cron_tag('housekeeping'), array());
         // Add schedule.
     }
     // Verify directories.
     pb_backupbuddy::status('details', 'Verifying directories ...');
     if (false === backupbuddy_core::verify_directories()) {
         pb_backupbuddy::status('error', 'Error #18573. Error verifying directories. See details above. Backup halted.');
         pb_backupbuddy::status('action', 'halt_script');
         // Halt JS on page.
         die;
     } else {
         pb_backupbuddy::status('details', 'Directories verified.');
     }
     // Delete all backup archives if this troubleshooting option is enabled.
     if (pb_backupbuddy::$options['delete_archives_pre_backup'] == '1') {
         pb_backupbuddy::status('message', 'Deleting all existing backups prior to backup as configured on the settings page.');
         $file_list = glob(backupbuddy_core::getBackupDirectory() . 'backup*.zip');
         if (is_array($file_list) && !empty($file_list)) {
             foreach ($file_list as $file) {
                 if (@unlink($file) === true) {
                     pb_backupbuddy::status('details', 'Deleted backup archive `' . basename($file) . '` based on settings to delete all backups.');
                 } else {
                     pb_backupbuddy::status('details', 'Unable to delete backup archive `' . basename($file) . '` based on settings to delete all backups. Verify permissions.');
                 }
             }
         }
     }
     // Generate unique serial ID.
     pb_backupbuddy::status('details', 'Backup serial generated: `' . $serial . '`.');
     pb_backupbuddy::status('details', 'About to load fileoptions data in create mode.');
     require_once pb_backupbuddy::plugin_path() . '/classes/fileoptions.php';
     $this->_backup_options = new pb_backupbuddy_fileoptions(backupbuddy_core::getLogDirectory() . 'fileoptions/' . $serial . '.txt', $read_only = false, $ignore_lock = false, $create_file = true);
     if (true !== ($result = $this->_backup_options->is_ok())) {
         pb_backupbuddy::status('error', __('Fatal Error #9034 A. Unable to access fileoptions data.', 'it-l10n-backupbuddy') . ' Error: ' . $result);
         pb_backupbuddy::status('action', 'halt_script');
         // Halt JS on page.
         return false;
     }
     pb_backupbuddy::status('details', 'Fileoptions data loaded.');
     $this->_backup =& $this->_backup_options->options;
     // Set reference.
     // Cleanup internal stats.
     pb_backupbuddy::status('details', 'Resetting statistics for last backup time and number of edits since last backup.');
     pb_backupbuddy::$options['last_backup_start'] = time();
     // Reset time since last backup.
     pb_backupbuddy::$options['edits_since_last'] = 0;
     // Reset edit stats for notifying user of how many posts/pages edited since last backup happened.
     pb_backupbuddy::$options['last_backup_serial'] = $serial;
     pb_backupbuddy::save();
     // Output active plugins list for debugging...
     $activePlugins = get_option('active_plugins');
     pb_backupbuddy::status('details', 'Active WordPress plugins: `' . implode('; ', $activePlugins) . '`.');
     pb_backupbuddy::status('action', 'start_subfunction^wp_plugins_found^Found ' . count($activePlugins) . ' active WordPress plugins.');
     unset($activePlugins);
     // Prepare some values for setting up the backup data.
     $siteurl_stripped = backupbuddy_core::backup_prefix();
     // Calculate customizable section of archive filename (date vs date+time).
     if (pb_backupbuddy::$options['archive_name_format'] == 'datetime') {
         // "datetime" = Date + time.
         $backupfile_datetime = date(self::ARCHIVE_NAME_FORMAT_DATETIME, pb_backupbuddy::$format->localize_time(time()));
     } else {
         // "date" = date only (the default).
         $backupfile_datetime = date(self::ARCHIVE_NAME_FORMAT_DATE, pb_backupbuddy::$format->localize_time(time()));
     }
     // Compression to bool.
     /*
     if ( $profile['compression'] == '1' ) {
     	$profile['compression'] = true;
     } else {
     	$profile['compression'] = false;
     }
     */
     if (pb_backupbuddy::$options['compression'] == '1') {
         $compression = true;
     } else {
         $compression = false;
     }
     $archiveFile = backupbuddy_core::getBackupDirectory() . 'backup-' . $siteurl_stripped . '-' . $backupfile_datetime . '-' . $type . '-' . $serial . '.zip';
     //$archiveURL = pb_backupbuddy::ajax_url( 'download_archive' ) . '&backupbuddy_backup=' . basename( $archiveFile );
     $archiveURL = '';
     $abspath = str_replace('\\', '/', ABSPATH);
     // Change slashes to handle Windows as we store backup_directory with Linux-style slashes even on Windows.
     $backup_dir = str_replace('\\', '/', backupbuddy_core::getBackupDirectory());
     if (FALSE !== stristr($backup_dir, $abspath)) {
         // Make sure file to download is in a publicly accessible location (beneath WP web root technically).
         $sitepath = str_replace($abspath, '', $backup_dir);
         $archiveURL = rtrim(site_url(), '/\\') . '/' . trim($sitepath, '/\\') . '/' . basename($archiveFile);
     }
     // Set up the backup data.
     $this->_backup = array('data_version' => 0, 'backupbuddy_version' => pb_backupbuddy::settings('version'), 'serial' => $serial, 'init_complete' => false, 'backup_mode' => $profile['backup_mode'], 'type' => $type, 'profile' => $profile, 'start_time' => time(), 'finish_time' => 0, 'updated_time' => time(), 'status' => array(), 'archive_size' => 0, 'schedule_title' => $schedule_title, 'backup_directory' => backupbuddy_core::getBackupDirectory(), 'archive_file' => $archiveFile, 'archive_url' => $archiveURL, 'trigger' => $trigger, 'zip_method_strategy' => pb_backupbuddy::$options['zip_method_strategy'], 'compression' => $compression, 'ignore_zip_warnings' => pb_backupbuddy::$options['ignore_zip_warnings'], 'ignore_zip_symlinks' => pb_backupbuddy::$options['ignore_zip_symlinks'], 'steps' => array(), 'integrity' => array(), 'temp_directory' => '', 'backup_root' => '', 'export_plugins' => array(), 'additional_table_includes' => array(), 'additional_table_excludes' => array(), 'directory_exclusions' => backupbuddy_core::get_directory_exclusions($profile, false, $serial), 'table_sizes' => array(), 'breakout_tables' => array());
     // Warn if excluding key paths.
     $fileExcludes = backupbuddy_core::alert_core_file_excludes($this->_backup['directory_exclusions']);
     foreach ($fileExcludes as $fileExcludeId => $fileExclude) {
         pb_backupbuddy::status('warning', $fileExclude);
     }
     pb_backupbuddy::status('action', 'start_subfunction^file_excludes^Found ' . count($fileExcludes) . ' file or directory exclusions.');
     // Figure out paths.
     if ($this->_backup['type'] == 'full' || $this->_backup['type'] == 'files') {
         $this->_backup['temp_directory'] = ABSPATH . 'wp-content/uploads/backupbuddy_temp/' . $serial . '/';
         $this->_backup['backup_root'] = ABSPATH;
         // ABSPATH contains trailing slash.
     } elseif ($this->_backup['type'] == 'db') {
         $this->_backup['temp_directory'] = ABSPATH . 'wp-content/uploads/backupbuddy_temp/' . $serial . '/';
         $this->_backup['backup_root'] = $this->_backup['temp_directory'];
     } elseif ($this->_backup['type'] == 'export') {
         // WordPress unzips into wordpress subdirectory by default so must include that in path.
         $this->_backup['temp_directory'] = ABSPATH . 'wp-content/uploads/backupbuddy_temp/' . $serial . '/wordpress/wp-content/uploads/backupbuddy_temp/' . $serial . '/';
         // We store temp data for export within the temporary WordPress installation within the temp directory. A bit confusing; sorry about that.
         $this->_backup['backup_root'] = ABSPATH . 'wp-content/uploads/backupbuddy_temp/' . $serial . '/wordpress/';
     } else {
         pb_backupbuddy::status('error', __('Backup FAILED. Unknown backup type.', 'it-l10n-backupbuddy'));
         pb_backupbuddy::status('action', 'halt_script');
         // Halt JS on page.
     }
     // Plugins to export (only for MS exports).
     if (count($export_plugins) > 0) {
         $this->_backup['export_plugins'] = $export_plugins;
     }
     // Calculate additional database table inclusion/exclusion.
     $additional_includes = explode("\n", $profile['mysqldump_additional_includes']);
     array_walk($additional_includes, create_function('&$val', '$val = trim($val);'));
     $this->_backup['additional_table_includes'] = array_unique($additional_includes);
     // removes duplicates.
     $additional_excludes = explode("\n", $profile['mysqldump_additional_excludes']);
     array_walk($additional_excludes, create_function('&$val', '$val = trim($val);'));
     $this->_backup['additional_table_excludes'] = array_unique($additional_excludes);
     // removes duplicates.
     unset($additional_includes);
     unset($additional_excludes);
     /********* Begin setting up steps array. *********/
     if ($type == 'export') {
         pb_backupbuddy::status('details', 'Setting up export-specific steps.');
         $this->_backup['steps'][] = array('function' => 'ms_download_extract_wordpress', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
         $this->_backup['steps'][] = array('function' => 'ms_create_wp_config', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
         $this->_backup['steps'][] = array('function' => 'ms_copy_plugins', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
         $this->_backup['steps'][] = array('function' => 'ms_copy_themes', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
         $this->_backup['steps'][] = array('function' => 'ms_copy_media', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
         $this->_backup['steps'][] = array('function' => 'ms_copy_users_table', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
     }
     if ('1' != $profile['skip_database_dump'] && $profile['type'] != 'files') {
         // Backup database if not skipping AND not a files only backup.
         global $wpdb;
         // Default tables to backup.
         if ($profile['backup_nonwp_tables'] == '1') {
             // Backup all tables.
             $base_dump_mode = 'all';
         } elseif ($profile['backup_nonwp_tables'] == '2') {
             // Backup no tables by default. Relies on listed additional tables.
             $base_dump_mode = 'none';
         } else {
             // Only backup matching prefix.
             $base_dump_mode = 'prefix';
         }
         $additional_tables = $this->_backup['additional_table_includes'];
         if ($type == 'export') {
             global $wpdb;
             array_push($additional_tables, $wpdb->prefix . "users");
             array_push($additional_tables, $wpdb->prefix . "usermeta");
         }
         // Warn if excluding key WP tables.
         $tableExcludes = backupbuddy_core::alert_core_table_excludes($this->_backup['additional_table_excludes']);
         foreach ($tableExcludes as $tableExcludeId => $tableExclude) {
             pb_backupbuddy::status('warning', $tableExclude);
         }
         // Calculate tables to dump based on the provided information. $tables will be an array of tables.
         $tables = $this->_calculate_tables($base_dump_mode, $additional_tables, $this->_backup['additional_table_excludes']);
         pb_backupbuddy::status('action', 'start_subfunction^calculate_tabeles^Found ' . count($tables) . ' tables to backup based on settings.');
         // If calculations show NO database tables should be backed up then change mode to skip database dump.
         if (0 == count($tables)) {
             pb_backupbuddy::status('warning', 'WARNING #857272: No database tables will be backed up based on current settings. This will not be a complete backup. Adjust settings if this is not intended and use with caution. Skipping database dump step.');
             $profile['skip_database_dump'] = '1';
             $this->_backup['profile']['skip_database_dump'] = '1';
         } else {
             // One or more tables set to backup.
             // Obtain tables sizes. Surround each table name by a single quote and implode with commas for SQL query to get sizes.
             $tables_formatted = $tables;
             foreach ($tables_formatted as &$table_formatted) {
                 $table_formatted = "'{$table_formatted}'";
             }
             $tables_formatted = implode(',', $tables_formatted);
             $sql = "SHOW TABLE STATUS WHERE Name IN({$tables_formatted});";
             $rows = $wpdb->get_results($sql, ARRAY_A);
             if (false === $rows) {
                 pb_backupbuddy::alert('Error #85473474: Unable to retrieve table status. Query: `' . $sql . '`.', true);
                 return false;
             }
             foreach ($rows as $row) {
                 $this->_backup['table_sizes'][$row['Name']] = $row['Data_length'] + $row['Index_length'];
             }
             unset($rows);
             unset($tables_formatted);
             // Tables we will try to break out into standalone steps if possible.
             $breakout_tables_defaults = array($wpdb->prefix . 'posts', $wpdb->prefix . 'postmeta');
             // Step through tables we want to break out and figure out which ones were indeed set to be backed up and break them out.
             if (pb_backupbuddy::$options['breakout_tables'] == '0') {
                 // Breaking out DISABLED.
                 pb_backupbuddy::status('details', 'Breaking out tables DISABLED based on settings.');
             } else {
                 // Breaking out ENABLED.
                 pb_backupbuddy::status('details', 'Breaking out tables ENABLED based on settings. Tables to be broken out into individual steps: `' . implode(', ', $breakout_tables_defaults) . '`.');
                 foreach ((array) $breakout_tables_defaults as $breakout_tables_default) {
                     if (in_array($breakout_tables_default, $tables)) {
                         $this->_backup['breakout_tables'][] = $breakout_tables_default;
                         $tables = array_diff($tables, array($breakout_tables_default));
                         // Remove from main table backup list.
                     }
                 }
             }
             unset($breakout_tables_defaults);
             // No longer needed.
             $this->_backup['steps'][] = array('function' => 'backup_create_database_dump', 'args' => array($tables), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
             // Set up backup steps for additional broken out tables.
             foreach ((array) $this->_backup['breakout_tables'] as $breakout_table) {
                 $this->_backup['steps'][] = array('function' => 'backup_create_database_dump', 'args' => array(array($breakout_table)), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
             }
         }
         // end there being tables to backup.
     } else {
         pb_backupbuddy::status('message', __('Skipping database dump based on settings / profile type.', 'it-l10n-backupbuddy') . ' Backup type: `' . $type . '`.');
     }
     $this->_backup['steps'][] = array('function' => 'backup_zip_files', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
     if ($type == 'export') {
         $this->_backup['steps'][] = array('function' => 'ms_cleanup', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
     }
     if ($profile['integrity_check'] == '1') {
         pb_backupbuddy::status('details', __('Integrity check will be performed based on settings for this profile.', 'it-l10n-backupbuddy'));
         $this->_backup['steps'][] = array('function' => 'integrity_check', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
     } else {
         pb_backupbuddy::status('details', __('Skipping integrity check step based on settings for this profile.', 'it-l10n-backupbuddy'));
     }
     $this->_backup['steps'][] = array('function' => 'post_backup', 'args' => array(), 'start_time' => 0, 'finish_time' => 0, 'attempts' => 0);
     // Prepend and append pre backup and post backup steps.
     $this->_backup['steps'] = array_merge($pre_backup, $this->_backup['steps'], $post_backup);
     /********* End setting up steps array. *********/
     // Save what we have so far so that any errors below will end up displayed to user.
     $this->_backup_options->save();
     /********* Begin directory creation and security. *********/
     pb_backupbuddy::anti_directory_browsing($this->_backup['backup_directory']);
     // Prepare temporary directory for holding SQL and data file.
     if (backupbuddy_core::getTempDirectory() == '') {
         pb_backupbuddy::status('error', 'Error #54534344. Temp directory blank. Please deactivate then reactivate plugin to reset.');
         return false;
     }
     if (!file_exists($this->_backup['temp_directory'])) {
         if (pb_backupbuddy::$filesystem->mkdir($this->_backup['temp_directory']) === false) {
             pb_backupbuddy::status('error', 'Error #9002b. Unable to create temporary storage directory (' . $this->_backup['temp_directory'] . ')');
             return false;
         }
     }
     if (!is_writable($this->_backup['temp_directory'])) {
         pb_backupbuddy::status('error', 'Error #9015. Temp data directory is not writable. Check your permissions. (' . $this->_backup['temp_directory'] . ')');
         return false;
     }
     pb_backupbuddy::anti_directory_browsing(ABSPATH . 'wp-content/uploads/backupbuddy_temp/');
     // Prepare temporary directory for holding ZIP file while it is being generated.
     $this->_backup['temporary_zip_directory'] = backupbuddy_core::getBackupDirectory() . 'temp_zip_' . $this->_backup['serial'] . '/';
     if (!file_exists($this->_backup['temporary_zip_directory'])) {
         if (pb_backupbuddy::$filesystem->mkdir($this->_backup['temporary_zip_directory']) === false) {
             pb_backupbuddy::status('details', 'Error #9002c. Unable to create temporary ZIP storage directory (' . $this->_backup['temporary_zip_directory'] . ')');
             return false;
         }
     }
     if (!is_writable($this->_backup['temporary_zip_directory'])) {
         pb_backupbuddy::status('error', 'Error #9015. Temp data directory is not writable. Check your permissions. (' . $this->_backup['temporary_zip_directory'] . ')');
         return false;
     }
     /********* End directory creation and security *********/
     // Generate backup DAT (data) file containing details about the backup.
     if ($this->backup_create_dat_file($trigger) !== true) {
         pb_backupbuddy::status('details', __('Problem creating DAT file.', 'it-l10n-backupbuddy'));
         return false;
     }
     // Generating ImportBuddy file to include in the backup for FULL BACKUPS ONLY currently. Cannot put in DB because it would be in root and be excluded or conflict on extraction.
     if ($type == 'full') {
         if (pb_backupbuddy::$options['include_importbuddy'] == '1') {
             pb_backupbuddy::status('details', 'Generating ImportBuddy tool to include in backup archive: `' . $this->_backup['temp_directory'] . 'importbuddy.php`.');
             backupbuddy_core::importbuddy($this->_backup['temp_directory'] . 'importbuddy.php');
             pb_backupbuddy::status('details', 'ImportBuddy generation complete.');
         } else {
             // dont include importbuddy.
             pb_backupbuddy::status('details', 'ImportBuddy tool inclusion in ZIP backup archive skipped based on settings.');
         }
     }
     // Save all of this.
     $this->_backup['init_complete'] = true;
     // pre_backup() completed.
     $this->_backup_options->save();
     //pb_backupbuddy::save();
     pb_backupbuddy::status('details', __('Finished pre-backup procedures.', 'it-l10n-backupbuddy'));
     pb_backupbuddy::status('action', 'finish_settings');
     pb_backupbuddy::status('action', 'finish_function^pre_backup');
     return true;
 }
Esempio n. 19
0
 public static function send($settings = array(), $files = array(), $send_id = '')
 {
     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', 'FTP class send() function started.');
     self::_init();
     // Connect to server.
     $server = $settings['address'];
     $port = '22';
     // Default sFTP port.
     if (strstr($server, ':')) {
         // Handle custom sFTP port.
         $server_params = explode(':', $server);
         $server = $server_params[0];
         $port = $server_params[1];
     }
     pb_backupbuddy::status('details', 'Connecting to sFTP server...');
     $sftp = new Net_SFTP($server, $port);
     if (!$sftp->login($settings['username'], $settings['password'])) {
         pb_backupbuddy::status('error', 'Connection to sFTP server FAILED.');
         pb_backupbuddy::status('details', 'sFTP log (if available & enabled via full logging mode): `' . $sftp->getSFTPLog() . '`.');
         return false;
     } else {
         pb_backupbuddy::status('details', 'Success connecting to sFTP server.');
     }
     pb_backupbuddy::status('details', 'Attempting to create path (if it does not exist)...');
     if (true === $sftp->mkdir($settings['path'])) {
         // Try to make directory.
         pb_backupbuddy::status('details', 'Directory created.');
     } else {
         pb_backupbuddy::status('details', 'Directory not created.');
     }
     // Change to directory.
     pb_backupbuddy::status('details', 'Attempting to change into directory...');
     if (true === $sftp->chdir($settings['path'])) {
         pb_backupbuddy::status('details', 'Changed into directory `' . $settings['path'] . '`. All uploads will be relative to this.');
     } else {
         pb_backupbuddy::status('error', 'Unable to change into specified path. Verify the path is correct with valid permissions.');
         pb_backupbuddy::status('details', 'sFTP log (if available & enabled via full logging mode): `' . $sftp->getSFTPLog() . '`.');
         return false;
     }
     // Upload files.
     $total_transfer_size = 0;
     $total_transfer_time = 0;
     foreach ($files as $file) {
         if (!file_exists($file)) {
             pb_backupbuddy::status('error', 'Error #859485495. Could not upload local file `' . $file . '` to send to sFTP as it does not exist. Verify the file exists, permissions of file, parent directory, and that ownership is correct. You may need suphp installed on the server.');
         }
         if (!is_readable($file)) {
             pb_backupbuddy::status('error', 'Error #8594846548. Could not read local file `' . $file . '` to send to sFTP as it is not readable. Verify permissions of file, parent directory, and that ownership is correct. You may need suphp installed on the server.');
         }
         $filesize = filesize($file);
         $total_transfer_size += $filesize;
         $destination_file = basename($file);
         pb_backupbuddy::status('details', 'About to put to sFTP local file `' . $file . '` of size `' . pb_backupbuddy::$format->file_size($filesize) . '` to remote file `' . $destination_file . '`.');
         $send_time = -microtime(true);
         $upload = $sftp->put($destination_file, $file, NET_SFTP_LOCAL_FILE);
         $send_time += microtime(true);
         $total_transfer_time += $send_time;
         if ($upload === false) {
             // Failed sending.
             $error_message = 'ERROR #9012b ( http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#9012 ).  sFTP file upload failed. Check file permissions & disk quota.';
             pb_backupbuddy::status('error', $error_message);
             backupbuddy_core::mail_error($error_message);
             pb_backupbuddy::status('details', 'sFTP log (if available & enabled via full logging mode): `' . $sftp->getSFTPLog() . '`.');
             return false;
         } else {
             // Success sending.
             pb_backupbuddy::status('details', 'Success completely sending `' . basename($file) . '` to destination.');
             // Start remote backup limit
             if ($settings['archive_limit'] > 0) {
                 pb_backupbuddy::status('details', 'Archive limit enabled. Getting contents of backup directory.');
                 $contents = $sftp->rawlist($settings['path']);
                 // already in destination directory/path.
                 // Create array of backups
                 $bkupprefix = backupbuddy_core::backup_prefix();
                 $backups = array();
                 foreach ($contents as $filename => $backup) {
                     // check if file is backup
                     $pos = strpos($filename, 'backup-' . $bkupprefix . '-');
                     if ($pos !== FALSE) {
                         $backups[] = array('file' => $filename, 'modified' => $backup['mtime']);
                     }
                 }
                 function backupbuddy_number_sort($a, $b)
                 {
                     return $a['modified'] < $b['modified'];
                 }
                 // Sort by modified using custom sort function above.
                 usort($backups, 'backupbuddy_number_sort');
                 if (count($backups) > $settings['archive_limit']) {
                     pb_backupbuddy::status('details', 'More backups found (' . count($backups) . ') than limit permits (' . $settings['archive_limit'] . ').' . print_r($backups, true));
                     $delete_fail_count = 0;
                     $i = 0;
                     foreach ($backups as $backup) {
                         $i++;
                         if ($i > $settings['archive_limit']) {
                             if (false === $sftp->delete($settings['path'] . '/' . $backup['file'])) {
                                 pb_backupbuddy::status('details', 'Unable to delete excess sFTP file `' . $backup['file'] . '` in path `' . $settings['path'] . '`.');
                                 $delete_fail_count++;
                             } else {
                                 pb_backupbuddy::status('details', 'Deleted excess sFTP file `' . $backup['file'] . '` in path `' . $settings['path'] . '`.');
                             }
                         }
                     }
                     if ($delete_fail_count != 0) {
                         backupbuddy_core::mail_error(sprintf(__('sFTP remote limit could not delete %s backups. Please check and verify file permissions.', 'it-l10n-backupbuddy'), $delete_fail_count));
                         pb_backupbuddy::status('error', 'Unable to delete one or more excess backup archives. File storage limit may be exceeded. Manually clean up backups and check permissions.');
                     } else {
                         pb_backupbuddy::status('details', 'No problems encountered deleting excess backups.');
                     }
                 } else {
                     pb_backupbuddy::status('details', 'Not enough backups found to exceed limit. Skipping limit enforcement.');
                 }
             } else {
                 pb_backupbuddy::status('details', 'No sFTP archive file limit to enforce.');
             }
             // End remote backup limit
         }
     }
     // end $files loop.
     // 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 #6.');
     $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.843498. 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.
     $fileoptions['write_speed'] = $total_transfer_size / $total_transfer_time;
     $fileoptions_obj->save();
     unset($fileoptions_obj);
     return true;
 }
Esempio n. 20
0
 public static function archiveLimit($settings, $backup_type)
 {
     if ($backup_type == 'full') {
         $limit = $settings['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 = $settings['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 = $settings['files_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-' . backupbuddy_core::backup_prefix()));
             // List all users files in this directory that are a backup for this site (limited by prefix).
         } catch (Exception $e) {
             return self::_error('Error #9338292: Unable to list files for archive limiting. Details: `' . $e->getMessage() . '`.');
         }
         if (!is_array($response_manage['Contents'])) {
             $response_manage['Contents'] = array();
         }
         // List backups associated with this site by date.
         $backups = array();
         foreach ($response_manage['Contents'] as $object) {
             $file = str_replace($settings['directory'], '', $object['Key']);
             if ($backup_type != backupbuddy_core::getBackupTypeFromFile($file, $quiet = true)) {
                 continue;
                 // Not of the same backup type.
             }
             $backups[$file] = strtotime($object['LastModified']);
         }
         arsort($backups);
         pb_backupbuddy::status('details', 'Found `' . count($backups) . '` backups of this type when checking archive limits out of `' . count($response_manage['Contents']) . '` total files in this location.');
         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++;
                     }
                 }
             }
             // end foreach.
             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
     return true;
 }
Esempio n. 21
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;
 }
Esempio n. 22
0
 public static function send($settings = array(), $files = array(), $send_id = '')
 {
     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);
     }
     $rs_container = $settings['container'];
     $limit = $settings['archive_limit'];
     if (false === ($conn = self::connect($settings))) {
         return false;
     }
     // Set container
     @$conn->create_container($rs_container);
     // Create container if it does not exist.
     $container = $conn->get_container($rs_container);
     // Get container.
     foreach ($files as $rs_file) {
         pb_backupbuddy::status('details', 'About to create object on Rackspace...');
         // Put file to Rackspace.
         $sendbackup = $container->create_object(basename($rs_file));
         pb_backupbuddy::status('details', 'Object created. About to stream actual file `' . $rs_file . '`...');
         if ($sendbackup->load_from_filename($rs_file)) {
             pb_backupbuddy::status('details', 'Send succeeded.');
             // Start remote backup limit
             if ($limit > 0) {
                 pb_backupbuddy::status('details', 'Archive limit of `' . $limit . '` in settings.');
                 $bkupprefix = backupbuddy_core::backup_prefix();
                 $results = $container->get_objects(0, NULL, 'backup-' . $bkupprefix . '-');
                 // Create array of backups and organize by date
                 $backups = array();
                 foreach ($results as $backup) {
                     $backups[$backup->name] = $backup->last_modified;
                 }
                 arsort($backups);
                 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 (!$container->delete_object($buname)) {
                                 pb_backupbuddy::status('details', 'Unable to delete excess Rackspace file `' . $buname . '`');
                                 $delete_fail_count++;
                             }
                         }
                     }
                     if ($delete_fail_count !== 0) {
                         $error_message = 'Rackspace remote limit could not delete `' . $delete_fail_count . '` backups.';
                         pb_backupbuddy::status('error', $error_message);
                         backupbuddy_core::mail_error($error_message);
                     }
                 }
             } else {
                 pb_backupbuddy::status('details', 'No Rackspace file limit to enforce.');
             }
             // End remote backup limit
             return true;
             // Success.
         } else {
             // Failed.
             $error_message = 'ERROR #9025: Connected to Rackspace but unable to put file. Verify Rackspace settings included Rackspace permissions.' . "\n\n" . 'http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#9025';
             pb_backupbuddy::status('details', $error_message, 'error');
             backupbuddy_core::mail_error(__($error_message, 'it-l10n-backupbuddy'));
             return false;
             // Failed.
         }
     }
     // end foreach.
 }