function process_s3_copy($s3file, $accesskey, $secretkey, $bucket, $directory, $ssl) { pb_backupbuddy::status('details', 'Copying remote S3 file `' . $s3file . '` down to local.'); pb_backupbuddy::set_greedy_script_limits(); require_once pb_backupbuddy::plugin_path() . '/destinations/s3/lib/s3.php'; $s3 = new pb_backupbuddy_S3($accesskey, $secretkey, $ssl); $destination_file = pb_backupbuddy::$options['backup_directory'] . $s3file; if (file_exists($destination_file)) { $destination_file = str_replace('backup-', 'backup_copy_' . pb_backupbuddy::random_string(5) . '-', $destination_file); } pb_backupbuddy::status('details', 'About to get S3 object...'); $s3->getObject($bucket, $directory . $s3file, $destination_file); pb_backupbuddy::status('details', 'S3 object retrieved.'); }
/** * Get the S3 response * * @return object | false */ public function getResponse() { $query = ''; if (sizeof($this->parameters) > 0) { $query = substr($this->uri, -1) !== '?' ? '?' : '&'; foreach ($this->parameters as $var => $value) { if ($value == null || $value == '') { $query .= $var . '&'; } else { $query .= $var . '=' . rawurlencode($value) . '&'; } } $query = substr($query, 0, -1); $this->uri .= $query; if (array_key_exists('acl', $this->parameters) || array_key_exists('location', $this->parameters) || array_key_exists('torrent', $this->parameters) || array_key_exists('logging', $this->parameters)) { $this->resource .= $query; } } $url = (pb_backupbuddy_S3::$useSSL && extension_loaded('openssl') ? 'https://' : 'http://') . $this->headers['Host'] . $this->uri; //var_dump($this->bucket, $this->uri, $this->resource, $url); // Basic setup $curl = curl_init(); curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php'); if (pb_backupbuddy_S3::$useSSL) { curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // modified to 0 so we wont need ssl cert on our end } curl_setopt($curl, CURLOPT_URL, $url); // Headers $headers = array(); $amz = array(); foreach ($this->amzHeaders as $header => $value) { if (strlen($value) > 0) { $headers[] = $header . ': ' . $value; } } foreach ($this->headers as $header => $value) { if (strlen($value) > 0) { $headers[] = $header . ': ' . $value; } } // Collect AMZ headers for signature foreach ($this->amzHeaders as $header => $value) { if (strlen($value) > 0) { $amz[] = strtolower($header) . ':' . $value; } } // AMZ headers must be sorted if (sizeof($amz) > 0) { sort($amz); $amz = "\n" . implode("\n", $amz); } else { $amz = ''; } // Authorization string (CloudFront stringToSign should only contain a date) $headers[] = 'Authorization: ' . pb_backupbuddy_S3::__getSignature($this->headers['Host'] == 'cloudfront.amazonaws.com' ? $this->headers['Date'] : $this->verb . "\n" . $this->headers['Content-MD5'] . "\n" . $this->headers['Content-Type'] . "\n" . $this->headers['Date'] . $amz . "\n" . $this->resource); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, false); curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback')); curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback')); @curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // sometimes triggers errors. ie if host has safe mode PHP on. // Request types switch ($this->verb) { case 'GET': break; case 'PUT': case 'POST': // POST only used for CloudFront if ($this->fp !== false) { curl_setopt($curl, CURLOPT_PUT, true); curl_setopt($curl, CURLOPT_INFILE, $this->fp); if ($this->size >= 0) { curl_setopt($curl, CURLOPT_INFILESIZE, $this->size); } } elseif ($this->data !== false) { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb); curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data); if ($this->size >= 0) { curl_setopt($curl, CURLOPT_BUFFERSIZE, $this->size); } } else { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb); } break; case 'HEAD': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD'); curl_setopt($curl, CURLOPT_NOBODY, true); break; case 'DELETE': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); break; default: break; } // Execute, grab errors if (curl_exec($curl)) { $this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE); } else { $this->response->error = array('code' => curl_errno($curl), 'message' => curl_error($curl), 'resource' => $this->resource); } @curl_close($curl); // Parse body into XML if ($this->response->error === false && isset($this->response->headers['type']) && $this->response->headers['type'] == 'application/xml' && isset($this->response->body)) { $this->response->body = simplexml_load_string($this->response->body); // Grab S3 errors if (!in_array($this->response->code, array(200, 204)) && isset($this->response->body->Code, $this->response->body->Message)) { $this->response->error = array('code' => (string) $this->response->body->Code, 'message' => (string) $this->response->body->Message); if (isset($this->response->body->Resource)) { $this->response->error['resource'] = (string) $this->response->body->Resource; } unset($this->response->body); } } // Clean up file resources if ($this->fp !== false && is_resource($this->fp)) { fclose($this->fp); } return $this->response; }
function test_s3($accesskey, $secretkey, $bucket, $directory = '', $ssl) { if (empty($accesskey) || empty($secretkey) || empty($bucket)) { return __('Missing one or more required fields.', 'it-l10n-backupbuddy'); } $bucket_requirements = __("Your bucket name must meet certain criteria. It must fulfill the following: \n\n Characters may be lowercase letters, numbers, periods (.), and dashes (-). \n Must start with a number or letter. \n Must be between 3 and 63 characters long. \n Must not be formatted as an IP address (e.g., 192.168.5.4). \n Should be between 3 and 63 characters long. \n Should not end with a dash. \n Cannot contain two, adjacent periods. \n Cannot contain dashes next to periods.", 'it-l10n-backupbuddy'); if (preg_match("/^[a-z0-9][a-z0-9\\-\\.\\_]*(?<!-)\$/i", $bucket) == 0) { // Starts with a-z or 0-9; middle is a-z, 0-9, -, or .; cannot end in a dash. return __('Your bucket failed one or more things in the check: Starts with a-z or 0-9; middle is a-z, 0-9, -, or .; cannot end in a dash.', 'it-l10n-backupbuddy') . ' ' . $bucket_requirements; } if (strlen($bucket) < 3 || strlen($bucket) > 63) { // Must be between 3 and 63 characters long return __('Your bucket must be between 3 and 63 characters long.', 'it-l10n-backupbuddy') . ' ' . $bucket_requirements; } if (strstr($bucket, '.-') !== false || strstr($bucket, '-.') !== false || strstr($bucket, '..') !== false) { // Bucket names cannot contain dashes next to periods (e.g., "my-.bucket.com" and "my.-bucket" are invalid) return __('Your bucket contains a period next to a dash.', 'it-l10n-backupbuddy') . ' ' . $bucket_requirements; } require_once pb_backupbuddy::plugin_path() . '/lib/s3/s3.php'; $s3 = new pb_backupbuddy_S3($accesskey, $secretkey, $ssl); if ($s3->getBucketLocation($bucket) === false) { // Easy way to see if bucket already exists. $s3->putBucket($bucket, pb_backupbuddy_S3::ACL_PRIVATE); } if (!empty($directory)) { $directory = $directory . '/'; } if ($s3->putObject(__('Upload test for BackupBuddy for Amazon S3', 'it-l10n-backupbuddy'), $bucket, $directory . 'backupbuddy.txt', pb_backupbuddy_S3::ACL_PRIVATE)) { // Success... just delete temp test file later... } else { return __('Unable to upload. Verify your keys, bucket name, and account permissions.', 'it-l10n-backupbuddy'); } if (!pb_backupbuddy_S3::deleteObject($bucket, $directory . 'backupbuddy.txt')) { return __('Partial success. Could not delete temp file.', 'it-l10n-backupbuddy'); } return true; // Success! }
/** * Get the S3 response * * @return object | false */ public function getResponse() { $query = ''; if (sizeof($this->parameters) > 0) { $query = substr($this->uri, -1) !== '?' ? '?' : '&'; foreach ($this->parameters as $var => $value) { if ($value == null || $value == '') { $query .= $var . '&'; } else { $query .= $var . '=' . rawurlencode($value) . '&'; } } $query = substr($query, 0, -1); $this->uri .= $query; if (array_key_exists('acl', $this->parameters) || array_key_exists('location', $this->parameters) || array_key_exists('torrent', $this->parameters) || array_key_exists('website', $this->parameters) || array_key_exists('logging', $this->parameters)) { $this->resource .= $query; } } $url = (pb_backupbuddy_S3::$useSSL ? 'https://' : 'http://') . ($this->headers['Host'] !== '' ? $this->headers['Host'] : $this->endpoint) . $this->uri; //var_dump('bucket: ' . $this->bucket, 'uri: ' . $this->uri, 'resource: ' . $this->resource, 'url: ' . $url); // Basic setup $curl = curl_init(); curl_setopt($curl, CURLOPT_USERAGENT, 'S3/php'); if (pb_backupbuddy_S3::$useSSL) { // SSL Validation can now be optional for those with broken OpenSSL installations curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, pb_backupbuddy_S3::$useSSLValidation ? 1 : 0); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, pb_backupbuddy_S3::$useSSLValidation ? 1 : 0); if (pb_backupbuddy_S3::$sslKey !== null) { curl_setopt($curl, CURLOPT_SSLKEY, pb_backupbuddy_S3::$sslKey); } if (pb_backupbuddy_S3::$sslCert !== null) { curl_setopt($curl, CURLOPT_SSLCERT, pb_backupbuddy_S3::$sslCert); } if (pb_backupbuddy_S3::$sslCACert !== null) { curl_setopt($curl, CURLOPT_CAINFO, pb_backupbuddy_S3::$sslCACert); } } curl_setopt($curl, CURLOPT_URL, $url); if (pb_backupbuddy_S3::$proxy != null && isset(pb_backupbuddy_S3::$proxy['host'])) { curl_setopt($curl, CURLOPT_PROXY, pb_backupbuddy_S3::$proxy['host']); curl_setopt($curl, CURLOPT_PROXYTYPE, pb_backupbuddy_S3::$proxy['type']); if (isset(pb_backupbuddy_S3::$proxy['user'], pb_backupbuddy_S3::$proxy['pass']) && pb_backupbuddy_S3::$proxy['user'] != null && pb_backupbuddy_S3::$proxy['pass'] != null) { curl_setopt($curl, CURLOPT_PROXYUSERPWD, sprintf('%s:%s', pb_backupbuddy_S3::$proxy['user'], pb_backupbuddy_S3::$proxy['pass'])); } } // Headers $headers = array(); $amz = array(); foreach ($this->amzHeaders as $header => $value) { if (strlen($value) > 0) { $headers[] = $header . ': ' . $value; } } foreach ($this->headers as $header => $value) { if (strlen($value) > 0) { $headers[] = $header . ': ' . $value; } } // Collect AMZ headers for signature foreach ($this->amzHeaders as $header => $value) { if (strlen($value) > 0) { $amz[] = strtolower($header) . ':' . $value; } } // AMZ headers must be sorted if (sizeof($amz) > 0) { //sort($amz); usort($amz, array(&$this, '__sortMetaHeadersCmp')); $amz = "\n" . implode("\n", $amz); } else { $amz = ''; } if (pb_backupbuddy_S3::hasAuth()) { // Authorization string (CloudFront stringToSign should only contain a date) if ($this->headers['Host'] == 'cloudfront.amazonaws.com') { $headers[] = 'Authorization: ' . pb_backupbuddy_S3::__getSignature($this->headers['Date']); } else { $headers[] = 'Authorization: ' . pb_backupbuddy_S3::__getSignature($this->verb . "\n" . $this->headers['Content-MD5'] . "\n" . $this->headers['Content-Type'] . "\n" . $this->headers['Date'] . $amz . "\n" . $this->resource); } } curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, false); curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback')); curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this, '__responseHeaderCallback')); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); // Request types switch ($this->verb) { case 'GET': break; case 'PUT': case 'POST': // POST only used for CloudFront if ($this->fp !== false) { curl_setopt($curl, CURLOPT_PUT, true); curl_setopt($curl, CURLOPT_INFILE, $this->fp); if ($this->size >= 0) { curl_setopt($curl, CURLOPT_INFILESIZE, $this->size); } } elseif ($this->data !== false) { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb); curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data); } else { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb); } break; case 'HEAD': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'HEAD'); curl_setopt($curl, CURLOPT_NOBODY, true); break; case 'DELETE': curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); break; default: break; } // Execute, grab errors if (curl_exec($curl)) { $this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE); } else { $this->response->error = array('code' => curl_errno($curl), 'message' => curl_error($curl), 'resource' => $this->resource); } @curl_close($curl); // Parse body into XML if ($this->response->error === false && isset($this->response->headers['type']) && $this->response->headers['type'] == 'application/xml' && isset($this->response->body)) { $this->response->body = simplexml_load_string($this->response->body); // Grab S3 errors if (!in_array($this->response->code, array(200, 204, 206)) && isset($this->response->body->Code, $this->response->body->Message)) { $this->response->error = array('code' => (string) $this->response->body->Code, 'message' => (string) $this->response->body->Message); if (isset($this->response->body->Resource)) { $this->response->error['resource'] = (string) $this->response->body->Resource; } unset($this->response->body); } } // Clean up file resources if ($this->fp !== false && is_resource($this->fp)) { fclose($this->fp); } return $this->response; }
pb_backupbuddy::$ui->title('Amazon S3'); // S3 information $aws_accesskey = $destination['accesskey']; $aws_secretkey = $destination['secretkey']; $aws_bucket = $destination['bucket']; $aws_directory = $destination['directory']; if (!empty($aws_directory)) { $aws_directory = $aws_directory . '/'; } if ($destination['ssl'] == '1') { $s3_ssl = true; } else { $s3_ssl = false; } require_once pb_backupbuddy::plugin_path() . '/destinations/s3/lib/s3.php'; $s3 = new pb_backupbuddy_S3($aws_accesskey, $aws_secretkey, $s3_ssl); // Delete S3 backups if (!empty($_POST['delete_file'])) { pb_backupbuddy::verify_nonce(); $delete_count = 0; if (!empty($_POST['files']) && is_array($_POST['files'])) { // loop through and delete s3 files foreach ($_POST['files'] as $s3file) { $delete_count++; // Delete S3 file $s3->deleteObject($aws_bucket, $s3file); } } if ($delete_count > 0) { pb_backupbuddy::alert(sprintf(_n('Deleted %d file.', 'Deleted %d files.', $delete_count, 'it-l10n-backupbuddy'), $delete_count)); }
public static function test($settings) { pb_backupbuddy::status('details', 'Beginning Amazon S3 destination test.'); $accesskey = $settings['accesskey']; $secretkey = $settings['secretkey']; $bucket = $settings['bucket']; $directory = $settings['directory']; $storage_class = $settings['storage_class']; $ssl = $settings['ssl']; // Add trailing slash to end of directory if one defined. if ($directory != '') { $directory = rtrim($directory, '/\\') . '/'; } // Verify all required fields passed. if (empty($accesskey) || empty($secretkey) || empty($bucket)) { return __('Missing one or more required fields.', 'it-l10n-backupbuddy'); } // Verify bucket naming requirements. $bucket_requirements = __("Your bucket name must meet certain criteria. It must fulfill the following: \n\n Characters may be lowercase letters, numbers, periods (.), and dashes (-). \n Must start with a number or letter. \n Must be between 3 and 63 characters long. \n Must not be formatted as an IP address (e.g., 192.168.5.4). \n Should be between 3 and 63 characters long. \n Should not end with a dash. \n Cannot contain two, adjacent periods. \n Cannot contain dashes next to periods.", 'it-l10n-backupbuddy'); if (preg_match("/^[a-z0-9][a-z0-9\\-\\.\\_]*(?<!-)\$/i", $bucket) == 0) { // Starts with a-z or 0-9; middle is a-z, 0-9, -, or .; cannot end in a dash. return __('Your bucket failed one or more things in the check: Starts with a-z or 0-9; middle is a-z, 0-9, -, or .; cannot end in a dash.', 'it-l10n-backupbuddy') . ' ' . $bucket_requirements; } if (strlen($bucket) < 3 || strlen($bucket) > 63) { // Must be between 3 and 63 characters long return __('Your bucket must be between 3 and 63 characters long.', 'it-l10n-backupbuddy') . ' ' . $bucket_requirements; } if (strstr($bucket, '.-') !== false || strstr($bucket, '-.') !== false || strstr($bucket, '..') !== false) { // Bucket names cannot contain dashes next to periods (e.g., "my-.bucket.com" and "my.-bucket" are invalid) return __('Your bucket contains a period next to a dash.', 'it-l10n-backupbuddy') . ' ' . $bucket_requirements; } pb_backupbuddy::status('details', 'Loading S3 library.'); require_once dirname(__FILE__) . '/lib/s3.php'; pb_backupbuddy::status('details', 'Creating S3 object.'); $s3 = new pb_backupbuddy_S3($accesskey, $secretkey, $ssl); // Check if target bucket exists. Create it if not. pb_backupbuddy::status('details', 'Check if bucket already exists.'); if ($s3->getBucketLocation($bucket) === false) { // Easy way to see if bucket already exists. pb_backupbuddy::status('details', 'Bucket does not exist; creating it.'); $s3->putBucket($bucket, pb_backupbuddy_S3::ACL_PRIVATE); } // Send temporary test file. //pb_backupbuddy::status( 'details', 'Using S3 storage class `' . $storage_class . '`.' ); pb_backupbuddy::status('details', 'About to put file to S3.'); if ($s3->putObject(__('Upload test for BackupBuddy for Amazon S3', 'it-l10n-backupbuddy'), $bucket, $directory . 'backupbuddy.txt', pb_backupbuddy_S3::ACL_PRIVATE)) { // Success... just delete temp test file later... pb_backupbuddy::status('details', 'Success uploading test file to S3.'); } else { pb_backupbuddy::status('error', 'Failure uploading test file to S3.'); return __('Unable to upload. Verify your keys, bucket name, and account permissions.', 'it-l10n-backupbuddy'); } // Delete temporary test file. if (!pb_backupbuddy_S3::deleteObject($bucket, $directory . 'backupbuddy.txt')) { pb_backupbuddy::status('details', 'Partial S3 test success. Could not delete temp file.'); return __('Partial success. Could not delete temp file.', 'it-l10n-backupbuddy'); } return true; // Success! }