Duplicator – WordPress Migration Plugin - Version 1.2.40

Version Description

Download this release

Release Info

Developer cory@lamle.org
Plugin Icon 128x128 Duplicator – WordPress Migration Plugin
Version 1.2.40
Comparing to
See all releases

Code changes from version 1.2.38 to 1.2.40

classes/package/class.pack.php CHANGED
@@ -1,602 +1,600 @@
1
- <?php
2
- if (!defined('DUPLICATOR_VERSION')) exit; // Exit if accessed directly
3
-
4
- require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.php');
5
- require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
6
- require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.installer.php');
7
- require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.database.php');
8
-
9
- final class DUP_PackageStatus
10
- {
11
-
12
- private function __construct()
13
- {
14
-
15
- }
16
- const START = 10;
17
- const DBSTART = 20;
18
- const DBDONE = 30;
19
- const ARCSTART = 40;
20
- const ARCDONE = 50;
21
- const COMPLETE = 100;
22
-
23
- }
24
-
25
- final class DUP_PackageType
26
- {
27
- const MANUAL = 0;
28
- const SCHEDULED = 1;
29
-
30
- }
31
-
32
- /**
33
- * Class used to store and process all Package logic
34
- *
35
- * @package Dupicator\classes
36
- */
37
- class DUP_Package
38
- {
39
- const OPT_ACTIVE = 'duplicator_package_active';
40
-
41
- //Properties
42
- public $Created;
43
- public $Version;
44
- public $VersionWP;
45
- public $VersionDB;
46
- public $VersionPHP;
47
- public $VersionOS;
48
- public $ID;
49
- public $Name;
50
- public $Hash;
51
- public $NameHash;
52
- public $Type;
53
- public $Notes;
54
- public $StorePath;
55
- public $StoreURL;
56
- public $ScanFile;
57
- public $Runtime;
58
- public $ExeSize;
59
- public $ZipSize;
60
- public $Status;
61
- public $WPUser;
62
- //Objects
63
- public $Archive;
64
- public $Installer;
65
- public $Database;
66
-
67
- /**
68
- * Manages the Package Process
69
- */
70
- function __construct()
71
- {
72
-
73
- $this->ID = null;
74
- $this->Version = DUPLICATOR_VERSION;
75
-
76
- $this->Type = DUP_PackageType::MANUAL;
77
- $this->Name = self::getDefaultName();
78
- $this->Notes = null;
79
- $this->StoreURL = DUP_Util::snapshotURL();
80
- $this->StorePath = DUPLICATOR_SSDIR_PATH_TMP;
81
- $this->Database = new DUP_Database($this);
82
- $this->Archive = new DUP_Archive($this);
83
- $this->Installer = new DUP_Installer($this);
84
- }
85
-
86
- /**
87
- * Generates a json scan report
88
- *
89
- * @return array of scan results
90
- *
91
- * @notes: Testing = /wp-admin/admin-ajax.php?action=duplicator_package_scan
92
- */
93
- public function runScanner()
94
- {
95
- $timerStart = DUP_Util::getMicrotime();
96
- $report = array();
97
- $this->ScanFile = "{$this->NameHash}_scan.json";
98
-
99
- $report['RPT']['ScanTime'] = "0";
100
- $report['RPT']['ScanFile'] = $this->ScanFile;
101
-
102
- //SERVER
103
- $srv = DUP_Server::getChecks();
104
- $report['SRV'] = $srv['SRV'];
105
-
106
- //FILES
107
- $this->Archive->getScannerData();
108
- $dirCount = count($this->Archive->Dirs);
109
- $fileCount = count($this->Archive->Files);
110
- $fullCount = $dirCount + $fileCount;
111
-
112
- $report['ARC']['Size'] = DUP_Util::byteSize($this->Archive->Size) or "unknown";
113
- $report['ARC']['DirCount'] = number_format($dirCount);
114
- $report['ARC']['FileCount'] = number_format($fileCount);
115
- $report['ARC']['FullCount'] = number_format($fullCount);
116
- $report['ARC']['FilterDirsAll'] = $this->Archive->FilterDirsAll;
117
- $report['ARC']['FilterFilesAll'] = $this->Archive->FilterFilesAll;
118
- $report['ARC']['FilterExtsAll'] = $this->Archive->FilterExtsAll;
119
- $report['ARC']['FilterInfo'] = $this->Archive->FilterInfo;
120
- $report['ARC']['RecursiveLinks'] = $this->Archive->RecursiveLinks;
121
- $report['ARC']['UnreadableItems'] = array_merge($this->Archive->FilterInfo->Files->Unreadable,$this->Archive->FilterInfo->Dirs->Unreadable);
122
- $report['ARC']['Status']['Size'] = ($this->Archive->Size > DUPLICATOR_SCAN_SIZE_DEFAULT) ? 'Warn' : 'Good';
123
- $report['ARC']['Status']['Names'] = (count($this->Archive->FilterInfo->Files->Warning) + count($this->Archive->FilterInfo->Dirs->Warning)) ? 'Warn' : 'Good';
124
- $report['ARC']['Status']['UnreadableItems'] = !empty($this->Archive->RecursiveLinks) || !empty($report['ARC']['UnreadableItems'])? 'Warn' : 'Good';
125
-
126
- //$report['ARC']['Status']['Big'] = count($this->Archive->FilterInfo->Files->Size) ? 'Warn' : 'Good';
127
- $report['ARC']['Dirs'] = $this->Archive->Dirs;
128
- $report['ARC']['Files'] = $this->Archive->Files;
129
- $report['ARC']['Status']['AddonSites'] = count($this->Archive->FilterInfo->Dirs->AddonSites) ? 'Warn' : 'Good';
130
-
131
-
132
-
133
- //DATABASE
134
- $db = $this->Database->getScannerData();
135
- $report['DB'] = $db;
136
-
137
- $warnings = array(
138
- $report['SRV']['PHP']['ALL'],
139
- $report['SRV']['WP']['ALL'],
140
- $report['ARC']['Status']['Size'],
141
- $report['ARC']['Status']['Names'],
142
- $db['Status']['DB_Size'],
143
- $db['Status']['DB_Rows']);
144
-
145
- //array_count_values will throw a warning message if it has null values,
146
- //so lets replace all nulls with empty string
147
- foreach ($warnings as $i => $value) {
148
- if (is_null($value)) {
149
- $warnings[$i] = '';
150
- }
151
- }
152
-
153
- $warn_counts = is_array($warnings) ? array_count_values($warnings) : 0;
154
- $report['RPT']['Warnings'] = is_null($warn_counts['Warn']) ? 0 : $warn_counts['Warn'];
155
- $report['RPT']['Success'] = is_null($warn_counts['Good']) ? 0 : $warn_counts['Good'];
156
- $report['RPT']['ScanTime'] = DUP_Util::elapsedTime(DUP_Util::getMicrotime(), $timerStart);
157
- $fp = fopen(DUPLICATOR_SSDIR_PATH_TMP."/{$this->ScanFile}", 'w');
158
-
159
-
160
- fwrite($fp, json_encode($report));
161
- fclose($fp);
162
-
163
- return $report;
164
- }
165
-
166
- /**
167
- * Starts the package build process
168
- *
169
- * @return obj Returns a DUP_Package object
170
- */
171
- public function runBuild()
172
- {
173
- global $wp_version;
174
- global $wpdb;
175
- global $current_user;
176
-
177
- $timerStart = DUP_Util::getMicrotime();
178
-
179
- $this->Archive->File = "{$this->NameHash}_archive.zip";
180
- $this->Installer->File = "{$this->NameHash}_installer.php";
181
- $this->Database->File = "{$this->NameHash}_database.sql";
182
- $this->WPUser = isset($current_user->user_login) ? $current_user->user_login : 'unknown';
183
-
184
- //START LOGGING
185
- DUP_Log::Open($this->NameHash);
186
- $php_max_time = @ini_get("max_execution_time");
187
- $php_max_memory = @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY);
188
- $php_max_time = ($php_max_time == 0) ? "(0) no time limit imposed" : "[{$php_max_time}] not allowed";
189
- $php_max_memory = ($php_max_memory === false) ? "Unabled to set php memory_limit" : DUPLICATOR_PHP_MAX_MEMORY." ({$php_max_memory} default)";
190
-
191
- $info = "********************************************************************************\n";
192
- $info .= "DUPLICATOR-LITE PACKAGE-LOG: ".@date(get_option('date_format')." ".get_option('time_format'))."\n";
193
- $info .= "NOTICE: Do NOT post to public sites or forums \n";
194
- $info .= "********************************************************************************\n";
195
- $info .= "VERSION:\t".DUPLICATOR_VERSION."\n";
196
- $info .= "WORDPRESS:\t{$wp_version}\n";
197
- $info .= "PHP INFO:\t".phpversion().' | '.'SAPI: '.php_sapi_name()."\n";
198
- $info .= "SERVER:\t\t{$_SERVER['SERVER_SOFTWARE']} \n";
199
- $info .= "PHP TIME LIMIT: {$php_max_time} \n";
200
- $info .= "PHP MAX MEMORY: {$php_max_memory} \n";
201
- $info .= "MEMORY STACK: ".DUP_Server::getPHPMemory();
202
- DUP_Log::Info($info);
203
- $info = null;
204
-
205
- //CREATE DB RECORD
206
- $packageObj = serialize($this);
207
- if (!$packageObj) {
208
- DUP_Log::Error("Unable to serialize pacakge object while building record.");
209
- }
210
-
211
- $this->ID = $this->getHashKey($this->Hash);
212
-
213
- if ($this->ID != 0) {
214
- $this->setStatus(DUP_PackageStatus::START);
215
- } else {
216
- $results = $wpdb->insert($wpdb->prefix."duplicator_packages",
217
- array(
218
- 'name' => $this->Name,
219
- 'hash' => $this->Hash,
220
- 'status' => DUP_PackageStatus::START,
221
- 'created' => current_time('mysql', get_option('gmt_offset', 1)),
222
- 'owner' => isset($current_user->user_login) ? $current_user->user_login : 'unknown',
223
- 'package' => $packageObj)
224
- );
225
- if ($results === false) {
226
-
227
- $wpdb->print_error();
228
- DUP_Log::Error("Duplicator is unable to insert a package record into the database table.", "'{$wpdb->last_error}'");
229
- }
230
- $this->ID = $wpdb->insert_id;
231
- }
232
-
233
- //START BUILD
234
- //PHPs serialze method will return the object, but the ID above is not passed
235
- //for one reason or another so passing the object back in seems to do the trick
236
- $this->Database->build($this);
237
- $this->Archive->build($this);
238
- $this->Installer->build($this);
239
-
240
- //INTEGRITY CHECKS
241
- DUP_Log::Info("\n********************************************************************************");
242
- DUP_Log::Info("INTEGRITY CHECKS:");
243
- DUP_Log::Info("********************************************************************************");
244
- $dbSizeRead = DUP_Util::byteSize($this->Database->Size);
245
- $zipSizeRead = DUP_Util::byteSize($this->Archive->Size);
246
- $exeSizeRead = DUP_Util::byteSize($this->Installer->Size);
247
-
248
- DUP_Log::Info("SQL File: {$dbSizeRead}");
249
- DUP_Log::Info("Installer File: {$exeSizeRead}");
250
- DUP_Log::Info("Archive File: {$zipSizeRead} ");
251
-
252
- if (!($this->Archive->Size && $this->Database->Size && $this->Installer->Size)) {
253
- DUP_Log::Error("A required file contains zero bytes.", "Archive Size: {$zipSizeRead} | SQL Size: {$dbSizeRead} | Installer Size: {$exeSizeRead}");
254
- }
255
-
256
- //Validate SQL files completed
257
- $sql_tmp_path = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP.'/'.$this->Database->File);
258
- $sql_complete_txt = DUP_Util::tailFile($sql_tmp_path, 3);
259
- if (!strstr($sql_complete_txt, 'DUPLICATOR_MYSQLDUMP_EOF')) {
260
- DUP_Log::Error("ERROR: SQL file not complete. The end of file marker was not found. Please try to re-create the package.");
261
- }
262
-
263
- $timerEnd = DUP_Util::getMicrotime();
264
- $timerSum = DUP_Util::elapsedTime($timerEnd, $timerStart);
265
-
266
- $this->Runtime = $timerSum;
267
- $this->ExeSize = $exeSizeRead;
268
- $this->ZipSize = $zipSizeRead;
269
-
270
- $this->buildCleanup();
271
-
272
- //FINAL REPORT
273
- $info = "\n********************************************************************************\n";
274
- $info .= "RECORD ID:[{$this->ID}]\n";
275
- $info .= "TOTAL PROCESS RUNTIME: {$timerSum}\n";
276
- $info .= "PEAK PHP MEMORY USED: ".DUP_Server::getPHPMemory(true)."\n";
277
- $info .= "DONE PROCESSING => {$this->Name} ".@date(get_option('date_format')." ".get_option('time_format'))."\n";
278
-
279
- DUP_Log::Info($info);
280
- DUP_Log::Close();
281
-
282
- $this->setStatus(DUP_PackageStatus::COMPLETE);
283
- return $this;
284
- }
285
-
286
- /**
287
- * Saves the active options associted with the active(latest) package.
288
- *
289
- * @see DUP_Package::getActive
290
- *
291
- * @param $_POST $post The Post server object
292
- *
293
- * @return null
294
- */
295
- public function saveActive($post = null)
296
- {
297
- global $wp_version;
298
-
299
- if (isset($post)) {
300
- $post = stripslashes_deep($post);
301
-
302
- $name = ( isset($post['package-name']) && !empty($post['package-name'])) ? $post['package-name'] : self::getDefaultName();
303
- $name = substr(sanitize_file_name($name), 0, 40);
304
- $name = str_replace(array('.', '-', ';', ':', "'", '"'), '', $name);
305
-
306
- $filter_dirs = isset($post['filter-dirs']) ? $this->Archive->parseDirectoryFilter($post['filter-dirs']) : '';
307
- $filter_files = isset($post['filter-files']) ? $this->Archive->parseFileFilter($post['filter-files']) : '';
308
- $filter_exts = isset($post['filter-exts']) ? $this->Archive->parseExtensionFilter($post['filter-exts']) : '';
309
- $tablelist = isset($post['dbtables']) ? implode(',', $post['dbtables']) : '';
310
- $compatlist = isset($post['dbcompat']) ? implode(',', $post['dbcompat']) : '';
311
- $dbversion = DUP_DB::getVersion();
312
- $dbversion = is_null($dbversion) ? '- unknown -' : $dbversion;
313
- $dbcomments = DUP_DB::getVariable('version_comment');
314
- $dbcomments = is_null($dbcomments) ? '- unknown -' : $dbcomments;
315
-
316
-
317
- //PACKAGE
318
- $this->Created = date("Y-m-d H:i:s");
319
- $this->Version = DUPLICATOR_VERSION;
320
- $this->VersionOS = defined('PHP_OS') ? PHP_OS : 'unknown';
321
- $this->VersionWP = $wp_version;
322
- $this->VersionPHP = phpversion();
323
- $this->VersionDB = esc_html($dbversion);
324
- $this->Name = sanitize_text_field($name);
325
- $this->Hash = $this->makeHash();
326
- $this->NameHash = "{$this->Name}_{$this->Hash}";
327
-
328
- $this->Notes = DUP_Util::escSanitizeTextAreaField($post['package-notes']);
329
- //ARCHIVE
330
- $this->Archive->PackDir = rtrim(DUPLICATOR_WPROOTPATH, '/');
331
- $this->Archive->Format = 'ZIP';
332
- $this->Archive->FilterOn = isset($post['filter-on']) ? 1 : 0;
333
- $this->Archive->ExportOnlyDB = isset($post['export-onlydb']) ? 1 : 0;
334
- $this->Archive->FilterDirs = DUP_Util::escSanitizeTextAreaField($filter_dirs);
335
- $this->Archive->FilterFiles = DUP_Util::escSanitizeTextAreaField($filter_files);
336
- $this->Archive->FilterExts = str_replace(array('.', ' '), '', DUP_Util::escSanitizeTextAreaField($filter_exts));
337
- //INSTALLER
338
- $this->Installer->OptsDBHost = DUP_Util::escSanitizeTextField($post['dbhost']);
339
- $this->Installer->OptsDBPort = DUP_Util::escSanitizeTextField($post['dbport']);
340
- $this->Installer->OptsDBName = DUP_Util::escSanitizeTextField($post['dbname']);
341
- $this->Installer->OptsDBUser = DUP_Util::escSanitizeTextField($post['dbuser']);
342
- //DATABASE
343
- $this->Database->FilterOn = isset($post['dbfilter-on']) ? 1 : 0;
344
- $this->Database->FilterTables = esc_html($tablelist);
345
- $this->Database->Compatible = $compatlist;
346
- $this->Database->Comments = esc_html($dbcomments);
347
-
348
- update_option(self::OPT_ACTIVE, $this);
349
- }
350
- }
351
-
352
- /**
353
- * Save any property of this class through reflection
354
- *
355
- * @param $property A valid public property in this class
356
- * @param $value The value for the new dynamic property
357
- *
358
- * @return null
359
- */
360
- public function saveActiveItem($property, $value)
361
- {
362
- $package = self::getActive();
363
-
364
- $reflectionClass = new ReflectionClass($package);
365
- $reflectionClass->getProperty($property)->setValue($package, $value);
366
- update_option(self::OPT_ACTIVE, $package);
367
- }
368
-
369
-
370
-
371
- /**
372
- * Sets the status to log the state of the build
373
- *
374
- * @param $status The status level for where the package is
375
- *
376
- * @return void
377
- */
378
- public function setStatus($status)
379
- {
380
- global $wpdb;
381
-
382
- $packageObj = serialize($this);
383
-
384
- if (!isset($status)) {
385
- DUP_Log::Error("Package SetStatus did not receive a proper code.");
386
- }
387
-
388
- if (!$packageObj) {
389
- DUP_Log::Error("Package SetStatus was unable to serialize package object while updating record.");
390
- }
391
-
392
- $wpdb->flush();
393
- $table = $wpdb->prefix."duplicator_packages";
394
- $sql = "UPDATE `{$table}` SET status = {$status}, package = '{$packageObj}' WHERE ID = {$this->ID}";
395
- $wpdb->query($sql);
396
- }
397
-
398
- /**
399
- * Does a hash already exisit
400
- *
401
- * @param string $hash An existing hash value
402
- *
403
- * @return int Returns 0 if no hash is found, if found returns the table ID
404
- */
405
- public function getHashKey($hash)
406
- {
407
- global $wpdb;
408
-
409
- $table = $wpdb->prefix."duplicator_packages";
410
- $qry = $wpdb->get_row("SELECT ID, hash FROM `{$table}` WHERE hash = '{$hash}'");
411
- if (strlen($qry->hash) == 0) {
412
- return 0;
413
- } else {
414
- return $qry->ID;
415
- }
416
- }
417
-
418
- /**
419
- * Makes the hashkey for the package files
420
- * Rare cases will need to fall back to GUID
421
- *
422
- * @return string Returns a unique hashkey
423
- */
424
- public function makeHash()
425
- {
426
- try {
427
- if (function_exists('random_bytes') && DUP_Util::$on_php_53_plus) {
428
- return bin2hex(random_bytes(8)).mt_rand(1000, 9999).date("ymdHis");
429
- } else {
430
- return DUP_Util::GUIDv4();
431
- }
432
- } catch (Exception $exc) {
433
- return DUP_Util::GUIDv4();
434
- }
435
- }
436
-
437
- /**
438
- * Gets the active package which is defined as the package that was lasted saved.
439
- * Do to cache issues with the built in WP function get_option moved call to a direct DB call.
440
- *
441
- * @see DUP_Package::saveActive
442
- *
443
- * @return obj A copy of the DUP_Package object
444
- */
445
- public static function getActive()
446
- {
447
- global $wpdb;
448
-
449
- $obj = new DUP_Package();
450
- $row = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM `{$wpdb->options}` WHERE option_name = %s LIMIT 1", self::OPT_ACTIVE));
451
- if (is_object($row)) {
452
- $obj = @unserialize($row->option_value);
453
- }
454
- //Incase unserilaize fails
455
- $obj = (is_object($obj)) ? $obj : new DUP_Package();
456
-
457
- return $obj;
458
- }
459
-
460
- /**
461
- * Gets the Package by ID
462
- *
463
- * @param int $id A valid package id form the duplicator_packages table
464
- *
465
- * @return obj A copy of the DUP_Package object
466
- */
467
- public static function getByID($id)
468
- {
469
-
470
- global $wpdb;
471
- $obj = new DUP_Package();
472
-
473
- $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM `{$wpdb->prefix}duplicator_packages` WHERE ID = %s", $id));
474
- if (is_object($row)) {
475
- $obj = @unserialize($row->package);
476
- $obj->Status = $row->status;
477
- }
478
- //Incase unserilaize fails
479
- $obj = (is_object($obj)) ? $obj : null;
480
- return $obj;
481
- }
482
-
483
- /**
484
- * Gets a default name for the package
485
- *
486
- * @return string A default package name such as 20170218_blogname
487
- */
488
- public static function getDefaultName($preDate = true)
489
- {
490
- //Remove specail_chars from final result
491
- $special_chars = array(".", "-");
492
- $name = ($preDate)
493
- ? date('Ymd') . '_' . sanitize_title(get_bloginfo('name', 'display'))
494
- : sanitize_title(get_bloginfo('name', 'display')) . '_' . date('Ymd');
495
- $name = substr(sanitize_file_name($name), 0, 40);
496
- $name = str_replace($special_chars, '', $name);
497
- return $name;
498
- }
499
-
500
- /**
501
- * Cleanup all tmp files
502
- *
503
- * @param all empty all contents
504
- *
505
- * @return null
506
- */
507
- public static function tempFileCleanup($all = false)
508
- {
509
- //Delete all files now
510
- if ($all) {
511
- $dir = DUPLICATOR_SSDIR_PATH_TMP."/*";
512
- foreach (glob($dir) as $file) {
513
- @unlink($file);
514
- }
515
- }
516
- //Remove scan files that are 24 hours old
517
- else {
518
- $dir = DUPLICATOR_SSDIR_PATH_TMP."/*_scan.json";
519
- foreach (glob($dir) as $file) {
520
- if (filemtime($file) <= time() - 86400) {
521
- @unlink($file);
522
- }
523
- }
524
- }
525
- }
526
-
527
- /**
528
- * Provides various date formats
529
- *
530
- * @param $date The date to format
531
- * @param $format Various date formats to apply
532
- *
533
- * @return a formated date based on the $format
534
- */
535
- public static function getCreatedDateFormat($date, $format = 1)
536
- {
537
- $date = new DateTime($date);
538
- switch ($format) {
539
- //YEAR
540
- case 1: return $date->format('Y-m-d H:i');
541
- break;
542
- case 2: return $date->format('Y-m-d H:i:s');
543
- break;
544
- case 3: return $date->format('y-m-d H:i');
545
- break;
546
- case 4: return $date->format('y-m-d H:i:s');
547
- break;
548
- //MONTH
549
- case 5: return $date->format('m-d-Y H:i');
550
- break;
551
- case 6: return $date->format('m-d-Y H:i:s');
552
- break;
553
- case 7: return $date->format('m-d-y H:i');
554
- break;
555
- case 8: return $date->format('m-d-y H:i:s');
556
- break;
557
- //DAY
558
- case 9: return $date->format('d-m-Y H:i');
559
- break;
560
- case 10: return $date->format('d-m-Y H:i:s');
561
- break;
562
- case 11: return $date->format('d-m-y H:i');
563
- break;
564
- case 12: return $date->format('d-m-y H:i:s');
565
- break;
566
- default :
567
- return $date->format('Y-m-d H:i');
568
- }
569
- }
570
-
571
- /**
572
- * Cleans up all the tmp files as part of the package build process
573
- */
574
- private function buildCleanup()
575
- {
576
-
577
- $files = DUP_Util::listFiles(DUPLICATOR_SSDIR_PATH_TMP);
578
- $newPath = DUPLICATOR_SSDIR_PATH;
579
-
580
- if (function_exists('rename')) {
581
- foreach ($files as $file) {
582
- $name = basename($file);
583
- if (strstr($name, $this->NameHash)) {
584
- rename($file, "{$newPath}/{$name}");
585
- }
586
- }
587
- } else {
588
- foreach ($files as $file) {
589
- $name = basename($file);
590
- if (strstr($name, $this->NameHash)) {
591
- copy($file, "{$newPath}/{$name}");
592
- @unlink($file);
593
- }
594
- }
595
- }
596
- }
597
-
598
-
599
-
600
-
601
- }
602
- ?>
1
+ <?php
2
+ if (!defined('DUPLICATOR_VERSION')) exit; // Exit if accessed directly
3
+
4
+ require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.php');
5
+ require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
6
+ require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.installer.php');
7
+ require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.database.php');
8
+
9
+ final class DUP_PackageStatus
10
+ {
11
+
12
+ private function __construct()
13
+ {
14
+
15
+ }
16
+ const START = 10;
17
+ const DBSTART = 20;
18
+ const DBDONE = 30;
19
+ const ARCSTART = 40;
20
+ const ARCDONE = 50;
21
+ const COMPLETE = 100;
22
+
23
+ }
24
+
25
+ final class DUP_PackageType
26
+ {
27
+ const MANUAL = 0;
28
+ const SCHEDULED = 1;
29
+
30
+ }
31
+
32
+ /**
33
+ * Class used to store and process all Package logic
34
+ *
35
+ * @package Duplicator\classes
36
+ */
37
+ class DUP_Package
38
+ {
39
+ const OPT_ACTIVE = 'duplicator_package_active';
40
+
41
+ //Properties
42
+ public $Created;
43
+ public $Version;
44
+ public $VersionWP;
45
+ public $VersionDB;
46
+ public $VersionPHP;
47
+ public $VersionOS;
48
+ public $ID;
49
+ public $Name;
50
+ public $Hash;
51
+ public $NameHash;
52
+ public $Type;
53
+ public $Notes;
54
+ public $StorePath;
55
+ public $StoreURL;
56
+ public $ScanFile;
57
+ public $Runtime;
58
+ public $ExeSize;
59
+ public $ZipSize;
60
+ public $Status;
61
+ public $WPUser;
62
+ //Objects
63
+ public $Archive;
64
+ public $Installer;
65
+ public $Database;
66
+
67
+ /**
68
+ * Manages the Package Process
69
+ */
70
+ function __construct()
71
+ {
72
+
73
+ $this->ID = null;
74
+ $this->Version = DUPLICATOR_VERSION;
75
+
76
+ $this->Type = DUP_PackageType::MANUAL;
77
+ $this->Name = self::getDefaultName();
78
+ $this->Notes = null;
79
+ $this->StoreURL = DUP_Util::snapshotURL();
80
+ $this->StorePath = DUPLICATOR_SSDIR_PATH_TMP;
81
+ $this->Database = new DUP_Database($this);
82
+ $this->Archive = new DUP_Archive($this);
83
+ $this->Installer = new DUP_Installer($this);
84
+ }
85
+
86
+ /**
87
+ * Generates a json scan report
88
+ *
89
+ * @return array of scan results
90
+ *
91
+ * @notes: Testing = /wp-admin/admin-ajax.php?action=duplicator_package_scan
92
+ */
93
+ public function runScanner()
94
+ {
95
+ $timerStart = DUP_Util::getMicrotime();
96
+ $report = array();
97
+ $this->ScanFile = "{$this->NameHash}_scan.json";
98
+
99
+ $report['RPT']['ScanTime'] = "0";
100
+ $report['RPT']['ScanFile'] = $this->ScanFile;
101
+
102
+ //SERVER
103
+ $srv = DUP_Server::getChecks();
104
+ $report['SRV'] = $srv['SRV'];
105
+
106
+ //FILES
107
+ $this->Archive->getScannerData();
108
+ $dirCount = count($this->Archive->Dirs);
109
+ $fileCount = count($this->Archive->Files);
110
+ $fullCount = $dirCount + $fileCount;
111
+
112
+ $report['ARC']['Size'] = DUP_Util::byteSize($this->Archive->Size) or "unknown";
113
+ $report['ARC']['DirCount'] = number_format($dirCount);
114
+ $report['ARC']['FileCount'] = number_format($fileCount);
115
+ $report['ARC']['FullCount'] = number_format($fullCount);
116
+ $report['ARC']['FilterDirsAll'] = $this->Archive->FilterDirsAll;
117
+ $report['ARC']['FilterFilesAll'] = $this->Archive->FilterFilesAll;
118
+ $report['ARC']['FilterExtsAll'] = $this->Archive->FilterExtsAll;
119
+ $report['ARC']['FilterInfo'] = $this->Archive->FilterInfo;
120
+ $report['ARC']['RecursiveLinks'] = $this->Archive->RecursiveLinks;
121
+ $report['ARC']['UnreadableItems'] = array_merge($this->Archive->FilterInfo->Files->Unreadable,$this->Archive->FilterInfo->Dirs->Unreadable);
122
+ $report['ARC']['Status']['Size'] = ($this->Archive->Size > DUPLICATOR_SCAN_SIZE_DEFAULT) ? 'Warn' : 'Good';
123
+ $report['ARC']['Status']['Names'] = (count($this->Archive->FilterInfo->Files->Warning) + count($this->Archive->FilterInfo->Dirs->Warning)) ? 'Warn' : 'Good';
124
+ $report['ARC']['Status']['UnreadableItems'] = !empty($this->Archive->RecursiveLinks) || !empty($report['ARC']['UnreadableItems'])? 'Warn' : 'Good';
125
+
126
+ //$report['ARC']['Status']['Big'] = count($this->Archive->FilterInfo->Files->Size) ? 'Warn' : 'Good';
127
+ $report['ARC']['Dirs'] = $this->Archive->Dirs;
128
+ $report['ARC']['Files'] = $this->Archive->Files;
129
+ $report['ARC']['Status']['AddonSites'] = count($this->Archive->FilterInfo->Dirs->AddonSites) ? 'Warn' : 'Good';
130
+
131
+
132
+
133
+ //DATABASE
134
+ $db = $this->Database->getScannerData();
135
+ $report['DB'] = $db;
136
+
137
+ $warnings = array(
138
+ $report['SRV']['PHP']['ALL'],
139
+ $report['SRV']['WP']['ALL'],
140
+ $report['ARC']['Status']['Size'],
141
+ $report['ARC']['Status']['Names'],
142
+ $db['Status']['DB_Size'],
143
+ $db['Status']['DB_Rows']);
144
+
145
+ //array_count_values will throw a warning message if it has null values,
146
+ //so lets replace all nulls with empty string
147
+ foreach ($warnings as $i => $value) {
148
+ if (is_null($value)) {
149
+ $warnings[$i] = '';
150
+ }
151
+ }
152
+
153
+ $warn_counts = is_array($warnings) ? array_count_values($warnings) : 0;
154
+ $report['RPT']['Warnings'] = is_null($warn_counts['Warn']) ? 0 : $warn_counts['Warn'];
155
+ $report['RPT']['Success'] = is_null($warn_counts['Good']) ? 0 : $warn_counts['Good'];
156
+ $report['RPT']['ScanTime'] = DUP_Util::elapsedTime(DUP_Util::getMicrotime(), $timerStart);
157
+ $fp = fopen(DUPLICATOR_SSDIR_PATH_TMP."/{$this->ScanFile}", 'w');
158
+
159
+
160
+ fwrite($fp, json_encode($report));
161
+ fclose($fp);
162
+
163
+ return $report;
164
+ }
165
+
166
+ /**
167
+ * Starts the package build process
168
+ *
169
+ * @return obj Returns a DUP_Package object
170
+ */
171
+ public function runBuild()
172
+ {
173
+ global $wp_version;
174
+ global $wpdb;
175
+ global $current_user;
176
+
177
+ $timerStart = DUP_Util::getMicrotime();
178
+
179
+ $this->Archive->File = "{$this->NameHash}_archive.zip";
180
+ $this->Installer->File = "{$this->NameHash}_installer.php";
181
+ $this->Database->File = "{$this->NameHash}_database.sql";
182
+ $this->WPUser = isset($current_user->user_login) ? $current_user->user_login : 'unknown';
183
+
184
+ //START LOGGING
185
+ DUP_Log::Open($this->NameHash);
186
+ $php_max_time = @ini_get("max_execution_time");
187
+ $php_max_memory = @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY);
188
+ $php_max_time = ($php_max_time == 0) ? "(0) no time limit imposed" : "[{$php_max_time}] not allowed";
189
+ $php_max_memory = ($php_max_memory === false) ? "Unabled to set php memory_limit" : DUPLICATOR_PHP_MAX_MEMORY." ({$php_max_memory} default)";
190
+
191
+ $info = "********************************************************************************\n";
192
+ $info .= "DUPLICATOR-LITE PACKAGE-LOG: ".@date(get_option('date_format')." ".get_option('time_format'))."\n";
193
+ $info .= "NOTICE: Do NOT post to public sites or forums \n";
194
+ $info .= "********************************************************************************\n";
195
+ $info .= "VERSION:\t".DUPLICATOR_VERSION."\n";
196
+ $info .= "WORDPRESS:\t{$wp_version}\n";
197
+ $info .= "PHP INFO:\t".phpversion().' | '.'SAPI: '.php_sapi_name()."\n";
198
+ $info .= "SERVER:\t\t{$_SERVER['SERVER_SOFTWARE']} \n";
199
+ $info .= "PHP TIME LIMIT: {$php_max_time} \n";
200
+ $info .= "PHP MAX MEMORY: {$php_max_memory} \n";
201
+ $info .= "MEMORY STACK: ".DUP_Server::getPHPMemory();
202
+ DUP_Log::Info($info);
203
+ $info = null;
204
+
205
+ //CREATE DB RECORD
206
+ $packageObj = serialize($this);
207
+ if (!$packageObj) {
208
+ DUP_Log::Error("Unable to serialize pacakge object while building record.");
209
+ }
210
+
211
+ $this->ID = $this->getHashKey($this->Hash);
212
+
213
+ if ($this->ID != 0) {
214
+ $this->setStatus(DUP_PackageStatus::START);
215
+ } else {
216
+ $results = $wpdb->insert($wpdb->prefix."duplicator_packages",
217
+ array(
218
+ 'name' => $this->Name,
219
+ 'hash' => $this->Hash,
220
+ 'status' => DUP_PackageStatus::START,
221
+ 'created' => current_time('mysql', get_option('gmt_offset', 1)),
222
+ 'owner' => isset($current_user->user_login) ? $current_user->user_login : 'unknown',
223
+ 'package' => $packageObj)
224
+ );
225
+ if ($results === false) {
226
+
227
+ $wpdb->print_error();
228
+ DUP_Log::Error("Duplicator is unable to insert a package record into the database table.", "'{$wpdb->last_error}'");
229
+ }
230
+ $this->ID = $wpdb->insert_id;
231
+ }
232
+
233
+ //START BUILD
234
+ //PHPs serialze method will return the object, but the ID above is not passed
235
+ //for one reason or another so passing the object back in seems to do the trick
236
+ $this->Database->build($this);
237
+ $this->Archive->build($this);
238
+ $this->Installer->build($this);
239
+
240
+ //INTEGRITY CHECKS
241
+ DUP_Log::Info("\n********************************************************************************");
242
+ DUP_Log::Info("INTEGRITY CHECKS:");
243
+ DUP_Log::Info("********************************************************************************");
244
+ $dbSizeRead = DUP_Util::byteSize($this->Database->Size);
245
+ $zipSizeRead = DUP_Util::byteSize($this->Archive->Size);
246
+ $exeSizeRead = DUP_Util::byteSize($this->Installer->Size);
247
+
248
+ DUP_Log::Info("SQL File: {$dbSizeRead}");
249
+ DUP_Log::Info("Installer File: {$exeSizeRead}");
250
+ DUP_Log::Info("Archive File: {$zipSizeRead} ");
251
+
252
+ if (!($this->Archive->Size && $this->Database->Size && $this->Installer->Size)) {
253
+ DUP_Log::Error("A required file contains zero bytes.", "Archive Size: {$zipSizeRead} | SQL Size: {$dbSizeRead} | Installer Size: {$exeSizeRead}");
254
+ }
255
+
256
+ //Validate SQL files completed
257
+ $sql_tmp_path = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP.'/'.$this->Database->File);
258
+ $sql_complete_txt = DUP_Util::tailFile($sql_tmp_path, 3);
259
+ if (!strstr($sql_complete_txt, 'DUPLICATOR_MYSQLDUMP_EOF')) {
260
+ DUP_Log::Error("ERROR: SQL file not complete. The end of file marker was not found. Please try to re-create the package.");
261
+ }
262
+
263
+ $timerEnd = DUP_Util::getMicrotime();
264
+ $timerSum = DUP_Util::elapsedTime($timerEnd, $timerStart);
265
+
266
+ $this->Runtime = $timerSum;
267
+ $this->ExeSize = $exeSizeRead;
268
+ $this->ZipSize = $zipSizeRead;
269
+
270
+ $this->buildCleanup();
271
+
272
+ //FINAL REPORT
273
+ $info = "\n********************************************************************************\n";
274
+ $info .= "RECORD ID:[{$this->ID}]\n";
275
+ $info .= "TOTAL PROCESS RUNTIME: {$timerSum}\n";
276
+ $info .= "PEAK PHP MEMORY USED: ".DUP_Server::getPHPMemory(true)."\n";
277
+ $info .= "DONE PROCESSING => {$this->Name} ".@date(get_option('date_format')." ".get_option('time_format'))."\n";
278
+
279
+ DUP_Log::Info($info);
280
+ DUP_Log::Close();
281
+
282
+ $this->setStatus(DUP_PackageStatus::COMPLETE);
283
+ return $this;
284
+ }
285
+
286
+ /**
287
+ * Saves the active options associted with the active(latest) package.
288
+ *
289
+ * @see DUP_Package::getActive
290
+ *
291
+ * @param $_POST $post The Post server object
292
+ *
293
+ * @return null
294
+ */
295
+ public function saveActive($post = null)
296
+ {
297
+ global $wp_version;
298
+
299
+ if (isset($post)) {
300
+ $post = stripslashes_deep($post);
301
+
302
+ $name = ( isset($post['package-name']) && !empty($post['package-name'])) ? $post['package-name'] : self::getDefaultName();
303
+ $name = substr(sanitize_file_name($name), 0, 40);
304
+ $name = str_replace(array('.', '-', ';', ':', "'", '"'), '', $name);
305
+
306
+ $filter_dirs = isset($post['filter-dirs']) ? $this->Archive->parseDirectoryFilter($post['filter-dirs']) : '';
307
+ $filter_files = isset($post['filter-files']) ? $this->Archive->parseFileFilter($post['filter-files']) : '';
308
+ $filter_exts = isset($post['filter-exts']) ? $this->Archive->parseExtensionFilter($post['filter-exts']) : '';
309
+ $tablelist = isset($post['dbtables']) ? implode(',', $post['dbtables']) : '';
310
+ $compatlist = isset($post['dbcompat']) ? implode(',', $post['dbcompat']) : '';
311
+ $dbversion = DUP_DB::getVersion();
312
+ $dbversion = is_null($dbversion) ? '- unknown -' : $dbversion;
313
+ $dbcomments = DUP_DB::getVariable('version_comment');
314
+ $dbcomments = is_null($dbcomments) ? '- unknown -' : $dbcomments;
315
+
316
+
317
+ //PACKAGE
318
+ $this->Created = date("Y-m-d H:i:s");
319
+ $this->Version = DUPLICATOR_VERSION;
320
+ $this->VersionOS = defined('PHP_OS') ? PHP_OS : 'unknown';
321
+ $this->VersionWP = $wp_version;
322
+ $this->VersionPHP = phpversion();
323
+ $this->VersionDB = esc_html($dbversion);
324
+ $this->Name = sanitize_text_field($name);
325
+ $this->Hash = $this->makeHash();
326
+ $this->NameHash = "{$this->Name}_{$this->Hash}";
327
+
328
+ $this->Notes = DUP_Util::escSanitizeTextAreaField($post['package-notes']);
329
+ //ARCHIVE
330
+ $this->Archive->PackDir = rtrim(DUPLICATOR_WPROOTPATH, '/');
331
+ $this->Archive->Format = 'ZIP';
332
+ $this->Archive->FilterOn = isset($post['filter-on']) ? 1 : 0;
333
+ $this->Archive->ExportOnlyDB = isset($post['export-onlydb']) ? 1 : 0;
334
+ $this->Archive->FilterDirs = DUP_Util::escSanitizeTextAreaField($filter_dirs);
335
+ $this->Archive->FilterFiles = DUP_Util::escSanitizeTextAreaField($filter_files);
336
+ $this->Archive->FilterExts = str_replace(array('.', ' '), '', DUP_Util::escSanitizeTextAreaField($filter_exts));
337
+ //INSTALLER
338
+ $this->Installer->OptsDBHost = DUP_Util::escSanitizeTextField($post['dbhost']);
339
+ $this->Installer->OptsDBPort = DUP_Util::escSanitizeTextField($post['dbport']);
340
+ $this->Installer->OptsDBName = DUP_Util::escSanitizeTextField($post['dbname']);
341
+ $this->Installer->OptsDBUser = DUP_Util::escSanitizeTextField($post['dbuser']);
342
+ //DATABASE
343
+ $this->Database->FilterOn = isset($post['dbfilter-on']) ? 1 : 0;
344
+ $this->Database->FilterTables = esc_html($tablelist);
345
+ $this->Database->Compatible = $compatlist;
346
+ $this->Database->Comments = esc_html($dbcomments);
347
+
348
+ update_option(self::OPT_ACTIVE, $this);
349
+ }
350
+ }
351
+
352
+ /**
353
+ * Save any property of this class through reflection
354
+ *
355
+ * @param $property A valid public property in this class
356
+ * @param $value The value for the new dynamic property
357
+ *
358
+ * @return null
359
+ */
360
+ public function saveActiveItem($property, $value)
361
+ {
362
+ $package = self::getActive();
363
+
364
+ $reflectionClass = new ReflectionClass($package);
365
+ $reflectionClass->getProperty($property)->setValue($package, $value);
366
+ update_option(self::OPT_ACTIVE, $package);
367
+ }
368
+
369
+ /**
370
+ * Sets the status to log the state of the build
371
+ *
372
+ * @param $status The status level for where the package is
373
+ *
374
+ * @return void
375
+ */
376
+ public function setStatus($status)
377
+ {
378
+ global $wpdb;
379
+
380
+ $packageObj = serialize($this);
381
+
382
+ if (!isset($status)) {
383
+ DUP_Log::Error("Package SetStatus did not receive a proper code.");
384
+ }
385
+
386
+ if (!$packageObj) {
387
+ DUP_Log::Error("Package SetStatus was unable to serialize package object while updating record.");
388
+ }
389
+
390
+ $wpdb->flush();
391
+ $table = $wpdb->prefix."duplicator_packages";
392
+ $sql = "UPDATE `{$table}` SET status = {$status}, package = '{$packageObj}' WHERE ID = {$this->ID}";
393
+ $wpdb->query($sql);
394
+ }
395
+
396
+ /**
397
+ * Does a hash already exist
398
+ *
399
+ * @param string $hash An existing hash value
400
+ *
401
+ * @return int Returns 0 if no hash is found, if found returns the table ID
402
+ */
403
+ public function getHashKey($hash)
404
+ {
405
+ global $wpdb;
406
+
407
+ $table = $wpdb->prefix."duplicator_packages";
408
+ $qry = $wpdb->get_row("SELECT ID, hash FROM `{$table}` WHERE hash = '{$hash}'");
409
+ if (strlen($qry->hash) == 0) {
410
+ return 0;
411
+ } else {
412
+ return $qry->ID;
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Makes the hashkey for the package files
418
+ * Rare cases will need to fall back to GUID
419
+ *
420
+ * @return string Returns a unique hashkey
421
+ */
422
+ public function makeHash()
423
+ {
424
+ try {
425
+ if (function_exists('random_bytes') && DUP_Util::$on_php_53_plus) {
426
+ return bin2hex(random_bytes(8)).mt_rand(1000, 9999).date("ymdHis");
427
+ } else {
428
+ return DUP_Util::GUIDv4();
429
+ }
430
+ } catch (Exception $exc) {
431
+ return DUP_Util::GUIDv4();
432
+ }
433
+ }
434
+
435
+ /**
436
+ * Gets the active package which is defined as the package that was lasted saved.
437
+ * Do to cache issues with the built in WP function get_option moved call to a direct DB call.
438
+ *
439
+ * @see DUP_Package::saveActive
440
+ *
441
+ * @return obj A copy of the DUP_Package object
442
+ */
443
+ public static function getActive()
444
+ {
445
+ global $wpdb;
446
+
447
+ $obj = new DUP_Package();
448
+ $row = $wpdb->get_row($wpdb->prepare("SELECT option_value FROM `{$wpdb->options}` WHERE option_name = %s LIMIT 1", self::OPT_ACTIVE));
449
+ if (is_object($row)) {
450
+ $obj = @unserialize($row->option_value);
451
+ }
452
+ //Incase unserilaize fails
453
+ $obj = (is_object($obj)) ? $obj : new DUP_Package();
454
+
455
+ return $obj;
456
+ }
457
+
458
+ /**
459
+ * Gets the Package by ID
460
+ *
461
+ * @param int $id A valid package id form the duplicator_packages table
462
+ *
463
+ * @return obj A copy of the DUP_Package object
464
+ */
465
+ public static function getByID($id)
466
+ {
467
+
468
+ global $wpdb;
469
+ $obj = new DUP_Package();
470
+
471
+ $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM `{$wpdb->prefix}duplicator_packages` WHERE ID = %s", $id));
472
+ if (is_object($row)) {
473
+ $obj = @unserialize($row->package);
474
+ $obj->Status = $row->status;
475
+ }
476
+ //Incase unserilaize fails
477
+ $obj = (is_object($obj)) ? $obj : null;
478
+ return $obj;
479
+ }
480
+
481
+ /**
482
+ * Gets a default name for the package
483
+ *
484
+ * @return string A default package name such as 20170218_blogname
485
+ */
486
+ public static function getDefaultName($preDate = true)
487
+ {
488
+ //Remove specail_chars from final result
489
+ $special_chars = array(".", "-");
490
+ $name = ($preDate)
491
+ ? date('Ymd') . '_' . sanitize_title(get_bloginfo('name', 'display'))
492
+ : sanitize_title(get_bloginfo('name', 'display')) . '_' . date('Ymd');
493
+ $name = substr(sanitize_file_name($name), 0, 40);
494
+ $name = str_replace($special_chars, '', $name);
495
+ return $name;
496
+ }
497
+
498
+ /**
499
+ * Cleanup all tmp files
500
+ *
501
+ * @param all empty all contents
502
+ *
503
+ * @return null
504
+ */
505
+ public static function tempFileCleanup($all = false)
506
+ {
507
+ //Delete all files now
508
+ if ($all) {
509
+ $dir = DUPLICATOR_SSDIR_PATH_TMP."/*";
510
+ foreach (glob($dir) as $file) {
511
+ @unlink($file);
512
+ }
513
+ }
514
+ //Remove scan files that are 24 hours old
515
+ else {
516
+ $dir = DUPLICATOR_SSDIR_PATH_TMP."/*_scan.json";
517
+ foreach (glob($dir) as $file) {
518
+ if (filemtime($file) <= time() - 86400) {
519
+ @unlink($file);
520
+ }
521
+ }
522
+ }
523
+ }
524
+
525
+ /**
526
+ * Provides various date formats
527
+ *
528
+ * @param $date The date to format
529
+ * @param $format Various date formats to apply
530
+ *
531
+ * @return a formated date based on the $format
532
+ */
533
+ public static function getCreatedDateFormat($date, $format = 1)
534
+ {
535
+ $date = new DateTime($date);
536
+ switch ($format) {
537
+ //YEAR
538
+ case 1: return $date->format('Y-m-d H:i');
539
+ break;
540
+ case 2: return $date->format('Y-m-d H:i:s');
541
+ break;
542
+ case 3: return $date->format('y-m-d H:i');
543
+ break;
544
+ case 4: return $date->format('y-m-d H:i:s');
545
+ break;
546
+ //MONTH
547
+ case 5: return $date->format('m-d-Y H:i');
548
+ break;
549
+ case 6: return $date->format('m-d-Y H:i:s');
550
+ break;
551
+ case 7: return $date->format('m-d-y H:i');
552
+ break;
553
+ case 8: return $date->format('m-d-y H:i:s');
554
+ break;
555
+ //DAY
556
+ case 9: return $date->format('d-m-Y H:i');
557
+ break;
558
+ case 10: return $date->format('d-m-Y H:i:s');
559
+ break;
560
+ case 11: return $date->format('d-m-y H:i');
561
+ break;
562
+ case 12: return $date->format('d-m-y H:i:s');
563
+ break;
564
+ default :
565
+ return $date->format('Y-m-d H:i');
566
+ }
567
+ }
568
+
569
+ /**
570
+ * Cleans up all the tmp files as part of the package build process
571
+ */
572
+ private function buildCleanup()
573
+ {
574
+
575
+ $files = DUP_Util::listFiles(DUPLICATOR_SSDIR_PATH_TMP);
576
+ $newPath = DUPLICATOR_SSDIR_PATH;
577
+
578
+ if (function_exists('rename')) {
579
+ foreach ($files as $file) {
580
+ $name = basename($file);
581
+ if (strstr($name, $this->NameHash)) {
582
+ rename($file, "{$newPath}/{$name}");
583
+ }
584
+ }
585
+ } else {
586
+ foreach ($files as $file) {
587
+ $name = basename($file);
588
+ if (strstr($name, $this->NameHash)) {
589
+ copy($file, "{$newPath}/{$name}");
590
+ @unlink($file);
591
+ }
592
+ }
593
+ }
594
+ }
595
+
596
+
597
+
598
+
599
+ }
600
+ ?>
 
 
ctrls/ctrl.package.php CHANGED
@@ -1,214 +1,214 @@
1
- <?php
2
-
3
- require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
4
- require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.scancheck.php');
5
- require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.json.php');
6
- require_once(DUPLICATOR_PLUGIN_PATH . '/classes/package/class.pack.php');
7
-
8
- /**
9
- * DUPLICATOR_PACKAGE_SCAN
10
- * Returns a JSON scan report object which contains data about the system
11
- *
12
- * @return json JSON report object
13
- * @example to test: /wp-admin/admin-ajax.php?action=duplicator_package_scan
14
- */
15
- function duplicator_package_scan() {
16
-
17
- header('Content-Type: application/json;');
18
- DUP_Util::hasCapability('export');
19
-
20
- @set_time_limit(0);
21
- $errLevel = error_reporting();
22
- error_reporting(E_ERROR);
23
- DUP_Util::initSnapshotDirectory();
24
-
25
- $package = DUP_Package::getActive();
26
- $report = $package->runScanner();
27
-
28
- $package->saveActiveItem('ScanFile', $package->ScanFile);
29
- $json_response = DUP_JSON::safeEncode($report);
30
-
31
- DUP_Package::tempFileCleanup();
32
- error_reporting($errLevel);
33
- die($json_response);
34
- }
35
-
36
- /**
37
- * duplicator_package_build
38
- * Returns the package result status
39
- *
40
- * @return json JSON object of package results
41
- */
42
- function duplicator_package_build() {
43
-
44
- DUP_Util::hasCapability('export');
45
-
46
- check_ajax_referer( 'dup_package_build', 'nonce');
47
-
48
- header('Content-Type: application/json');
49
-
50
- @set_time_limit(0);
51
- $errLevel = error_reporting();
52
- error_reporting(E_ERROR);
53
- DUP_Util::initSnapshotDirectory();
54
-
55
- $Package = DUP_Package::getActive();
56
-
57
- if (!is_readable(DUPLICATOR_SSDIR_PATH_TMP . "/{$Package->ScanFile}")) {
58
- die("The scan result file was not found. Please run the scan step before building the package.");
59
- }
60
-
61
- $Package->runBuild();
62
-
63
- //JSON:Debug Response
64
- //Pass = 1, Warn = 2, Fail = 3
65
- $json = array();
66
- $json['Status'] = 1;
67
- $json['Package'] = $Package;
68
- $json['Runtime'] = $Package->Runtime;
69
- $json['ExeSize'] = $Package->ExeSize;
70
- $json['ZipSize'] = $Package->ZipSize;
71
- $json_response = json_encode($json);
72
-
73
- //Simulate a Host Build Interrupt
74
- //die(0);
75
-
76
- error_reporting($errLevel);
77
- die($json_response);
78
- }
79
-
80
- /**
81
- * DUPLICATOR_PACKAGE_DELETE
82
- * Deletes the files and database record entries
83
- *
84
- * @return json A JSON message about the action.
85
- * Use console.log to debug from client
86
- */
87
- function duplicator_package_delete() {
88
-
89
- DUP_Util::hasCapability('export');
90
- check_ajax_referer( 'package_list', 'nonce' );
91
-
92
- try {
93
- global $wpdb;
94
- $json = array();
95
- $post = stripslashes_deep($_POST);
96
- $tblName = $wpdb->prefix . 'duplicator_packages';
97
- $postIDs = isset($post['duplicator_delid']) ? $post['duplicator_delid'] : null;
98
- $list = explode(",", $postIDs);
99
- $delCount = 0;
100
-
101
- if ($postIDs != null) {
102
-
103
- foreach ($list as $id) {
104
-
105
- $getResult = $wpdb->get_results($wpdb->prepare("SELECT name, hash FROM `{$tblName}` WHERE id = %d", $id), ARRAY_A);
106
-
107
- if ($getResult) {
108
- $row = $getResult[0];
109
- $nameHash = "{$row['name']}_{$row['hash']}";
110
- $delResult = $wpdb->query($wpdb->prepare( "DELETE FROM `{$tblName}` WHERE id = %d", $id ));
111
- if ($delResult != 0) {
112
- //Perms
113
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_archive.zip"), 0644);
114
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_database.sql"), 0644);
115
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_installer.php"), 0644);
116
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_archive.zip"), 0644);
117
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_database.sql"), 0644);
118
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_installer.php"), 0644);
119
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_scan.json"), 0644);
120
- @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}.log"), 0644);
121
- //Remove
122
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_archive.zip"));
123
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_database.sql"));
124
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_installer.php"));
125
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_archive.zip"));
126
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_database.sql"));
127
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_installer.php"));
128
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_scan.json"));
129
- @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}.log"));
130
- //Unfinished Zip files
131
- $tmpZip = DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_archive.zip.*";
132
- if ($tmpZip !== false) {
133
- array_map('unlink', glob($tmpZip));
134
- }
135
- $delCount++;
136
- }
137
- }
138
- }
139
- }
140
-
141
- } catch (Exception $e) {
142
- $json['error'] = "{$e}";
143
- die(json_encode($json));
144
- }
145
-
146
- $json['ids'] = "{$postIDs}";
147
- $json['removed'] = $delCount;
148
- die(json_encode($json));
149
- }
150
-
151
-
152
-
153
- /**
154
- * Controller for Tools
155
- * @package Duplicator\ctrls
156
- */
157
- class DUP_CTRL_Package extends DUP_CTRL_Base
158
- {
159
- /**
160
- * Init this instance of the object
161
- */
162
- function __construct()
163
- {
164
- add_action('wp_ajax_DUP_CTRL_Package_addQuickFilters', array($this, 'addQuickFilters'));
165
- }
166
-
167
-
168
- /**
169
- * Removed all reserved installer files names
170
- *
171
- * @param string $_POST['dir_paths'] A semi-colon separated list of directory paths
172
- *
173
- * @return string Returns all of the active directory filters as a ";" separated string
174
- */
175
- public function addQuickFilters($post)
176
- {
177
- $post = $this->postParamMerge($post);
178
- check_ajax_referer($post['action'], 'nonce');
179
- $result = new DUP_CTRL_Result($this);
180
-
181
- try {
182
- //CONTROLLER LOGIC
183
- $package = DUP_Package::getActive();
184
-
185
- //DIRS
186
- $dir_filters = $package->Archive->FilterDirs.';' . $post['dir_paths'];
187
- $dir_filters = $package->Archive->parseDirectoryFilter($dir_filters);
188
- $changed = $package->Archive->saveActiveItem($package, 'FilterDirs', $dir_filters);
189
-
190
- //FILES
191
- $file_filters = $package->Archive->FilterFiles.';' . $post['file_paths'];
192
- $file_filters = $package->Archive->parseFileFilter($file_filters);
193
- $changed = $package->Archive->saveActiveItem($package, 'FilterFiles', $file_filters);
194
-
195
-
196
- $changed = $package->Archive->saveActiveItem($package, 'FilterOn', 1);
197
-
198
- //Result
199
- $package = DUP_Package::getActive();
200
- $payload['dirs-in'] = $post['dir_paths'];
201
- $payload['dir-out'] = $package->Archive->FilterDirs;
202
- $payload['files-in'] = $post['file_paths'];
203
- $payload['files-out'] = $package->Archive->FilterFiles;
204
-
205
- //RETURN RESULT
206
- $test = ($changed) ? DUP_CTRL_Status::SUCCESS : DUP_CTRL_Status::FAILED;
207
- $result->process($payload, $test);
208
-
209
- } catch (Exception $exc) {
210
- $result->processError($exc);
211
- }
212
- }
213
-
214
  }
1
+ <?php
2
+
3
+ require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
4
+ require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.scancheck.php');
5
+ require_once(DUPLICATOR_PLUGIN_PATH . '/classes/utilities/class.u.json.php');
6
+ require_once(DUPLICATOR_PLUGIN_PATH . '/classes/package/class.pack.php');
7
+
8
+ /**
9
+ * DUPLICATOR_PACKAGE_SCAN
10
+ * Returns a JSON scan report object which contains data about the system
11
+ *
12
+ * @return json JSON report object
13
+ * @example to test: /wp-admin/admin-ajax.php?action=duplicator_package_scan
14
+ */
15
+ function duplicator_package_scan() {
16
+
17
+ header('Content-Type: application/json;');
18
+ DUP_Util::hasCapability('export');
19
+
20
+ @set_time_limit(0);
21
+ $errLevel = error_reporting();
22
+ error_reporting(E_ERROR);
23
+ DUP_Util::initSnapshotDirectory();
24
+
25
+ $package = DUP_Package::getActive();
26
+ $report = $package->runScanner();
27
+
28
+ $package->saveActiveItem('ScanFile', $package->ScanFile);
29
+ $json_response = DUP_JSON::safeEncode($report);
30
+
31
+ DUP_Package::tempFileCleanup();
32
+ error_reporting($errLevel);
33
+ die($json_response);
34
+ }
35
+
36
+ /**
37
+ * duplicator_package_build
38
+ * Returns the package result status
39
+ *
40
+ * @return json JSON object of package results
41
+ */
42
+ function duplicator_package_build() {
43
+
44
+ DUP_Util::hasCapability('export');
45
+
46
+ check_ajax_referer( 'dup_package_build', 'nonce');
47
+
48
+ header('Content-Type: application/json');
49
+
50
+ @set_time_limit(0);
51
+ $errLevel = error_reporting();
52
+ error_reporting(E_ERROR);
53
+ DUP_Util::initSnapshotDirectory();
54
+
55
+ $Package = DUP_Package::getActive();
56
+
57
+ if (!is_readable(DUPLICATOR_SSDIR_PATH_TMP . "/{$Package->ScanFile}")) {
58
+ die("The scan result file was not found. Please run the scan step before building the package.");
59
+ }
60
+
61
+ $Package->runBuild();
62
+
63
+ //JSON:Debug Response
64
+ //Pass = 1, Warn = 2, Fail = 3
65
+ $json = array();
66
+ $json['Status'] = 1;
67
+ $json['Package'] = $Package;
68
+ $json['Runtime'] = $Package->Runtime;
69
+ $json['ExeSize'] = $Package->ExeSize;
70
+ $json['ZipSize'] = $Package->ZipSize;
71
+ $json_response = json_encode($json);
72
+
73
+ //Simulate a Host Build Interrupt
74
+ //die(0);
75
+
76
+ error_reporting($errLevel);
77
+ die($json_response);
78
+ }
79
+
80
+ /**
81
+ * DUPLICATOR_PACKAGE_DELETE
82
+ * Deletes the files and database record entries
83
+ *
84
+ * @return json A JSON message about the action.
85
+ * Use console.log to debug from client
86
+ */
87
+ function duplicator_package_delete() {
88
+
89
+ DUP_Util::hasCapability('export');
90
+ check_ajax_referer( 'package_list', 'nonce' );
91
+
92
+ try {
93
+ global $wpdb;
94
+ $json = array();
95
+ $post = stripslashes_deep($_POST);
96
+ $tblName = $wpdb->prefix . 'duplicator_packages';
97
+ $postIDs = isset($post['duplicator_delid']) ? $post['duplicator_delid'] : null;
98
+ $list = explode(",", $postIDs);
99
+ $delCount = 0;
100
+
101
+ if ($postIDs != null) {
102
+
103
+ foreach ($list as $id) {
104
+
105
+ $getResult = $wpdb->get_results($wpdb->prepare("SELECT name, hash FROM `{$tblName}` WHERE id = %d", $id), ARRAY_A);
106
+
107
+ if ($getResult) {
108
+ $row = $getResult[0];
109
+ $nameHash = "{$row['name']}_{$row['hash']}";
110
+ $delResult = $wpdb->query($wpdb->prepare( "DELETE FROM `{$tblName}` WHERE id = %d", $id ));
111
+ if ($delResult != 0) {
112
+ //Perms
113
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_archive.zip"), 0644);
114
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_database.sql"), 0644);
115
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_installer.php"), 0644);
116
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_archive.zip"), 0644);
117
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_database.sql"), 0644);
118
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_installer.php"), 0644);
119
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_scan.json"), 0644);
120
+ @chmod(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}.log"), 0644);
121
+ //Remove
122
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_archive.zip"));
123
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_database.sql"));
124
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_installer.php"));
125
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_archive.zip"));
126
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_database.sql"));
127
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_installer.php"));
128
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}_scan.json"));
129
+ @unlink(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH . "/{$nameHash}.log"));
130
+ //Unfinished Zip files
131
+ $tmpZip = DUPLICATOR_SSDIR_PATH_TMP . "/{$nameHash}_archive.zip.*";
132
+ if ($tmpZip !== false) {
133
+ array_map('unlink', glob($tmpZip));
134
+ }
135
+ $delCount++;
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ } catch (Exception $e) {
142
+ $json['error'] = "{$e}";
143
+ die(json_encode($json));
144
+ }
145
+
146
+ $json['ids'] = "{$postIDs}";
147
+ $json['removed'] = $delCount;
148
+ die(json_encode($json));
149
+ }
150
+
151
+
152
+
153
+ /**
154
+ * Controller for Tools
155
+ * @package Duplicator\ctrls
156
+ */
157
+ class DUP_CTRL_Package extends DUP_CTRL_Base
158
+ {
159
+ /**
160
+ * Init this instance of the object
161
+ */
162
+ function __construct()
163
+ {
164
+ add_action('wp_ajax_DUP_CTRL_Package_addQuickFilters', array($this, 'addQuickFilters'));
165
+ }
166
+
167
+
168
+ /**
169
+ * Removed all reserved installer files names
170
+ *
171
+ * @param string $_POST['dir_paths'] A semi-colon separated list of directory paths
172
+ *
173
+ * @return string Returns all of the active directory filters as a ";" separated string
174
+ */
175
+ public function addQuickFilters($post)
176
+ {
177
+ $post = $this->postParamMerge($post);
178
+ check_ajax_referer($post['action'], 'nonce');
179
+ $result = new DUP_CTRL_Result($this);
180
+
181
+ try {
182
+ //CONTROLLER LOGIC
183
+ $package = DUP_Package::getActive();
184
+
185
+ //DIRS
186
+ $dir_filters = $package->Archive->FilterDirs.';' . $post['dir_paths'];
187
+ $dir_filters = $package->Archive->parseDirectoryFilter($dir_filters);
188
+ $changed = $package->Archive->saveActiveItem($package, 'FilterDirs', $dir_filters);
189
+
190
+ //FILES
191
+ $file_filters = $package->Archive->FilterFiles.';' . $post['file_paths'];
192
+ $file_filters = $package->Archive->parseFileFilter($file_filters);
193
+ $changed = $package->Archive->saveActiveItem($package, 'FilterFiles', $file_filters);
194
+
195
+
196
+ $changed = $package->Archive->saveActiveItem($package, 'FilterOn', 1);
197
+
198
+ //Result
199
+ $package = DUP_Package::getActive();
200
+ $payload['dirs-in'] = $post['dir_paths'];
201
+ $payload['dir-out'] = $package->Archive->FilterDirs;
202
+ $payload['files-in'] = $post['file_paths'];
203
+ $payload['files-out'] = $package->Archive->FilterFiles;
204
+
205
+ //RETURN RESULT
206
+ $test = ($changed) ? DUP_CTRL_Status::SUCCESS : DUP_CTRL_Status::FAILED;
207
+ $result->process($payload, $test);
208
+
209
+ } catch (Exception $exc) {
210
+ $result->processError($exc);
211
+ }
212
+ }
213
+
214
  }
define.php CHANGED
@@ -2,7 +2,7 @@
2
  //Prevent directly browsing to the file
3
  if (function_exists('plugin_dir_url'))
4
  {
5
- define('DUPLICATOR_VERSION', '1.2.38');
6
  define('DUPLICATOR_HOMEPAGE', 'http://lifeinthegrid.com/labs/duplicator');
7
  define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
8
  define('DUPLICATOR_SITE_URL', get_site_url());
2
  //Prevent directly browsing to the file
3
  if (function_exists('plugin_dir_url'))
4
  {
5
+ define('DUPLICATOR_VERSION', '1.2.40');
6
  define('DUPLICATOR_HOMEPAGE', 'http://lifeinthegrid.com/labs/duplicator');
7
  define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
8
  define('DUPLICATOR_SITE_URL', get_site_url());
duplicator.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Duplicator
4
  Plugin URI: http://www.lifeinthegrid.com/duplicator/
5
  Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly.
6
- Version: 1.2.38
7
  Author: Snap Creek
8
  Author URI: http://www.snapcreek.com/duplicator/
9
  Text Domain: duplicator
3
  Plugin Name: Duplicator
4
  Plugin URI: http://www.lifeinthegrid.com/duplicator/
5
  Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly.
6
+ Version: 1.2.40
7
  Author: Snap Creek
8
  Author URI: http://www.snapcreek.com/duplicator/
9
  Text Domain: duplicator
readme.txt CHANGED
@@ -1,11 +1,10 @@
1
  === Duplicator - WordPress Migration Plugin ===
2
  Contributors: corylamleorg, bobriley
3
- Donate link: www.lifeinthegrid.com/partner
4
  Tags: migration, backup, restore, move, migrate, duplicate, transfer, clone, automate, copy site
5
  Requires at least: 4.0
6
  Tested up to: 4.9
7
  Requires PHP: 5.2.17
8
- Stable tag: 1.2.38
9
  License: GPLv2
10
 
11
  WordPress migration and backups are much easier with Duplicator! Clone, backup, move and transfer an entire site from one location to another.
@@ -24,6 +23,7 @@ Duplicator enables you to:
24
 
25
  * Move, migrate or clone a WordPress site between domains or hosts with **zero downtime**
26
  * Pull down a live site to localhost for development
 
27
  * Manually backup a WordPress site or parts of a site
28
  * Duplicate a live site to a staging area or vice versa
29
  * Bundle up an entire WordPress site for easy reuse or distribution
@@ -39,7 +39,7 @@ Duplicator lets you make your own pre-configured sites to eliminate rework. Ins
39
  Duplicator Pro takes Duplicator to the next level with features you'll really appreciate, such as:
40
 
41
  * Scheduled backups
42
- * Cloud Storage to Dropbox, Google Drive, Amazon S3 and FTP
43
  * Multi-threaded to support larger web sites &amp; databases
44
  * Migrate an entire multisite WordPress network in one shot
45
  * Install a multisite subsite as a new standalone website
1
  === Duplicator - WordPress Migration Plugin ===
2
  Contributors: corylamleorg, bobriley
 
3
  Tags: migration, backup, restore, move, migrate, duplicate, transfer, clone, automate, copy site
4
  Requires at least: 4.0
5
  Tested up to: 4.9
6
  Requires PHP: 5.2.17
7
+ Stable tag: 1.2.40
8
  License: GPLv2
9
 
10
  WordPress migration and backups are much easier with Duplicator! Clone, backup, move and transfer an entire site from one location to another.
23
 
24
  * Move, migrate or clone a WordPress site between domains or hosts with **zero downtime**
25
  * Pull down a live site to localhost for development
26
+ * Transfer a WordPress site from one host to another
27
  * Manually backup a WordPress site or parts of a site
28
  * Duplicate a live site to a staging area or vice versa
29
  * Bundle up an entire WordPress site for easy reuse or distribution
39
  Duplicator Pro takes Duplicator to the next level with features you'll really appreciate, such as:
40
 
41
  * Scheduled backups
42
+ * Cloud Storage to Dropbox, Google Drive, Microsoft OneDrive, Amazon S3 and FTP/SFTP
43
  * Multi-threaded to support larger web sites &amp; databases
44
  * Migrate an entire multisite WordPress network in one shot
45
  * Install a multisite subsite as a new standalone website
views/packages/main/s3.build.php CHANGED
@@ -296,6 +296,42 @@ TOOL BAR: STEPS -->
296
  </div>
297
  </div>
298
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  <br/><br/><br/>
300
  </div>
301
 
@@ -379,6 +415,19 @@ jQuery(document).ready(function($) {
379
  }
380
  };
381
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  //Page Init:
383
  Duplicator.UI.AnimateProgressBar('dup-progress-bar');
384
  Duplicator.Pack.Create();
296
  </div>
297
  </div>
298
  </div>
299
+
300
+
301
+ <!-- OPTION 4: Try DupArchive Engine -->
302
+ <div class="dup-box no-top">
303
+ <div class="dup-box-title">
304
+ <i class="fa fa-share-alt"></i>&nbsp;<?php _e('Try Duplicator 1.3', 'duplicator'); ?>
305
+ <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
306
+ </div>
307
+ <div class="dup-box-panel" id="dup-pack-build-try2" style="display:none">
308
+ <b class="opt-title"><?php _e('OPTION 4:', 'duplicator'); ?></b><br/>
309
+
310
+ <?php _e('Duplicator 1.3 now has a new engine format named DupArchive. This format is specific to Duplicator and is designed around performance and scalability. '
311
+ . 'Many budget hosting providers have very strict timeouts, CPU/IO constraints that they configure into their servers. With DupArchive the format is '
312
+ . 'designed to help get around these server constraints so that users can build larger packages. The DupArchive engine is currently only available in '
313
+ . 'Duplicator 1.3 and above. This version is currently in Beta and after we have had a good amount of community support we will make it publicly available.', 'duplicator'); ?><br/><br/>
314
+
315
+ <b><?php _e('<i class="fa fa-file-text-o"></i> Overview', 'duplicator'); ?></b><br/>
316
+ <?php _e('Please follow these steps:', 'duplicator'); ?><br/>
317
+ <ol>
318
+ <li><?php _e('Uninstall this version of Duplicator.', 'duplicator'); ?></li>
319
+ <li><?php _e('Install Duplicator 1.3 (Beta) via the link below.', 'duplicator'); ?></li>
320
+ <li><?php _e('After plugin install goto Duplicator &gt; Settings &gt; Packages Tab &gt; Archive Engine &gt; Enable DupArchive', 'duplicator'); ?></li>
321
+ <li><?php _e('Try and build a new package again using the new engine format and let us know how it goes.', 'duplicator'); ?></li>
322
+ </ol> <br/>
323
+
324
+ <div style="text-align: center; margin: 10px">
325
+ <input type="checkbox" id="dup-duparchive-check" onclick="Duplicator.Pack.ToggleDupArchive()">
326
+ <label for="dup-duparchive-check"><?php _e('Yes. I have read the above overview and would like to try the new DupArchive engine!', 'duplicator'); ?></label><br/><br/>
327
+ <button id="dup-duparchive-btn" type="button" class="button-large button-primary" disabled="true" onclick="Duplicator.Pack.OpenBetaLink()">
328
+ <i class="fa fa-share-alt"></i> <?php _e('Download Duplicator 1.3 (Beta)', 'duplicator'); ?>
329
+ </button>
330
+ </div><br/>
331
+ </div>
332
+ </div>
333
+
334
+
335
  <br/><br/><br/>
336
  </div>
337
 
415
  }
416
  };
417
 
418
+ Duplicator.Pack.ToggleDupArchive = function() {
419
+ var $btn = $('#dup-duparchive-btn');
420
+ if ($('#dup-duparchive-check').is(':checked')) {
421
+ $btn.removeAttr("disabled");
422
+ } else {
423
+ $btn.attr("disabled", true);
424
+ }
425
+ };
426
+
427
+ Duplicator.Pack.OpenBetaLink = function() {
428
+ window.open('http://snapcreek.com/duplicator/duplicator-lite-1-3-beta/');
429
+ };
430
+
431
  //Page Init:
432
  Duplicator.UI.AnimateProgressBar('dup-progress-bar');
433
  Duplicator.Pack.Create();