1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* XCloner - Backup and Restore backup plugin for Wordpress |
4
|
|
|
* |
5
|
|
|
* class-xcloner-remote-storage.php |
6
|
|
|
* @author Liuta Ovidiu <[email protected]> |
7
|
|
|
* |
8
|
|
|
* This program is free software; you can redistribute it and/or modify |
9
|
|
|
* it under the terms of the GNU General Public License as published by |
10
|
|
|
* the Free Software Foundation; either version 2 of the License, or |
11
|
|
|
* (at your option) any later version. |
12
|
|
|
* |
13
|
|
|
* This program is distributed in the hope that it will be useful, |
14
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
15
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16
|
|
|
* GNU General Public License for more details. |
17
|
|
|
* |
18
|
|
|
* You should have received a copy of the GNU General Public License |
19
|
|
|
* along with this program; if not, write to the Free Software |
20
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
21
|
|
|
* MA 02110-1301, USA. |
22
|
|
|
* |
23
|
|
|
* @link https://github.com/ovidiul/XCloner-Wordpress |
24
|
|
|
* |
25
|
|
|
* @modified 7/25/18 2:15 PM |
26
|
|
|
* |
27
|
|
|
*/ |
28
|
|
|
|
29
|
|
|
use League\Flysystem\Config; |
30
|
|
|
use League\Flysystem\Filesystem; |
31
|
|
|
|
32
|
|
|
use League\Flysystem\Adapter\Ftp as Adapter; |
33
|
|
|
|
34
|
|
|
use League\Flysystem\Sftp\SftpAdapter; |
35
|
|
|
|
36
|
|
|
use Srmklive\Dropbox\Client\DropboxClient; |
37
|
|
|
use Srmklive\Dropbox\Adapter\DropboxAdapter; |
38
|
|
|
|
39
|
|
|
use MicrosoftAzure\Storage\Common\ServicesBuilder; |
40
|
|
|
use League\Flysystem\Azure\AzureAdapter; |
41
|
|
|
|
42
|
|
|
use Aws\S3\S3Client; |
43
|
|
|
use League\Flysystem\AwsS3v3\AwsS3Adapter; |
44
|
|
|
|
45
|
|
|
use Mhetreramesh\Flysystem\BackblazeAdapter; |
46
|
|
|
use BackblazeB2\Client as B2Client; |
47
|
|
|
|
48
|
|
|
use Sabre\DAV\Client as SabreClient; |
49
|
|
|
use League\Flysystem\WebDAV\WebDAVAdapter; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Class Xcloner_Remote_Storage |
53
|
|
|
*/ |
54
|
|
|
class Xcloner_Remote_Storage { |
55
|
|
|
|
56
|
|
|
private $gdrive_app_name = "XCloner Backup and Restore"; |
57
|
|
|
|
58
|
|
|
private $storage_fields = array( |
59
|
|
|
"option_prefix" => "xcloner_", |
60
|
|
|
"ftp" => array( |
61
|
|
|
"text" => "FTP", |
62
|
|
|
"ftp_enable" => "int", |
63
|
|
|
"ftp_hostname" => "string", |
64
|
|
|
"ftp_port" => "int", |
65
|
|
|
"ftp_username" => "string", |
66
|
|
|
"ftp_password" => "raw", |
67
|
|
|
"ftp_path" => "path", |
68
|
|
|
"ftp_transfer_mode" => "int", |
69
|
|
|
"ftp_ssl_mode" => "int", |
70
|
|
|
"ftp_timeout" => "int", |
71
|
|
|
"ftp_cleanup_days" => "float", |
72
|
|
|
), |
73
|
|
|
"sftp" => array( |
74
|
|
|
"text" => "SFTP", |
75
|
|
|
"sftp_enable" => "int", |
76
|
|
|
"sftp_hostname" => "string", |
77
|
|
|
"sftp_port" => "int", |
78
|
|
|
"sftp_username" => "string", |
79
|
|
|
"sftp_password" => "raw", |
80
|
|
|
"sftp_path" => "path", |
81
|
|
|
"sftp_private_key" => "raw", |
82
|
|
|
"sftp_timeout" => "int", |
83
|
|
|
"sftp_cleanup_days" => "float", |
84
|
|
|
), |
85
|
|
|
"aws" => array( |
86
|
|
|
"text" => "S3", |
87
|
|
|
"aws_enable" => "int", |
88
|
|
|
"aws_key" => "string", |
89
|
|
|
"aws_secret" => "raw", |
90
|
|
|
"aws_endpoint" => "string", |
91
|
|
|
"aws_region" => "string", |
92
|
|
|
"aws_bucket_name" => "string", |
93
|
|
|
"aws_prefix" => "string", |
94
|
|
|
"aws_cleanup_days" => "float", |
95
|
|
|
), |
96
|
|
|
"dropbox" => array( |
97
|
|
|
"text" => "Dropbox", |
98
|
|
|
"dropbox_enable" => "int", |
99
|
|
|
"dropbox_access_token" => "string", |
100
|
|
|
"dropbox_app_secret" => "raw", |
101
|
|
|
"dropbox_prefix" => "string", |
102
|
|
|
"dropbox_cleanup_days" => "float", |
103
|
|
|
), |
104
|
|
|
"azure" => array( |
105
|
|
|
"text" => "Azure BLOB", |
106
|
|
|
"azure_enable" => "int", |
107
|
|
|
"azure_account_name" => "string", |
108
|
|
|
"azure_api_key" => "string", |
109
|
|
|
"azure_container" => "string", |
110
|
|
|
"azure_cleanup_days" => "float", |
111
|
|
|
), |
112
|
|
|
"backblaze" => array( |
113
|
|
|
"text" => "Backblaze", |
114
|
|
|
"backblaze_enable" => "int", |
115
|
|
|
"backblaze_account_id" => "string", |
116
|
|
|
"backblaze_application_key" => "string", |
117
|
|
|
"backblaze_bucket_name" => "string", |
118
|
|
|
"backblaze_cleanup_days" => "float", |
119
|
|
|
), |
120
|
|
|
|
121
|
|
|
"webdav" => array( |
122
|
|
|
"text" => "WebDAV", |
123
|
|
|
"webdav_enable" => "int", |
124
|
|
|
"webdav_url" => "string", |
125
|
|
|
"webdav_username" => "string", |
126
|
|
|
"webdav_password" => "raw", |
127
|
|
|
"webdav_target_folder" => "string", |
128
|
|
|
"webdav_cleanup_days" => "float", |
129
|
|
|
), |
130
|
|
|
|
131
|
|
|
"gdrive" => array( |
132
|
|
|
"text" => "Google Drive", |
133
|
|
|
"gdrive_enable" => "int", |
134
|
|
|
"gdrive_access_code" => "string", |
135
|
|
|
"gdrive_client_id" => "string", |
136
|
|
|
"gdrive_client_secret" => "raw", |
137
|
|
|
"gdrive_target_folder" => "string", |
138
|
|
|
"gdrive_cleanup_days" => "float", |
139
|
|
|
"gdrive_empty_trash" => "int", |
140
|
|
|
), |
141
|
|
|
); |
142
|
|
|
|
143
|
|
|
private $aws_regions = array( |
144
|
|
|
'us-east-1' => 'US East (N. Virginia)', |
145
|
|
|
'us-east-2' => 'US East (Ohio)', |
146
|
|
|
'us-west-1' => 'US West (N. California)', |
147
|
|
|
'us-west-2' => 'US West (Oregon)', |
148
|
|
|
'ca-central-1' => 'Canada (Central)', |
149
|
|
|
'eu-west-1' => 'EU (Ireland)', |
150
|
|
|
'eu-central-1' => 'EU (Frankfurt)', |
151
|
|
|
'eu-west-2' => 'EU (London)', |
152
|
|
|
'ap-northeast-1' => 'Asia Pacific (Tokyo)', |
153
|
|
|
'ap-northeast-2' => 'Asia Pacific (Seoul)', |
154
|
|
|
'ap-southeast-1' => 'Asia Pacific (Singapore)', |
155
|
|
|
'ap-southeast-2' => 'Asia Pacific (Sydney)', |
156
|
|
|
'ap-south-1' => 'Asia Pacific (Mumbai)', |
157
|
|
|
'sa-east-1' => 'South America (São Paulo)' |
158
|
|
|
); |
159
|
|
|
|
160
|
|
|
private $xcloner_sanitization; |
161
|
|
|
private $xcloner_file_system; |
162
|
|
|
private $logger; |
163
|
|
|
private $xcloner; |
164
|
|
|
|
165
|
|
|
public function __construct( Xcloner $xcloner_container ) { |
166
|
|
|
$this->xcloner_sanitization = $xcloner_container->get_xcloner_sanitization(); |
167
|
|
|
$this->xcloner_file_system = $xcloner_container->get_xcloner_filesystem(); |
168
|
|
|
$this->logger = $xcloner_container->get_xcloner_logger()->withName( "xcloner_remote_storage" ); |
169
|
|
|
$this->xcloner = $xcloner_container; |
170
|
|
|
|
171
|
|
|
foreach($this->storage_fields as $main_key=>$array){ |
172
|
|
|
|
173
|
|
|
if(is_array($array)) { |
174
|
|
|
foreach ($array as $key => $type) { |
175
|
|
|
|
176
|
|
|
if( $type == "raw") { |
177
|
|
|
add_filter("pre_update_option_" . $this->storage_fields['option_prefix'] . $key, |
178
|
|
|
function ($value) { |
179
|
|
|
|
180
|
|
|
return $this->simple_crypt($value, 'e'); |
181
|
|
|
|
182
|
|
|
}, 10, 1); |
183
|
|
|
|
184
|
|
|
add_filter("option_" . $this->storage_fields['option_prefix'] . $key, function ($value) { |
185
|
|
|
|
186
|
|
|
return $this->simple_crypt($value, 'd'); |
187
|
|
|
|
188
|
|
|
}, 10, 1); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
} |
194
|
|
|
|
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Encrypts and Decrypt a string based on openssl lib |
199
|
|
|
* |
200
|
|
|
* @param $string |
201
|
|
|
* @param string $action |
202
|
|
|
* @return string |
203
|
|
|
*/ |
204
|
|
|
private function simple_crypt( $string, $action = 'e' ) { |
205
|
|
|
// you may change these values to your own |
206
|
|
|
$secret_key = NONCE_KEY; |
207
|
|
|
$secret_iv = NONCE_SALT; |
208
|
|
|
|
209
|
|
|
$output = $string; |
210
|
|
|
$encrypt_method = "AES-256-CBC"; |
211
|
|
|
$key = hash( 'sha256', $secret_key ); |
212
|
|
|
$iv = substr( hash( 'sha256', $secret_iv ), 0, 16 ); |
213
|
|
|
|
214
|
|
|
if( $action == 'e' && function_exists('openssl_encrypt')) { |
215
|
|
|
$output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) ); |
216
|
|
|
} |
217
|
|
|
else if( $action == 'd' && function_exists('openssl_decrypt') && base64_decode( $string )){ |
218
|
|
|
$decrypt = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv ); |
219
|
|
|
if($decrypt) { |
220
|
|
|
//we check if decrypt was succesful |
221
|
|
|
$output = $decrypt; |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
return $output; |
226
|
|
|
} |
227
|
|
|
|
228
|
|
|
private function get_xcloner_container() { |
229
|
|
|
return $this->xcloner_container; |
|
|
|
|
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
public function get_available_storages() { |
233
|
|
|
$return = array(); |
234
|
|
|
foreach ( $this->storage_fields as $storage => $data ) { |
235
|
|
|
$check_field = $this->storage_fields["option_prefix"] . $storage . "_enable"; |
236
|
|
|
if ( get_option( $check_field ) ) { |
237
|
|
|
$return[ $storage ] = $data['text']; |
238
|
|
|
} |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
return $return; |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
public function save( $action = "ftp" ) { |
245
|
|
|
if ( ! $action ) { |
246
|
|
|
return false; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
$storage = $this->xcloner_sanitization->sanitize_input_as_string( $action ); |
250
|
|
|
$this->logger->debug( sprintf( "Saving the remote storage %s options", strtoupper( $action ) ) ); |
251
|
|
|
|
252
|
|
|
if ( is_array( $this->storage_fields[ $storage ] ) ) { |
253
|
|
|
foreach ( $this->storage_fields[ $storage ] as $field => $validation ) { |
254
|
|
|
$check_field = $this->storage_fields["option_prefix"] . $field; |
255
|
|
|
$sanitize_method = "sanitize_input_as_" . $validation; |
256
|
|
|
|
257
|
|
|
if ( ! isset( $_POST[ $check_field ] ) ) { |
258
|
|
|
$_POST[ $check_field ] = 0; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
if ( ! method_exists( $this->xcloner_sanitization, $sanitize_method ) ) { |
262
|
|
|
$sanitize_method = "sanitize_input_as_string"; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
$sanitized_value = $this->xcloner_sanitization->$sanitize_method( stripslashes( $_POST[ $check_field ] ) ); |
266
|
|
|
update_option( $check_field, $sanitized_value ); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
$this->xcloner->trigger_message( __( "%s storage settings saved.", 'xcloner-backup-and-restore' ), "success", $this->storage_fields[ $action ]['text'] ); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
public function check( $action = "ftp" ) { |
275
|
|
|
try { |
276
|
|
|
$this->verify_filesystem( $action ); |
277
|
|
|
$this->xcloner->trigger_message( __( "%s connection is valid.", 'xcloner-backup-and-restore' ), "success", $this->storage_fields[ $action ]['text'] ); |
278
|
|
|
$this->logger->debug( sprintf( "Connection to remote storage %s is valid", strtoupper( $action ) ) ); |
279
|
|
|
} catch ( Exception $e ) { |
280
|
|
|
$this->xcloner->trigger_message( "%s connection error: " . $e->getMessage(), "error", $this->storage_fields[ $action ]['text'] ); |
281
|
|
|
} |
282
|
|
|
} |
283
|
|
|
|
284
|
|
|
public function verify_filesystem( $storage_type ) { |
285
|
|
|
$method = "get_" . $storage_type . "_filesystem"; |
286
|
|
|
|
287
|
|
|
$this->logger->info( sprintf( "Checking validity of the remote storage %s filesystem", strtoupper( $storage_type ) ) ); |
288
|
|
|
|
289
|
|
|
if ( ! method_exists( $this, $method ) ) { |
290
|
|
|
return false; |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
list( $adapter, $filesystem ) = $this->$method(); |
|
|
|
|
294
|
|
|
|
295
|
|
|
$test_file = substr( ".xcloner_" . md5( time() ), 0, 15 ); |
296
|
|
|
|
297
|
|
|
if ( $storage_type == "gdrive" ) { |
298
|
|
|
if ( ! is_array( $filesystem->listContents() ) ) { |
299
|
|
|
throw new Exception( __( "Could not read data", 'xcloner-backup-and-restore' ) ); |
300
|
|
|
} |
301
|
|
|
$this->logger->debug( sprintf( "I can list data from remote storage %s", strtoupper( $storage_type ) ) ); |
302
|
|
|
|
303
|
|
|
return true; |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
//testing write access |
307
|
|
|
if ( ! $filesystem->write( $test_file, "data" ) ) { |
308
|
|
|
throw new Exception( __( "Could not write data", 'xcloner-backup-and-restore' ) ); |
309
|
|
|
} |
310
|
|
|
$this->logger->debug( sprintf( "I can write data to remote storage %s", strtoupper( $storage_type ) ) ); |
311
|
|
|
|
312
|
|
|
//testing read access |
313
|
|
|
if ( ! $filesystem->has( $test_file ) ) { |
314
|
|
|
throw new Exception( __( "Could not read data", 'xcloner-backup-and-restore' ) ); |
315
|
|
|
} |
316
|
|
|
$this->logger->debug( sprintf( "I can read data to remote storage %s", strtoupper( $storage_type ) ) ); |
317
|
|
|
|
318
|
|
|
//delete test file |
319
|
|
|
if ( ! $filesystem->delete( $test_file ) ) { |
320
|
|
|
throw new Exception( __( "Could not delete data", 'xcloner-backup-and-restore' ) ); |
321
|
|
|
} |
322
|
|
|
$this->logger->debug( sprintf( "I can delete data to remote storage %s", strtoupper( $storage_type ) ) ); |
323
|
|
|
|
324
|
|
|
return true; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
public function upload_backup_to_storage( $file, $storage ) { |
328
|
|
|
if ( ! $this->xcloner_file_system->get_storage_filesystem()->has( $file ) ) { |
329
|
|
|
$this->logger->info( sprintf( "File not found %s in local storage", $file ) ); |
330
|
|
|
|
331
|
|
|
return false; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
$method = "get_" . $storage . "_filesystem"; |
335
|
|
|
|
336
|
|
|
if ( ! method_exists( $this, $method ) ) { |
337
|
|
|
return false; |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
list( $remote_storage_adapter, $remote_storage_filesystem ) = $this->$method(); |
|
|
|
|
341
|
|
|
|
342
|
|
|
//doing remote storage cleaning here |
343
|
|
|
$this->clean_remote_storage( $storage, $remote_storage_filesystem ); |
344
|
|
|
|
345
|
|
|
$this->logger->info( sprintf( "Transferring backup %s to remote storage %s", $file, strtoupper( $storage ) ), array( "" ) ); |
346
|
|
|
|
347
|
|
|
/*if(!$this->xcloner_file_system->get_storage_filesystem()->has($file)) |
348
|
|
|
{ |
349
|
|
|
$this->logger->info(sprintf("File not found %s in local storage", $file)); |
350
|
|
|
return false; |
351
|
|
|
}*/ |
352
|
|
|
|
353
|
|
|
$backup_file_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream( $file ); |
354
|
|
|
|
355
|
|
|
if ( ! $remote_storage_filesystem->writeStream( $file, $backup_file_stream ) ) { |
356
|
|
|
$this->logger->info( sprintf( "Could not transfer file %s", $file ) ); |
357
|
|
|
|
358
|
|
|
return false; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
View Code Duplication |
if ( $this->xcloner_file_system->is_multipart( $file ) ) { |
|
|
|
|
362
|
|
|
$parts = $this->xcloner_file_system->get_multipart_files( $file ); |
363
|
|
|
if ( is_array( $parts ) ) { |
364
|
|
|
foreach ( $parts as $part_file ) { |
365
|
|
|
$this->logger->info( sprintf( "Transferring backup %s to remote storage %s", $part_file, strtoupper( $storage ) ), array( "" ) ); |
366
|
|
|
|
367
|
|
|
$backup_file_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream( $part_file ); |
368
|
|
|
if ( ! $remote_storage_filesystem->writeStream( $part_file, $backup_file_stream ) ) { |
369
|
|
|
return false; |
370
|
|
|
} |
371
|
|
|
} |
372
|
|
|
} |
373
|
|
|
} |
374
|
|
|
|
375
|
|
|
$this->logger->info( sprintf( "Upload done, disconnecting from remote storage %s", strtoupper( $storage ) ) ); |
376
|
|
|
|
377
|
|
|
return true; |
378
|
|
|
|
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
public function copy_backup_remote_to_local( $file, $storage ) { |
382
|
|
|
$method = "get_" . $storage . "_filesystem"; |
383
|
|
|
|
384
|
|
|
$target_filename = $file; |
385
|
|
|
|
386
|
|
|
if ( ! method_exists( $this, $method ) ) { |
387
|
|
|
return false; |
388
|
|
|
} |
389
|
|
|
|
390
|
|
|
list( $remote_storage_adapter, $remote_storage_filesystem ) = $this->$method(); |
|
|
|
|
391
|
|
|
|
392
|
|
|
if ( ! $remote_storage_filesystem->has( $file ) ) { |
393
|
|
|
$this->logger->info( sprintf( "File not found %s in remote storage %s", $file, strtoupper( $storage ) ) ); |
394
|
|
|
|
395
|
|
|
return false; |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
if ( $storage == "gdrive" ) { |
399
|
|
|
$metadata = $remote_storage_filesystem->getMetadata( $file ); |
400
|
|
|
$target_filename = $metadata['filename'] . "." . $metadata['extension']; |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
$this->logger->info( sprintf( "Transferring backup %s to local storage from %s storage", $file, strtoupper( $storage ) ), array( "" ) ); |
404
|
|
|
|
405
|
|
|
$backup_file_stream = $remote_storage_filesystem->readStream( $file ); |
406
|
|
|
|
407
|
|
|
if ( ! $this->xcloner_file_system->get_storage_filesystem()->writeStream( $target_filename, $backup_file_stream ) ) { |
408
|
|
|
$this->logger->info( sprintf( "Could not transfer file %s", $file ) ); |
409
|
|
|
|
410
|
|
|
return false; |
411
|
|
|
} |
412
|
|
|
|
413
|
|
View Code Duplication |
if ( $this->xcloner_file_system->is_multipart( $target_filename ) ) { |
|
|
|
|
414
|
|
|
$parts = $this->xcloner_file_system->get_multipart_files( $file, $storage ); |
415
|
|
|
if ( is_array( $parts ) ) { |
416
|
|
|
foreach ( $parts as $part_file ) { |
417
|
|
|
$this->logger->info( sprintf( "Transferring backup %s to local storage from %s storage", $part_file, strtoupper( $storage ) ), array( "" ) ); |
418
|
|
|
|
419
|
|
|
$backup_file_stream = $remote_storage_filesystem->readStream( $part_file ); |
420
|
|
|
if ( ! $this->xcloner_file_system->get_storage_filesystem()->writeStream( $part_file, $backup_file_stream ) ) { |
421
|
|
|
return false; |
422
|
|
|
} |
423
|
|
|
} |
424
|
|
|
} |
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
$this->logger->info( sprintf( "Upload done, disconnecting from remote storage %s", strtoupper( $storage ) ) ); |
428
|
|
|
|
429
|
|
|
return true; |
430
|
|
|
|
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
public function clean_remote_storage( $storage, $remote_storage_filesystem ) { |
434
|
|
|
$check_field = $this->storage_fields["option_prefix"] . $storage . "_cleanup_days"; |
435
|
|
|
if ( $expire_days = get_option( $check_field ) ) { |
436
|
|
|
$this->logger->info( sprintf( "Doing %s remote storage cleanup for %s days limit", strtoupper( $storage ), $expire_days ) ); |
437
|
|
|
$files = $remote_storage_filesystem->listContents(); |
438
|
|
|
|
439
|
|
|
$current_timestamp = strtotime( "-" . $expire_days . " days" ); |
440
|
|
|
|
441
|
|
|
if ( is_array( $files ) ) { |
442
|
|
|
foreach ( $files as $file ) { |
443
|
|
|
$file['timestamp'] = $remote_storage_filesystem->getTimestamp( $file['path'] ); |
444
|
|
|
|
445
|
|
|
if ( $current_timestamp >= $file['timestamp'] ) { |
446
|
|
|
$remote_storage_filesystem->delete( $file['path'] ); |
447
|
|
|
$this->logger->info( "Deleting remote file " . $file['path'] . " matching rule", array( |
448
|
|
|
"RETENTION LIMIT TIMESTAMP", |
449
|
|
|
$file['timestamp'] . " =< " . $expire_days |
450
|
|
|
) ); |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
} |
454
|
|
|
} |
455
|
|
|
} |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
public function get_azure_filesystem() { |
459
|
|
|
$this->logger->info( sprintf( "Creating the AZURE BLOB remote storage connection" ), array( "" ) ); |
460
|
|
|
|
461
|
|
|
if ( version_compare( phpversion(), '5.6.0', '<' ) ) { |
462
|
|
|
throw new Exception( "AZURE BLOB requires PHP 5.6 to be installed!" ); |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
if ( ! class_exists( 'XmlWriter' ) ) { |
466
|
|
|
throw new Exception( "AZURE BLOB requires libxml PHP module to be installed with XmlWriter class enabled!" ); |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
$endpoint = sprintf( |
470
|
|
|
'DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s', |
471
|
|
|
get_option( "xcloner_azure_account_name" ), |
472
|
|
|
get_option( "xcloner_azure_api_key" ) |
473
|
|
|
); |
474
|
|
|
|
475
|
|
|
$blobRestProxy = ServicesBuilder::getInstance()->createBlobService( $endpoint ); |
476
|
|
|
|
477
|
|
|
$adapter = new AzureAdapter( $blobRestProxy, get_option( "xcloner_azure_container" ) ); |
478
|
|
|
|
479
|
|
|
$filesystem = new Filesystem( $adapter, new Config( [ |
480
|
|
|
'disable_asserts' => true, |
481
|
|
|
] ) ); |
482
|
|
|
|
483
|
|
|
return array( $adapter, $filesystem ); |
484
|
|
|
} |
485
|
|
|
|
486
|
|
View Code Duplication |
public function get_dropbox_filesystem() { |
|
|
|
|
487
|
|
|
$this->logger->info( sprintf( "Creating the DROPBOX remote storage connection" ), array( "" ) ); |
488
|
|
|
|
489
|
|
|
if ( version_compare( phpversion(), '5.6.0', '<' ) ) { |
490
|
|
|
throw new Exception( "DROPBOX requires PHP 5.6 to be installed!" ); |
491
|
|
|
} |
492
|
|
|
|
493
|
|
|
$client = new DropboxClient( get_option( "xcloner_dropbox_access_token" ) ); |
494
|
|
|
$adapter = new DropboxAdapter( $client, get_option( "xcloner_dropbox_prefix" ) ); |
495
|
|
|
|
496
|
|
|
$filesystem = new Filesystem( $adapter, new Config( [ |
497
|
|
|
'disable_asserts' => true, |
498
|
|
|
] ) ); |
499
|
|
|
|
500
|
|
|
return array( $adapter, $filesystem ); |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
public function get_aws_filesystem() { |
504
|
|
|
$this->logger->info( sprintf( "Creating the S3 remote storage connection" ), array( "" ) ); |
505
|
|
|
|
506
|
|
|
if ( version_compare( phpversion(), '5.6.0', '<' ) ) { |
507
|
|
|
throw new Exception( "S3 class requires PHP 5.6 to be installed!" ); |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
if ( ! class_exists( 'XmlWriter' ) ) { |
511
|
|
|
throw new Exception( "AZURE BLOB requires libxml PHP module to be installed with XmlWriter class enabled!" ); |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
|
515
|
|
|
$credentials = array( |
516
|
|
|
'credentials' => array( |
517
|
|
|
'key' => get_option( "xcloner_aws_key" ), |
518
|
|
|
'secret' => get_option( "xcloner_aws_secret" ) |
519
|
|
|
), |
520
|
|
|
'region' => get_option( "xcloner_aws_region" ), |
521
|
|
|
'version' => 'latest', |
522
|
|
|
); |
523
|
|
|
|
524
|
|
|
if ( get_option( 'xcloner_aws_endpoint' ) != "" && ! get_option( "xcloner_aws_region" ) ) { |
525
|
|
|
|
526
|
|
|
$credentials['endpoint'] = get_option( 'xcloner_aws_endpoint' ); |
527
|
|
|
#$credentials['use_path_style_endpoint'] = true; |
528
|
|
|
#$credentials['bucket_endpoint'] = false; |
529
|
|
|
|
530
|
|
|
|
531
|
|
|
} |
532
|
|
|
|
533
|
|
|
$client = new S3Client( $credentials ); |
534
|
|
|
|
535
|
|
|
$adapter = new AwsS3Adapter( $client, get_option( "xcloner_aws_bucket_name" ), get_option( "xcloner_aws_prefix" ) ); |
536
|
|
|
$filesystem = new Filesystem( $adapter, new Config( [ |
537
|
|
|
'disable_asserts' => true, |
538
|
|
|
] ) ); |
539
|
|
|
|
540
|
|
|
return array( $adapter, $filesystem ); |
541
|
|
|
} |
542
|
|
|
|
543
|
|
View Code Duplication |
public function get_backblaze_filesystem() { |
|
|
|
|
544
|
|
|
$this->logger->info( sprintf( "Creating the BACKBLAZE remote storage connection" ), array( "" ) ); |
545
|
|
|
|
546
|
|
|
if ( version_compare( phpversion(), '5.6.0', '<' ) ) { |
547
|
|
|
throw new Exception( "BACKBLAZE API requires PHP 5.6 to be installed!" ); |
548
|
|
|
} |
549
|
|
|
|
550
|
|
|
|
551
|
|
|
$client = new B2Client( get_option( "xcloner_backblaze_account_id" ), get_option( "xcloner_backblaze_application_key" ) ); |
552
|
|
|
$adapter = new BackblazeAdapter( $client, get_option( "xcloner_backblaze_bucket_name" ) ); |
553
|
|
|
|
554
|
|
|
$filesystem = new Filesystem( $adapter, new Config( [ |
555
|
|
|
'disable_asserts' => true, |
556
|
|
|
] ) ); |
557
|
|
|
|
558
|
|
|
return array( $adapter, $filesystem ); |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
public function get_webdav_filesystem() { |
562
|
|
|
$this->logger->info( sprintf( "Creating the WEBDAV remote storage connection" ), array( "" ) ); |
563
|
|
|
|
564
|
|
|
if ( version_compare( phpversion(), '5.6.0', '<' ) ) { |
565
|
|
|
throw new Exception( "WEBDAV API requires PHP 5.6 to be installed!" ); |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
$settings = array( |
569
|
|
|
'baseUri' => get_option( "xcloner_webdav_url" ), |
570
|
|
|
'userName' => get_option( "xcloner_webdav_username" ), |
571
|
|
|
'password' => get_option( "xcloner_webdav_password" ), |
572
|
|
|
//'proxy' => 'locahost:8888', |
573
|
|
|
); |
574
|
|
|
|
575
|
|
|
|
576
|
|
|
$client = new SabreClient( $settings ); |
577
|
|
|
$adapter = new WebDAVAdapter( $client, get_option( "xcloner_webdav_target_folder" ) ); |
578
|
|
|
$filesystem = new Filesystem( $adapter, new Config( [ |
579
|
|
|
'disable_asserts' => true, |
580
|
|
|
] ) ); |
581
|
|
|
|
582
|
|
|
return array( $adapter, $filesystem ); |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
|
586
|
|
|
public function gdrive_construct() { |
587
|
|
|
|
588
|
|
|
//if((function_exists("is_plugin_active") && !is_plugin_active("xcloner-google-drive/xcloner-google-drive.php")) || !file_exists(__DIR__ . "/../../xcloner-google-drive/vendor/autoload.php")) |
589
|
|
|
if ( ! class_exists( 'Google_Client' ) ) { |
590
|
|
|
return false; |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
//require_once(__DIR__ . "/../../xcloner-google-drive/vendor/autoload.php"); |
594
|
|
|
|
595
|
|
|
$client = new \Google_Client(); |
596
|
|
|
$client->setApplicationName( $this->gdrive_app_name ); |
597
|
|
|
$client->setClientId( get_option( "xcloner_gdrive_client_id" ) ); |
598
|
|
|
$client->setClientSecret( get_option( "xcloner_gdrive_client_secret" ) ); |
599
|
|
|
|
600
|
|
|
//$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']."?page=xcloner_remote_storage_page&action=set_gdrive_code"; |
601
|
|
|
$redirect_uri = "urn:ietf:wg:oauth:2.0:oob"; |
602
|
|
|
|
603
|
|
|
$client->setRedirectUri( $redirect_uri ); //urn:ietf:wg:oauth:2.0:oob |
604
|
|
|
$client->addScope( "https://www.googleapis.com/auth/drive" ); |
605
|
|
|
$client->setAccessType( 'offline' ); |
606
|
|
|
|
607
|
|
|
return $client; |
608
|
|
|
} |
609
|
|
|
|
610
|
|
|
public function get_gdrive_auth_url() { |
611
|
|
|
$client = $this->gdrive_construct(); |
612
|
|
|
|
613
|
|
|
if ( ! $client ) { |
614
|
|
|
return false; |
615
|
|
|
} |
616
|
|
|
|
617
|
|
|
return $authUrl = $client->createAuthUrl(); |
|
|
|
|
618
|
|
|
} |
619
|
|
|
|
620
|
|
|
public function set_access_token( $code ) { |
621
|
|
|
$client = $this->gdrive_construct(); |
622
|
|
|
|
623
|
|
|
if ( ! $client ) { |
624
|
|
|
$error_msg = "Could not initialize the Google Drive Class, please check that the xcloner-google-drive plugin is enabled..."; |
625
|
|
|
$this->logger->error( $error_msg ); |
626
|
|
|
|
627
|
|
|
return false; |
628
|
|
|
} |
629
|
|
|
|
630
|
|
|
$token = $client->fetchAccessTokenWithAuthCode( $code ); |
631
|
|
|
$client->setAccessToken( $token ); |
632
|
|
|
|
633
|
|
|
update_option( "xcloner_gdrive_access_token", $token['access_token'] ); |
634
|
|
|
update_option( "xcloner_gdrive_refresh_token", $token['refresh_token'] ); |
635
|
|
|
|
636
|
|
|
$redirect_url = ( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] . "?page=xcloner_remote_storage_page#gdrive" ); |
637
|
|
|
|
638
|
|
|
?> |
639
|
|
|
<script> |
640
|
|
|
window.location = '<?php echo $redirect_url?>'; |
641
|
|
|
</script> |
642
|
|
|
<?php |
643
|
|
|
|
644
|
|
|
} |
645
|
|
|
|
646
|
|
|
/* |
647
|
|
|
* php composer.phar remove nao-pon/flysystem-google-drive |
648
|
|
|
* |
649
|
|
|
*/ |
650
|
|
|
public function get_gdrive_filesystem() { |
651
|
|
|
|
652
|
|
|
if ( version_compare( phpversion(), '5.6.0', '<' ) ) { |
653
|
|
|
throw new Exception( "Google Drive API requires PHP 5.6 to be installed!" ); |
654
|
|
|
} |
655
|
|
|
|
656
|
|
|
$this->logger->info( sprintf( "Creating the Google Drive remote storage connection" ), array( "" ) ); |
657
|
|
|
|
658
|
|
|
$client = $this->gdrive_construct(); |
659
|
|
|
|
660
|
|
|
if ( ! $client ) { |
661
|
|
|
$error_msg = "Could not initialize the Google Drive Class, please check that the xcloner-google-drive plugin is enabled..."; |
662
|
|
|
$this->logger->error( $error_msg ); |
663
|
|
|
throw new Exception( $error_msg ); |
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
$client->refreshToken( get_option( "xcloner_gdrive_refresh_token" ) ); |
667
|
|
|
|
668
|
|
|
$service = new \Google_Service_Drive( $client ); |
669
|
|
|
|
670
|
|
|
/*if( get_option("xcloner_gdrive_empty_trash",0) ){ |
671
|
|
|
$this->logger->info(sprintf("Doing a Google Drive emptyTrash call"), array("")); |
672
|
|
|
$service->files->emptyTrash(); |
673
|
|
|
}*/ |
674
|
|
|
|
675
|
|
|
$parent = 'root'; |
676
|
|
|
$dir = basename( get_option( "xcloner_gdrive_target_folder" ) ); |
677
|
|
|
|
678
|
|
|
$folderID = get_option( "xcloner_gdrive_target_folder" ); |
679
|
|
|
|
680
|
|
|
$tmp = parse_url( $folderID ); |
681
|
|
|
|
682
|
|
|
if ( isset( $tmp['query'] ) ) { |
683
|
|
|
$folderID = str_replace( "id=", "", $tmp['query'] ); |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
if ( stristr( $folderID, "/" ) ) { |
687
|
|
|
$query = sprintf( 'mimeType = \'application/vnd.google-apps.folder\' and \'%s\' in parents and name contains \'%s\'', $parent, $dir ); |
688
|
|
|
$response = $service->files->listFiles( [ |
689
|
|
|
'pageSize' => 1, |
690
|
|
|
'q' => $query |
691
|
|
|
] ); |
692
|
|
|
|
693
|
|
|
if ( sizeof( $response ) ) { |
694
|
|
|
foreach ( $response as $obj ) { |
695
|
|
|
$folderID = $obj->getId(); |
696
|
|
|
} |
697
|
|
|
} else { |
698
|
|
|
$this->xcloner->trigger_message( sprintf( __( "Could not find folder ID by name %s", 'xcloner-backup-and-restore' ), $folderID ), "error" ); |
699
|
|
|
} |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
$this->logger->info( sprintf( "Using target folder with ID %s on the remote storage", $folderID ) ); |
703
|
|
|
|
704
|
|
|
if ( class_exists( 'XCloner_Google_Drive_Adapter' ) ) { |
705
|
|
|
$adapter = new XCloner_Google_Drive_Adapter( $service, $folderID ); |
706
|
|
|
} else { |
707
|
|
|
$adapter = new \Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter( $service, $folderID ); |
708
|
|
|
} |
709
|
|
|
|
710
|
|
|
$filesystem = new \League\Flysystem\Filesystem( $adapter, new Config( [ |
711
|
|
|
'disable_asserts' => true, |
712
|
|
|
] ) ); |
713
|
|
|
|
714
|
|
|
|
715
|
|
|
return array( $adapter, $filesystem ); |
716
|
|
|
} |
717
|
|
|
|
718
|
|
View Code Duplication |
public function get_ftp_filesystem() { |
|
|
|
|
719
|
|
|
$this->logger->info( sprintf( "Creating the FTP remote storage connection" ), array( "" ) ); |
720
|
|
|
|
721
|
|
|
$adapter = new Adapter( [ |
722
|
|
|
'host' => get_option( "xcloner_ftp_hostname" ), |
723
|
|
|
'username' => get_option( "xcloner_ftp_username" ), |
724
|
|
|
'password' => get_option( "xcloner_ftp_password" ), |
725
|
|
|
|
726
|
|
|
/** optional config settings */ |
727
|
|
|
'port' => get_option( "xcloner_ftp_port", 21 ), |
728
|
|
|
'root' => get_option( "xcloner_ftp_path" ), |
729
|
|
|
'passive' => get_option( "xcloner_ftp_transfer_mode" ), |
730
|
|
|
'ssl' => get_option( "xcloner_ftp_ssl_mode" ), |
731
|
|
|
'timeout' => get_option( "xcloner_ftp_timeout", 30 ), |
732
|
|
|
] ); |
733
|
|
|
|
734
|
|
|
$adapter->connect(); |
735
|
|
|
|
736
|
|
|
$filesystem = new Filesystem( $adapter, new Config( [ |
737
|
|
|
'disable_asserts' => true, |
738
|
|
|
] ) ); |
739
|
|
|
|
740
|
|
|
return array( $adapter, $filesystem ); |
741
|
|
|
} |
742
|
|
|
|
743
|
|
View Code Duplication |
public function get_sftp_filesystem() { |
|
|
|
|
744
|
|
|
$this->logger->info( sprintf( "Creating the SFTP remote storage connection" ), array( "" ) ); |
745
|
|
|
|
746
|
|
|
$adapter = new SftpAdapter( [ |
747
|
|
|
'host' => get_option( "xcloner_sftp_hostname" ), |
748
|
|
|
'username' => get_option( "xcloner_sftp_username" ), |
749
|
|
|
'password' => get_option( "xcloner_sftp_password" ), |
750
|
|
|
|
751
|
|
|
/** optional config settings */ |
752
|
|
|
'port' => get_option( "xcloner_sftp_port", 22 ), |
753
|
|
|
'root' => get_option( "xcloner_sftp_path" ), |
754
|
|
|
'privateKey' => get_option( "xcloner_sftp_private_key" ), |
755
|
|
|
'timeout' => get_option( "xcloner_ftp_timeout", 30 ), |
756
|
|
|
] ); |
757
|
|
|
|
758
|
|
|
$adapter->connect(); |
759
|
|
|
|
760
|
|
|
$filesystem = new Filesystem( $adapter, new Config( [ |
761
|
|
|
'disable_asserts' => true, |
762
|
|
|
] ) ); |
763
|
|
|
|
764
|
|
|
return array( $adapter, $filesystem ); |
765
|
|
|
} |
766
|
|
|
|
767
|
|
|
public function change_storage_status( $field, $value ) { |
768
|
|
|
$field = $this->xcloner_sanitization->sanitize_input_as_string( $field ); |
769
|
|
|
$value = $this->xcloner_sanitization->sanitize_input_as_int( $value ); |
770
|
|
|
|
771
|
|
|
return update_option( $field, $value ); |
772
|
|
|
} |
773
|
|
|
|
774
|
|
|
public function get_aws_regions() { |
775
|
|
|
return $this->aws_regions; |
776
|
|
|
} |
777
|
|
|
|
778
|
|
|
} |
779
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.