PluginProbe
UpdraftPlus: WP Backup & Migration Plugin / 1.3.8
UpdraftPlus: WP Backup & Migration Plugin v1.3.8
1.26.7 1.26.6 1.26.5 1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 All 371 releases
updraftplus / methods / s3.php

s3.php in UpdraftPlus: WP Backup & Migration Plugin 1.3.8, at methods/s3.php

248 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class UpdraftPlus_BackupModule_s3 {
4
5 function backup($backup_array) {
6
7 global $updraftplus;
8
9 if (!class_exists('S3')) require_once(UPDRAFTPLUS_DIR.'/includes/S3.php');
10
11 $s3 = new S3(UpdraftPlus_Options::get_updraft_option('updraft_s3_login'), UpdraftPlus_Options::get_updraft_option('updraft_s3_pass'));
12
13 $bucket_name = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_s3_remote_path'));
14 $bucket_path = "";
15 $orig_bucket_name = $bucket_name;
16
17 if (preg_match("#^([^/]+)/(.*)$#",$bucket_name,$bmatches)) {
18 $bucket_name = $bmatches[1];
19 $bucket_path = $bmatches[2]."/";
20 }
21
22 // See if we can detect the region (which implies the bucket exists and is ours), or if not create it
23 if (@$s3->getBucketLocation($bucket_name) || @$s3->putBucket($bucket_name, S3::ACL_PRIVATE)) {
24
25 foreach($backup_array as $file) {
26
27 // We upload in 5Mb chunks to allow more efficient resuming and hence uploading of larger files
28 $fullpath = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_dir')).$file;
29 $chunks = floor(filesize($fullpath) / 5242880)+1;
30 $hash = md5($file);
31
32 $updraftplus->log("S3 upload: $fullpath (chunks: $chunks) -> s3://$bucket_name/$bucket_path$file");
33
34 $filepath = $bucket_path.$file;
35
36 // This is extra code for the 1-chunk case, but less overhead (no bothering with transients)
37 if ($chunks < 2) {
38 if (!$s3->putObjectFile($fullpath, $bucket_name, $filepath)) {
39 $updraftplus->log("S3 regular upload: failed ($fullpath)");
40 $updraftplus->error("S3 Error: Failed to upload $file.");
41 } else {
42 $updraftplus->log("S3 regular upload: success");
43 $updraftplus->uploaded_file($file);
44 }
45 } else {
46
47 // Retrieve the upload ID
48 $uploadId = get_transient("updraft_${hash}_uid");
49 if (empty($uploadId)) {
50 $uploadId = $s3->initiateMultipartUpload($bucket_name, $filepath);
51 if (empty($uploadId)) {
52 $updraftplus->log("S3 upload: failed: could not get uploadId for multipart upload");
53 continue;
54 } else {
55 $updraftplus->log("S3 chunked upload: got multipart ID: $uploadId");
56 set_transient("updraft_${hash}_uid", $uploadId, 3600*3);
57 }
58 } else {
59 $updraftplus->log("S3 chunked upload: retrieved previously obtained multipart ID: $uploadId");
60 }
61
62 $successes = 0;
63 $etags = array();
64 for ($i = 1 ; $i <= $chunks; $i++) {
65 # Shorted to upd here to avoid hitting the 45-character limit
66 $etag = get_transient("upd_${hash}_e$i");
67 if (strlen($etag) > 0) {
68 $updraftplus->log("S3 chunk $i: was already completed (etag: $etag)");
69 $successes++;
70 array_push($etags, $etag);
71 } else {
72 $etag = $s3->uploadPart($bucket_name, $filepath, $uploadId, $fullpath, $i);
73 if (is_string($etag)) {
74 $updraftplus->log("S3 chunk $i: uploaded (etag: $etag)");
75 array_push($etags, $etag);
76 set_transient("upd_${hash}_e$i", $etag, 3600*3);
77 $successes++;
78 } else {
79 $updraftplus->log("S3 chunk $i: upload failed");
80 $updraftplus->error("S3 chunk $i: upload failed");
81 }
82 }
83 }
84 if ($successes >= $chunks) {
85 $updraftplus->log("S3 upload: all chunks uploaded; will now instruct S3 to re-assemble");
86 if ($s3->completeMultipartUpload ($bucket_name, $filepath, $uploadId, $etags)) {
87 $updraftplus->log("S3 upload: re-assembly succeeded");
88 $updraftplus->uploaded_file($file);
89 } else {
90 $updraftplus->log("S3 upload: re-assembly failed");
91 $updraftplus->error("S3 upload: re-assembly failed ($file)");
92 }
93 } else {
94 $updraftplus->log("S3 upload: upload was not completely successful on this run");
95 }
96 }
97 }
98 $updraftplus->prune_retained_backups('s3', $this, array('s3_object' => $s3, 's3_orig_bucket_name' => $orig_bucket_name));
99 } else {
100 $updraftplus->log("S3 Error: Failed to create bucket $bucket_name.");
101 $updraftplus->error("S3 Error: Failed to create bucket $bucket_name. Check your permissions and credentials.");
102 }
103 }
104
105 function delete($file, $s3arr) {
106
107 global $updraftplus;
108
109 $s3 = $s3arr['s3_object'];
110 $orig_bucket_name = $s3arr['s3_orig_bucket_name'];
111
112 if (preg_match("#^([^/]+)/(.*)$#", $orig_bucket_name, $bmatches)) {
113 $s3_bucket=$bmatches[1];
114 $s3_uri = $bmatches[2]."/".$file;
115 } else {
116 $s3_bucket = $orig_bucket_name;
117 $s3_uri = $file;
118 }
119 $updraftplus->log("S3: Delete remote: bucket=$s3_bucket, URI=$s3_uri");
120
121 # Here we brought in the contents of the S3.php function deleteObject in order to get more direct access to any error
122 $rest = new S3Request('DELETE', $s3_bucket, $s3_uri);
123 $rest = $rest->getResponse();
124 if ($rest->error === false && $rest->code !== 204) {
125 $updraftplus->log("S3 Error: Expected HTTP response 204; got: ".$rest->code);
126 //$updraftplus->error("S3 Error: Unexpected HTTP response code ".$rest->code." (expected 204)");
127 } elseif ($rest->error !== false) {
128 $updraftplus->log("S3 Error: ".$rest->error['code'].": ".$rest->error['message']);
129 //$updraftplus->error("S3 delete error: ".$rest->error['code'].": ".$rest->error['message']);
130 }
131
132 }
133
134 function download($file) {
135
136 global $updraftplus;
137 if(!class_exists('S3')) require_once(UPDRAFTPLUS_DIR.'/includes/S3.php');
138
139 $s3 = new S3(UpdraftPlus_Options::get_updraft_option('updraft_s3_login'), UpdraftPlus_Options::get_updraft_option('updraft_s3_pass'));
140 $bucket_name = untrailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_s3_remote_path'));
141 $bucket_path = "";
142
143 if (preg_match("#^([^/]+)/(.*)$#",$bucket_name,$bmatches)) {
144 $bucket_name = $bmatches[1];
145 $bucket_path = $bmatches[2]."/";
146 }
147
148 if (@$s3->getBucketLocation($bucket_name)) {
149 $fullpath = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_dir')).$file;
150 if (!$s3->getObject($bucket_name, $bucket_path.$file, $fullpath)) {
151 $updraftplus->error("S3 Error: Failed to download $file. Check your permissions and credentials.");
152 }
153 } else {
154 $updraftplus->error("S3 Error: Failed to access bucket $bucket_name. Check your permissions and credentials.");
155 }
156
157 }
158
159 function config_print_javascript_onready() {
160 ?>
161 jQuery('#updraft-s3-test').click(function(){
162 var data = {
163 action: 'updraft_ajax',
164 subaction: 'credentials_test',
165 method: 's3',
166 nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>',
167 apikey: jQuery('#updraft_s3_apikey').val(),
168 apisecret: jQuery('#updraft_s3_apisecret').val(),
169 path: jQuery('#updraft_s3_path').val()
170 };
171 jQuery.post(ajaxurl, data, function(response) {
172 alert('Settings test result: ' + response);
173 });
174 });
175 <?php
176 }
177
178 function config_print() {
179
180 ?>
181 <tr class="updraftplusmethod s3">
182 <td></td>
183 <td><img src="https://d36cz9buwru1tt.cloudfront.net/Powered-by-Amazon-Web-Services.jpg" alt="Amazon Web Services"><p><em>Amazon S3 is a great choice, because UpdraftPlus supports chunked uploads - no matter how big your blog is, UpdraftPlus can upload it a little at a time, and not get thwarted by timeouts.</em></p></td>
184 </tr>
185 <tr class="updraftplusmethod s3">
186 <th></th>
187 <td>
188 <p>Get your access key and secret key <a href="http://aws.amazon.com/console/">from your AWS console</a>, then pick a (globally unique - all Amazon S3 users) bucket name (letters and numbers) (and optionally a path) to use for storage. This bucket will be created for you if it does not already exist.</p>
189 </td></tr>
190 <tr class="updraftplusmethod s3">
191 <th>S3 access key:</th>
192 <td><input type="text" autocomplete="off" style="width: 292px" id="updraft_s3_apikey" name="updraft_s3_login" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_s3_login')) ?>" /></td>
193 </tr>
194 <tr class="updraftplusmethod s3">
195 <th>S3 secret key:</th>
196 <td><input type="text" autocomplete="off" style="width: 292px" id="updraft_s3_apisecret" name="updraft_s3_pass" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_s3_pass')); ?>" /></td>
197 </tr>
198 <tr class="updraftplusmethod s3">
199 <th>S3 location:</th>
200 <td>s3://<input type="text" style="width: 292px" name="updraft_s3_remote_path" id="updraft_s3_path" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_s3_remote_path')); ?>" /></td>
201 </tr>
202 <tr class="updraftplusmethod s3">
203 <th></th>
204 <td><p><button id="updraft-s3-test" type="button" class="button-primary" style="font-size:18px !important">Test S3 Settings</button></p></td>
205 </tr>
206 <?php
207 }
208
209 function credentials_test() {
210
211 $key = $_POST['apikey'];
212 $secret = $_POST['apisecret'];
213 $path = $_POST['path'];
214
215 $bucket = (preg_match("#^([^/]+)/(.*)$#", $path, $bmatches)) ? $bmatches[1] : $path;
216
217 if (empty($bucket)) {
218 echo "Failure: No bucket details were given.";
219 return;
220 }
221 if (empty($key)) {
222 echo "Failure: No API key was given.";
223 return;
224 }
225 if (empty($secret)) {
226 echo "Failure: No API secret was given.";
227 return;
228 }
229
230 if (!class_exists('S3')) require_once(UPDRAFTPLUS_DIR.'/includes/S3.php');
231 $s3 = new S3($key, $secret);
232
233 $location = @$s3->getBucketLocation($bucket);
234 if ($location) {
235 echo "Success: this bucket exists (Amazon region: $location) and we have access to it.";
236 } else {
237 $try_to_create = @$s3->putBucket($bucket, S3::ACL_PRIVATE);
238 if ($try_to_create) {
239 echo "Success: We have successfully created this bucket in your S3 account.";
240 } else {
241 echo "Failure: We could not successfully access or create such a bucket. Please check your access credentials, and if those are correct then try another bucket name (as another S3 user may already have taken this name).";
242 }
243 }
244
245 }
246
247 }
248 ?>