Duplicator – WordPress Migration Plugin - Version 1.4.5

Version Description

Download this release

Release Info

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

Code changes from version 1.4.4 to 1.4.5

Files changed (38) hide show
  1. assets/css/style.css +1 -1
  2. assets/img/logo-pro-32.png +0 -0
  3. classes/class.db.php +35 -28
  4. classes/class.logging.php +538 -538
  5. classes/class.password.php +1 -1
  6. classes/package/class.pack.archive.zip.php +237 -237
  7. classes/package/class.pack.database.php +13 -7
  8. classes/package/class.pack.php +23 -12
  9. classes/package/duparchive/class.pack.archive.duparchive.php +0 -57
  10. classes/utilities/class.u.php +859 -859
  11. ctrls/class.web.services.php +4 -4
  12. ctrls/ctrl.ui.php +165 -165
  13. deactivation.php +3 -3
  14. define.php +2 -2
  15. duplicator.php +1 -1
  16. installer/dup-installer/assets/inc.js.php +226 -226
  17. installer/dup-installer/classes/class.csrf.php +3 -3
  18. installer/dup-installer/classes/class.s3.func.php +2 -2
  19. installer/dup-installer/classes/utilities/class.u.html.php +1 -1
  20. installer/dup-installer/classes/utilities/class.u.notices.manager.php +1250 -1250
  21. installer/dup-installer/ctrls/classes/class.ctrl.extraction.php +604 -603
  22. installer/dup-installer/views/view.help.php +1 -1
  23. installer/dup-installer/views/view.s3.php +26 -12
  24. installer/dup-installer/views/view.s4.php +11 -6
  25. lib/snaplib/class.snaplib.u.util.php +1 -1
  26. readme.txt +1 -1
  27. views/packages/details/detail.php +94 -53
  28. views/packages/details/transfer.php +2 -2
  29. views/packages/main/packages.php +12 -8
  30. views/packages/main/s1.setup2.php +117 -74
  31. views/packages/main/s2.scan2.php +3 -3
  32. views/packages/main/s2.scan3.php +3 -3
  33. views/packages/main/s3.build.php +72 -67
  34. views/settings/import.php +0 -8
  35. views/settings/packages.php +1 -1
  36. views/settings/storage.php +12 -12
  37. views/tools/diagnostics/inc.settings.php +1 -1
  38. views/tools/diagnostics/logging.php +1 -1
assets/css/style.css CHANGED
@@ -28,7 +28,7 @@ ul.category-tabs li {cursor:pointer}
28
 
29
  /*BOXES:Expandable sections */
30
  div.dup-box {padding:0px; display:block; background-color:#fff; border:1px solid #e5e5e5; box-shadow:0 1px 1px rgba(0,0,0,.04);}
31
- div.dup-box-title {font-size:18px; padding:12px 0 3px 12px; font-weight:bold; cursor:pointer; height:30px; margin:0; color:#000; }
32
  div.dup-box-title:hover {color:#555;}
33
  div.dup-box-arrow {text-decoration:none!important; float:right; width:27px; height:30px; font-size:16px; cursor:pointer; padding:1px 0 0 0; white-space:nowrap}
34
  div.dup-box-panel {padding:10px 15px 10px 15px; border-top:1px solid #EEEEEE; margin:-1px 0 0 0;}
28
 
29
  /*BOXES:Expandable sections */
30
  div.dup-box {padding:0px; display:block; background-color:#fff; border:1px solid #e5e5e5; box-shadow:0 1px 1px rgba(0,0,0,.04);}
31
+ div.dup-box-title {font-size:20px; padding:12px 0 3px 12px; font-weight:bold; cursor:pointer; height:30px; margin:0; color:#000; }
32
  div.dup-box-title:hover {color:#555;}
33
  div.dup-box-arrow {text-decoration:none!important; float:right; width:27px; height:30px; font-size:16px; cursor:pointer; padding:1px 0 0 0; white-space:nowrap}
34
  div.dup-box-panel {padding:10px 15px 10px 15px; border-top:1px solid #EEEEEE; margin:-1px 0 0 0;}
assets/img/logo-pro-32.png DELETED
Binary file
classes/class.db.php CHANGED
@@ -16,6 +16,8 @@ if (!defined('DUPLICATOR_VERSION')) exit;
16
 
17
  class DUP_DB extends wpdb
18
  {
 
 
19
  public static $remove_placeholder_escape_exists = null;
20
 
21
  public static function init()
@@ -176,36 +178,41 @@ class DUP_DB extends wpdb
176
  }
177
 
178
  /**
179
- * Returns all collation types that are assigned to the tables in
180
- * the current database. Each element in the array is unique
181
- *
182
- * @param array $excludeTables A list of tables to exclude from the search
183
- *
184
- * @return array Returns an array with all the collation types being used
 
185
  */
186
- public static function getTableCollationList($excludeTables)
187
- {
188
- global $wpdb;
189
- $collations = array();
 
 
 
 
 
190
 
191
- try {
192
- $query = $wpdb->get_results("SHOW TABLE STATUS FROM `{$wpdb->dbname}`");
 
 
 
193
 
194
- foreach($query as $key => $row) {
195
- if (! in_array($row->Name, $excludeTables)) {
196
- if (! empty($row->Collation))
197
- $collations[] = $row->Collation;
198
- }
199
- }
200
-
201
- $collations = array_unique($collations, SORT_STRING);
202
- $collations = array_values($collations);
203
- return $collations;
204
-
205
- } catch (Exception $ex) {
206
- return $collations;
207
- }
208
- }
209
 
210
  /**
211
  * Returns an escaped SQL string
@@ -231,7 +238,7 @@ class DUP_DB extends wpdb
231
 
232
  /**
233
  * this function escape sql string without add and remove remove_placeholder_escape
234
- * don't work on array
235
  *
236
  * @global type $wpdb
237
  * @param mixed $sql
16
 
17
  class DUP_DB extends wpdb
18
  {
19
+ const MAX_TABLE_COUNT_IN_PACKET = 100;
20
+
21
  public static $remove_placeholder_escape_exists = null;
22
 
23
  public static function init()
178
  }
179
 
180
  /**
181
+ * Returns all collation types that are assigned to the tables and columns table in
182
+ * the current database. Each element in the array is unique
183
+ *
184
+ * @param array &$tablesToInclude A list of tables to include in the search.
185
+ * Parameter does not change in the function, is passed by reference only to avoid copying.
186
+ *
187
+ * @return array Returns an array with all the collation types being used
188
  */
189
+ public static function getTableCollationList(&$tablesToInclude)
190
+ {
191
+ global $wpdb;
192
+ static $collations = null;
193
+ if (is_null($collations)) {
194
+ $collations = array();
195
+ //use half the number of tables since we are using them twice
196
+ foreach (array_chunk($tablesToInclude, self::MAX_TABLE_COUNT_IN_PACKET) as $tablesChunk) {
197
+ $sqlTables = implode(",", array_map(array(__CLASS__, 'escValueToQueryString'), $tablesChunk));
198
 
199
+ //UNION is by default DISTINCT
200
+ $query = "SELECT `COLLATION_NAME` FROM `information_schema`.`columns` WHERE `COLLATION_NAME` IS NOT NULL AND `table_schema` = '{$wpdb->dbname}' "
201
+ . "AND `table_name` in (" . $sqlTables . ")"
202
+ . "UNION SELECT `TABLE_COLLATION` FROM `information_schema`.`tables` WHERE `TABLE_COLLATION` IS NOT NULL AND `table_schema` = '{$wpdb->dbname}' "
203
+ . "AND `table_name` in (" . $sqlTables . ")";
204
 
205
+ if (!$wpdb->query($query)) {
206
+ DUP_Log::Info("GET TABLE COLLATION ERROR: " . $wpdb->last_error);
207
+ continue;
208
+ }
209
+
210
+ $collations = array_unique(array_merge($collations, $wpdb->get_col()));
211
+ }
212
+ sort($collations);
213
+ }
214
+ return $collations;
215
+ }
 
 
 
 
216
 
217
  /**
218
  * Returns an escaped SQL string
238
 
239
  /**
240
  * this function escape sql string without add and remove remove_placeholder_escape
241
+ * doesn't work on array
242
  *
243
  * @global type $wpdb
244
  * @param mixed $sql
classes/class.logging.php CHANGED
@@ -1,538 +1,538 @@
1
- <?php
2
- defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
- // Exit if accessed directly
4
- if (!defined('DUPLICATOR_VERSION')) exit;
5
-
6
- /**
7
- * Helper Class for logging
8
- * @package Duplicator\classes
9
- */
10
- abstract class Dup_ErrorBehavior
11
- {
12
- const LogOnly = 0;
13
- const ThrowException = 1;
14
- const Quit = 2;
15
- }
16
-
17
- class DUP_Log
18
- {
19
- /**
20
- * The file handle used to write to the package log file
21
- */
22
- private static $logFileHandle = null;
23
-
24
- /**
25
- * Get the setting which indicates if tracing is enabled
26
- */
27
- private static $traceEnabled = false;
28
-
29
- public static $profileLogs = null;
30
-
31
- /**
32
- * Init this static object
33
- */
34
- public static function Init()
35
- {
36
- self::$traceEnabled = (DUP_Settings::Get('trace_log_enabled') == 1);
37
- }
38
-
39
- /**
40
- * Open a log file connection for writing to the package log file
41
- *
42
- * @param string $nameHas The Name of the log file to create
43
- *
44
- * @return nul
45
- */
46
- public static function Open($nameHash)
47
- {
48
- if (!isset($nameHash)) {
49
- throw new Exception("A name value is required to open a file log.");
50
- }
51
- self::Close();
52
- if ((self::$logFileHandle = @fopen(DUP_Settings::getSsdirPath()."/{$nameHash}.log", "a+")) === false) {
53
- self::$logFileHandle = null;
54
- return false;
55
- } else {
56
- /**
57
- * By initializing the error_handler on opening the log, I am sure that when a package is processed, the handler is active.
58
- */
59
- DUP_Handler::init_error_handler();
60
- return true;
61
- }
62
- }
63
-
64
- /**
65
- * Close the package log file connection if is opened
66
- *
67
- * @return bool Returns TRUE on success or FALSE on failure.
68
- */
69
- public static function Close()
70
- {
71
- $result = true;
72
-
73
- if (!is_null(self::$logFileHandle)) {
74
- $result = @fclose(self::$logFileHandle);
75
- self::$logFileHandle = null;
76
- } else {
77
- $result = true;
78
- }
79
- return $result;
80
- }
81
-
82
- /**
83
- * General information send to the package log if opened
84
- * @param string $msg The message to log
85
- *
86
- * REPLACE TO DEBUG: Memory consumption as script runs
87
- * $results = DUP_Util::byteSize(memory_get_peak_usage(true)) . "\t" . $msg;
88
- * @fwrite(self::$logFileHandle, "{$results} \n");
89
- *
90
- * @param string $msg The message to log
91
- *
92
- * @return null
93
- */
94
- public static function Info($msg)
95
- {
96
- if (self::$traceEnabled) {
97
- self::Trace($msg);
98
- }
99
- if (!is_null(self::$logFileHandle)) {
100
- @fwrite(self::$logFileHandle, $msg."\n");
101
- }
102
- }
103
-
104
- public static function print_r_info($val, $name = '')
105
- {
106
- $msg = empty($name) ? '' : 'VALUE '.$name.': ';
107
- $msg .= print_r($val, true);
108
- self::info($msg);
109
- }
110
-
111
- /**
112
- * Does the trace file exists
113
- *
114
- * @return bool Returns true if an active trace file exists
115
- */
116
- public static function TraceFileExists()
117
- {
118
- $file_path = self::getTraceFilepath();
119
- return file_exists($file_path);
120
- }
121
-
122
- /**
123
- * Gets the current file size of the active trace file
124
- *
125
- * @return string Returns a human readable file size of the active trace file
126
- */
127
- public static function getTraceStatus()
128
- {
129
- $file_path = DUP_Log::getTraceFilepath();
130
- $backup_path = DUP_Log::getBackupTraceFilepath();
131
-
132
- if (file_exists($file_path)) {
133
-
134
- $filesize = is_file($file_path) ? @filesize($file_path) : 0;
135
-
136
- //Its possible mulitple trace log files exist due to size
137
- if (is_file($backup_path)) {
138
- $filesize += @filesize($backup_path);
139
- }
140
-
141
- $message = sprintf('%1$s', DUP_Util::byteSize($filesize));
142
- } else {
143
- $message = esc_html__('No Log', 'duplicator');
144
- }
145
-
146
- return $message;
147
- }
148
-
149
- // RSR TODO: Swap trace logic out for real trace later
150
- public static function Trace($message, $calling_function_override = null)
151
- {
152
-
153
- if (self::$traceEnabled) {
154
- $unique_id = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'].$_SERVER['REQUEST_TIME'].$_SERVER['REMOTE_PORT'])));
155
-
156
- if ($calling_function_override == null) {
157
- $calling_function = DupLiteSnapLibUtil::getCallingFunctionName();
158
- } else {
159
- $calling_function = $calling_function_override;
160
- }
161
-
162
- if (is_object($message)) {
163
- $ov = get_object_vars($message);
164
- $message = print_r($ov, true);
165
- } else if (is_array($message)) {
166
- $message = print_r($message, true);
167
- }
168
-
169
- $logging_message = "{$unique_id}|{$calling_function} | {$message}";
170
- $ticks = time() + ((int) get_option('gmt_offset') * 3600);
171
- $formatted_time = date('d-m-H:i:s', $ticks);
172
- $formatted_logging_message = "{$formatted_time}|DUP|{$logging_message} \r\n";
173
-
174
- // Always write to error log - if they don't want the info they can turn off WordPress error logging or tracing
175
- self::ErrLog($logging_message);
176
-
177
- // Everything goes to the plugin log, whether it's part of package generation or not.
178
- self::WriteToTrace($formatted_logging_message);
179
- }
180
- }
181
-
182
- public static function print_r_trace($val, $name = '', $calling_function_override = null)
183
- {
184
- $msg = empty($name) ? '' : 'VALUE '.$name.': ';
185
- $msg .= print_r($val, true);
186
- self::trace($msg, $calling_function_override);
187
- }
188
-
189
- public static function errLog($message)
190
- {
191
- $message = 'DUP:'.$message;
192
- error_log($message);
193
- }
194
-
195
- public static function TraceObject($msg, $o, $log_private_members = true)
196
- {
197
- if (self::$traceEnabled) {
198
- if (!$log_private_members) {
199
- $o = get_object_vars($o);
200
- }
201
- self::Trace($msg.':'.print_r($o, true));
202
- }
203
- }
204
-
205
- public static function GetDefaultKey()
206
- {
207
- $auth_key = defined('AUTH_KEY') ? AUTH_KEY : 'atk';
208
- $auth_key .= defined('DB_HOST') ? DB_HOST : 'dbh';
209
- $auth_key .= defined('DB_NAME') ? DB_NAME : 'dbn';
210
- $auth_key .= defined('DB_USER') ? DB_USER : 'dbu';
211
- return hash('md5', $auth_key);
212
- }
213
-
214
- /**
215
- * Gets the current file size of the old trace file "1"
216
- *
217
- * @return string Returns a human readable file size of the active trace file
218
- */
219
- public static function GetBackupTraceFilepath()
220
- {
221
- $default_key = self::getDefaultKey();
222
- $backup_log_filename = "dup_$default_key.log1";
223
- $backup_path = DUP_Settings::getSsdirPath()."/".$backup_log_filename;
224
- return $backup_path;
225
- }
226
-
227
- /**
228
- * Gets the active trace file path
229
- *
230
- * @return string Returns the full path to the active trace file (i.e. dup-pro_hash.log)
231
- */
232
- public static function GetTraceFilepath()
233
- {
234
- $default_key = self::getDefaultKey();
235
- $log_filename = "dup_$default_key.log";
236
- $file_path = DUP_Settings::getSsdirPath()."/".$log_filename;
237
- return $file_path;
238
- }
239
-
240
- /**
241
- * Deletes the trace log and backup trace log files
242
- *
243
- * @return null
244
- */
245
- public static function DeleteTraceLog()
246
- {
247
- $file_path = self::GetTraceFilepath();
248
- $backup_path = self::GetBackupTraceFilepath();
249
- self::trace("deleting $file_path");
250
- @unlink($file_path);
251
- self::trace("deleting $backup_path");
252
- @unlink($backup_path);
253
- }
254
-
255
- /**
256
- * Called when an error is detected and no further processing should occur
257
- * @param string $msg The message to log
258
- * @param string $detail Additional details to help resolve the issue if possible
259
- * @param int $behavior
260
- * @throws Exception
261
- */
262
- public static function error($msg, $detail = '', $behavior = Dup_ErrorBehavior::Quit)
263
- {
264
-
265
- error_log($msg.' DETAIL:'.$detail);
266
- $source = self::getStack(debug_backtrace());
267
-
268
- $err_msg = "\n==================================================================================\n";
269
- $err_msg .= "DUPLICATOR ERROR\n";
270
- $err_msg .= "Please try again! If the error persists see the Duplicator 'Help' menu.\n";
271
- $err_msg .= "---------------------------------------------------------------------------------\n";
272
- $err_msg .= "MESSAGE:\n\t{$msg}\n";
273
- if (strlen($detail)) {
274
- $err_msg .= "DETAILS:\n\t{$detail}\n";
275
- }
276
- $err_msg .= "TRACE:\n{$source}";
277
- $err_msg .= "==================================================================================\n\n";
278
- @fwrite(self::$logFileHandle, "{$err_msg}");
279
-
280
- switch ($behavior) {
281
-
282
- case Dup_ErrorBehavior::ThrowException:
283
- DUP_LOG::trace("throwing exception");
284
- throw new Exception($msg);
285
- break;
286
-
287
- case Dup_ErrorBehavior::Quit:
288
- DUP_LOG::trace("quitting");
289
- die("DUPLICATOR ERROR: Please see the 'Package Log' file link below.");
290
- break;
291
-
292
- default:
293
- // Nothing
294
- }
295
- }
296
-
297
- /**
298
- * The current stack trace of a PHP call
299
- * @param $stacktrace The current debug stack
300
- * @return string
301
- */
302
- public static function getStack($stacktrace)
303
- {
304
- $output = "";
305
- $i = 1;
306
- foreach ($stacktrace as $node) {
307
- $output .= "\t $i. ".basename($node['file'])." : ".$node['function']." (".$node['line'].")\n";
308
- $i++;
309
- }
310
- return $output;
311
- }
312
-
313
- /**
314
- * Manages writing the active or backup log based on the size setting
315
- *
316
- * @return null
317
- */
318
- private static function WriteToTrace($formatted_logging_message)
319
- {
320
- $log_filepath = self::GetTraceFilepath();
321
-
322
- if (@filesize($log_filepath) > DUPLICATOR_MAX_LOG_SIZE) {
323
- $backup_log_filepath = self::GetBackupTraceFilepath();
324
-
325
- if (file_exists($backup_log_filepath)) {
326
- if (@unlink($backup_log_filepath) === false) {
327
- self::errLog("Couldn't delete backup log $backup_log_filepath");
328
- }
329
- }
330
-
331
- if (@rename($log_filepath, $backup_log_filepath) === false) {
332
- self::errLog("Couldn't rename log $log_filepath to $backup_log_filepath");
333
- }
334
- }
335
-
336
- if (@file_put_contents($log_filepath, $formatted_logging_message, FILE_APPEND) === false) {
337
- // Not en error worth reporting
338
- }
339
- }
340
- }
341
-
342
- class DUP_Handler
343
- {
344
- const MODE_OFF = 0; // don't write in log
345
- const MODE_LOG = 1; // write errors in log file
346
- const MODE_VAR = 2; // put php errors in $varModeLog static var
347
- const SHUTDOWN_TIMEOUT = 'tm';
348
-
349
- /**
350
- *
351
- * @var bool
352
- */
353
- private static $initialized = false;
354
-
355
- /**
356
- *
357
- * @var array
358
- */
359
- private static $shutdownReturns = array(
360
- 'tm' => 'timeout'
361
- );
362
-
363
- /**
364
- *
365
- * @var int
366
- */
367
- private static $handlerMode = self::MODE_LOG;
368
-
369
- /**
370
- *
371
- * @var bool // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100]
372
- */
373
- private static $codeReference = true;
374
-
375
- /**
376
- *
377
- * @var bool // print prefix in php error line [PHP ERR][WARN] MSG: .....
378
- */
379
- private static $errPrefix = true;
380
-
381
- /**
382
- *
383
- * @var string // php errors in MODE_VAR
384
- */
385
- private static $varModeLog = '';
386
-
387
- /**
388
- * This function only initializes the error handler the first time it is called
389
- */
390
- public static function init_error_handler()
391
- {
392
- if (!self::$initialized) {
393
- @set_error_handler(array(__CLASS__, 'error'));
394
- @register_shutdown_function(array(__CLASS__, 'shutdown'));
395
- self::$initialized = true;
396
- }
397
- }
398
-
399
- /**
400
- * Error handler
401
- *
402
- * @param integer $errno Error level
403
- * @param string $errstr Error message
404
- * @param string $errfile Error file
405
- * @param integer $errline Error line
406
- * @return void
407
- */
408
- public static function error($errno, $errstr, $errfile, $errline)
409
- {
410
- switch (self::$handlerMode) {
411
- case self::MODE_OFF:
412
- if ($errno == E_ERROR) {
413
- $log_message = self::getMessage($errno, $errstr, $errfile, $errline);
414
- DUP_Log::error($log_message);
415
- }
416
- break;
417
- case self::MODE_VAR:
418
- self::$varModeLog .= self::getMessage($errno, $errstr, $errfile, $errline)."\n";
419
- break;
420
- case self::MODE_LOG:
421
- default:
422
- switch ($errno) {
423
- case E_ERROR :
424
- $log_message = self::getMessage($errno, $errstr, $errfile, $errline);
425
- DUP_Log::error($log_message);
426
- break;
427
- case E_NOTICE :
428
- case E_WARNING :
429
- default :
430
- $log_message = self::getMessage($errno, $errstr, $errfile, $errline);
431
- DUP_Log::Info($log_message);
432
- break;
433
- }
434
- }
435
- }
436
-
437
- private static function getMessage($errno, $errstr, $errfile, $errline)
438
- {
439
- $result = '';
440
-
441
- if (self::$errPrefix) {
442
- $result = '[PHP ERR]';
443
- switch ($errno) {
444
- case E_ERROR :
445
- $result .= '[FATAL]';
446
- break;
447
- case E_WARNING :
448
- $result .= '[WARN]';
449
- break;
450
- case E_NOTICE :
451
- $result .= '[NOTICE]';
452
- break;
453
- default :
454
- $result .= '[ISSUE]';
455
- break;
456
- }
457
- $result .= ' MSG:';
458
- }
459
-
460
- $result .= $errstr;
461
-
462
- if (self::$codeReference) {
463
- $result .= ' [CODE:'.$errno.'|FILE:'.$errfile.'|LINE:'.$errline.']';
464
- $result .= "\n".wp_debug_backtrace_summary();
465
- }
466
-
467
- return $result;
468
- }
469
-
470
- /**
471
- * if setMode is called without params set as default
472
- *
473
- * @param int $mode
474
- * @param bool $errPrefix // print prefix in php error line [PHP ERR][WARN] MSG: .....
475
- * @param bool $codeReference // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100]
476
- */
477
- public static function setMode($mode = self::MODE_LOG, $errPrefix = true, $codeReference = true)
478
- {
479
- switch ($mode) {
480
- case self::MODE_OFF:
481
- case self::MODE_VAR:
482
- self::$handlerMode = $mode;
483
- break;
484
- case self::MODE_LOG:
485
- default:
486
- self::$handlerMode = self::MODE_LOG;
487
- }
488
-
489
- self::$varModeLog = '';
490
- self::$errPrefix = $errPrefix;
491
- self::$codeReference = $codeReference;
492
- }
493
-
494
- /**
495
- *
496
- * @return string // return var log string in MODE_VAR
497
- */
498
- public static function getVarLog()
499
- {
500
- return self::$varModeLog;
501
- }
502
-
503
- /**
504
- *
505
- * @return string // return var log string in MODE_VAR and clean var
506
- */
507
- public static function getVarLogClean()
508
- {
509
- $result = self::$varModeLog;
510
- self::$varModeLog = '';
511
- return $result;
512
- }
513
-
514
- /**
515
- *
516
- * @param string $status // timeout
517
- * @param string
518
- */
519
- public static function setShutdownReturn($status, $str)
520
- {
521
- self::$shutdownReturns[$status] = $str;
522
- }
523
-
524
- /**
525
- * Shutdown handler
526
- *
527
- * @return void
528
- */
529
- public static function shutdown()
530
- {
531
- if (($error = error_get_last())) {
532
- if (preg_match('/^Maximum execution time (?:.+) exceeded$/i', $error['message'])) {
533
- echo self::$shutdownReturns[self::SHUTDOWN_TIMEOUT];
534
- }
535
- self::error($error['type'], $error['message'], $error['file'], $error['line']);
536
- }
537
- }
538
- }
1
+ <?php
2
+ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
+ // Exit if accessed directly
4
+ if (!defined('DUPLICATOR_VERSION')) exit;
5
+
6
+ /**
7
+ * Helper Class for logging
8
+ * @package Duplicator\classes
9
+ */
10
+ abstract class Dup_ErrorBehavior
11
+ {
12
+ const LogOnly = 0;
13
+ const ThrowException = 1;
14
+ const Quit = 2;
15
+ }
16
+
17
+ class DUP_Log
18
+ {
19
+ /**
20
+ * The file handle used to write to the package log file
21
+ */
22
+ private static $logFileHandle = null;
23
+
24
+ /**
25
+ * Get the setting which indicates if tracing is enabled
26
+ */
27
+ private static $traceEnabled = false;
28
+
29
+ public static $profileLogs = null;
30
+
31
+ /**
32
+ * Init this static object
33
+ */
34
+ public static function Init()
35
+ {
36
+ self::$traceEnabled = (DUP_Settings::Get('trace_log_enabled') == 1);
37
+ }
38
+
39
+ /**
40
+ * Open a log file connection for writing to the package log file
41
+ *
42
+ * @param string $nameHas The Name of the log file to create
43
+ *
44
+ * @return nul
45
+ */
46
+ public static function Open($nameHash)
47
+ {
48
+ if (!isset($nameHash)) {
49
+ throw new Exception("A name value is required to open a file log.");
50
+ }
51
+ self::Close();
52
+ if ((self::$logFileHandle = @fopen(DUP_Settings::getSsdirPath()."/{$nameHash}.log", "a+")) === false) {
53
+ self::$logFileHandle = null;
54
+ return false;
55
+ } else {
56
+ /**
57
+ * By initializing the error_handler on opening the log, I am sure that when a package is processed, the handler is active.
58
+ */
59
+ DUP_Handler::init_error_handler();
60
+ return true;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Close the package log file connection if is opened
66
+ *
67
+ * @return bool Returns TRUE on success or FALSE on failure.
68
+ */
69
+ public static function Close()
70
+ {
71
+ $result = true;
72
+
73
+ if (!is_null(self::$logFileHandle)) {
74
+ $result = @fclose(self::$logFileHandle);
75
+ self::$logFileHandle = null;
76
+ } else {
77
+ $result = true;
78
+ }
79
+ return $result;
80
+ }
81
+
82
+ /**
83
+ * General information send to the package log if opened
84
+ * @param string $msg The message to log
85
+ *
86
+ * REPLACE TO DEBUG: Memory consumption as script runs
87
+ * $results = DUP_Util::byteSize(memory_get_peak_usage(true)) . "\t" . $msg;
88
+ * @fwrite(self::$logFileHandle, "{$results} \n");
89
+ *
90
+ * @param string $msg The message to log
91
+ *
92
+ * @return null
93
+ */
94
+ public static function Info($msg)
95
+ {
96
+ if (self::$traceEnabled) {
97
+ self::Trace($msg);
98
+ }
99
+ if (!is_null(self::$logFileHandle)) {
100
+ @fwrite(self::$logFileHandle, $msg."\n");
101
+ }
102
+ }
103
+
104
+ public static function print_r_info($val, $name = '')
105
+ {
106
+ $msg = empty($name) ? '' : 'VALUE '.$name.': ';
107
+ $msg .= print_r($val, true);
108
+ self::info($msg);
109
+ }
110
+
111
+ /**
112
+ * Does the trace file exists
113
+ *
114
+ * @return bool Returns true if an active trace file exists
115
+ */
116
+ public static function TraceFileExists()
117
+ {
118
+ $file_path = self::getTraceFilepath();
119
+ return file_exists($file_path);
120
+ }
121
+
122
+ /**
123
+ * Gets the current file size of the active trace file
124
+ *
125
+ * @return string Returns a human readable file size of the active trace file
126
+ */
127
+ public static function getTraceStatus()
128
+ {
129
+ $file_path = DUP_Log::getTraceFilepath();
130
+ $backup_path = DUP_Log::getBackupTraceFilepath();
131
+
132
+ if (file_exists($file_path)) {
133
+
134
+ $filesize = is_file($file_path) ? @filesize($file_path) : 0;
135
+
136
+ //Its possible mulitple trace log files exist due to size
137
+ if (is_file($backup_path)) {
138
+ $filesize += @filesize($backup_path);
139
+ }
140
+
141
+ $message = sprintf('%1$s', DUP_Util::byteSize($filesize));
142
+ } else {
143
+ $message = esc_html__('No Log', 'duplicator');
144
+ }
145
+
146
+ return $message;
147
+ }
148
+
149
+ // RSR TODO: Swap trace logic out for real trace later
150
+ public static function Trace($message, $calling_function_override = null)
151
+ {
152
+
153
+ if (self::$traceEnabled) {
154
+ $unique_id = sprintf("%08x", abs(crc32($_SERVER['REMOTE_ADDR'].$_SERVER['REQUEST_TIME'].$_SERVER['REMOTE_PORT'])));
155
+
156
+ if ($calling_function_override == null) {
157
+ $calling_function = DupLiteSnapLibUtil::getCallingFunctionName();
158
+ } else {
159
+ $calling_function = $calling_function_override;
160
+ }
161
+
162
+ if (is_object($message)) {
163
+ $ov = get_object_vars($message);
164
+ $message = print_r($ov, true);
165
+ } else if (is_array($message)) {
166
+ $message = print_r($message, true);
167
+ }
168
+
169
+ $logging_message = "{$unique_id}|{$calling_function} | {$message}";
170
+ $ticks = time() + ((int) get_option('gmt_offset') * 3600);
171
+ $formatted_time = date('d-m-H:i:s', $ticks);
172
+ $formatted_logging_message = "{$formatted_time}|DUP|{$logging_message} \r\n";
173
+
174
+ // Always write to error log - if they don't want the info they can turn off WordPress error logging or tracing
175
+ self::ErrLog($logging_message);
176
+
177
+ // Everything goes to the plugin log, whether it's part of package generation or not.
178
+ self::WriteToTrace($formatted_logging_message);
179
+ }
180
+ }
181
+
182
+ public static function print_r_trace($val, $name = '', $calling_function_override = null)
183
+ {
184
+ $msg = empty($name) ? '' : 'VALUE '.$name.': ';
185
+ $msg .= print_r($val, true);
186
+ self::trace($msg, $calling_function_override);
187
+ }
188
+
189
+ public static function errLog($message)
190
+ {
191
+ $message = 'DUP:'.$message;
192
+ error_log($message);
193
+ }
194
+
195
+ public static function TraceObject($msg, $o, $log_private_members = true)
196
+ {
197
+ if (self::$traceEnabled) {
198
+ if (!$log_private_members) {
199
+ $o = get_object_vars($o);
200
+ }
201
+ self::Trace($msg.':'.print_r($o, true));
202
+ }
203
+ }
204
+
205
+ public static function GetDefaultKey()
206
+ {
207
+ $auth_key = defined('AUTH_KEY') ? AUTH_KEY : 'atk';
208
+ $auth_key .= defined('DB_HOST') ? DB_HOST : 'dbh';
209
+ $auth_key .= defined('DB_NAME') ? DB_NAME : 'dbn';
210
+ $auth_key .= defined('DB_USER') ? DB_USER : 'dbu';
211
+ return hash('md5', $auth_key);
212
+ }
213
+
214
+ /**
215
+ * Gets the current file size of the old trace file "1"
216
+ *
217
+ * @return string Returns a human readable file size of the active trace file
218
+ */
219
+ public static function GetBackupTraceFilepath()
220
+ {
221
+ $default_key = self::getDefaultKey();
222
+ $backup_log_filename = "dup_$default_key.log1";
223
+ $backup_path = DUP_Settings::getSsdirPath()."/".$backup_log_filename;
224
+ return $backup_path;
225
+ }
226
+
227
+ /**
228
+ * Gets the active trace file path
229
+ *
230
+ * @return string Returns the full path to the active trace file (i.e. dup-pro_hash.log)
231
+ */
232
+ public static function GetTraceFilepath()
233
+ {
234
+ $default_key = self::getDefaultKey();
235
+ $log_filename = "dup_$default_key.log";
236
+ $file_path = DUP_Settings::getSsdirPath()."/".$log_filename;
237
+ return $file_path;
238
+ }
239
+
240
+ /**
241
+ * Deletes the trace log and backup trace log files
242
+ *
243
+ * @return null
244
+ */
245
+ public static function DeleteTraceLog()
246
+ {
247
+ $file_path = self::GetTraceFilepath();
248
+ $backup_path = self::GetBackupTraceFilepath();
249
+ self::trace("deleting $file_path");
250
+ @unlink($file_path);
251
+ self::trace("deleting $backup_path");
252
+ @unlink($backup_path);
253
+ }
254
+
255
+ /**
256
+ * Called when an error is detected and no further processing should occur
257
+ * @param string $msg The message to log
258
+ * @param string $detail Additional details to help resolve the issue if possible
259
+ * @param int $behavior
260
+ * @throws Exception
261
+ */
262
+ public static function error($msg, $detail = '', $behavior = Dup_ErrorBehavior::Quit)
263
+ {
264
+
265
+ error_log($msg.' DETAIL:'.$detail);
266
+ $source = self::getStack(debug_backtrace());
267
+
268
+ $err_msg = "\n==================================================================================\n";
269
+ $err_msg .= "DUPLICATOR ERROR\n";
270
+ $err_msg .= "Please try again! If the error persists see the Duplicator 'Help' menu.\n";
271
+ $err_msg .= "---------------------------------------------------------------------------------\n";
272
+ $err_msg .= "MESSAGE:\n\t{$msg}\n";
273
+ if (strlen($detail)) {
274
+ $err_msg .= "DETAILS:\n\t{$detail}\n";
275
+ }
276
+ $err_msg .= "TRACE:\n{$source}";
277
+ $err_msg .= "==================================================================================\n\n";
278
+ @fwrite(self::$logFileHandle, "{$err_msg}");
279
+
280
+ switch ($behavior) {
281
+
282
+ case Dup_ErrorBehavior::ThrowException:
283
+ DUP_LOG::trace("throwing exception");
284
+ throw new Exception($msg);
285
+ break;
286
+
287
+ case Dup_ErrorBehavior::Quit:
288
+ DUP_LOG::trace("quitting");
289
+ die("DUPLICATOR ERROR: Please see the 'Package Log' file link below.");
290
+ break;
291
+
292
+ default:
293
+ // Nothing
294
+ }
295
+ }
296
+
297
+ /**
298
+ * The current stack trace of a PHP call
299
+ * @param $stacktrace The current debug stack
300
+ * @return string
301
+ */
302
+ public static function getStack($stacktrace)
303
+ {
304
+ $output = "";
305
+ $i = 1;
306
+ foreach ($stacktrace as $node) {
307
+ $output .= "\t $i. ".basename($node['file'])." : ".$node['function']." (".$node['line'].")\n";
308
+ $i++;
309
+ }
310
+ return $output;
311
+ }
312
+
313
+ /**
314
+ * Manages writing the active or backup log based on the size setting
315
+ *
316
+ * @return null
317
+ */
318
+ private static function WriteToTrace($formatted_logging_message)
319
+ {
320
+ $log_filepath = self::GetTraceFilepath();
321
+
322
+ if (@filesize($log_filepath) > DUPLICATOR_MAX_LOG_SIZE) {
323
+ $backup_log_filepath = self::GetBackupTraceFilepath();
324
+
325
+ if (file_exists($backup_log_filepath)) {
326
+ if (@unlink($backup_log_filepath) === false) {
327
+ self::errLog("Couldn't delete backup log $backup_log_filepath");
328
+ }
329
+ }
330
+
331
+ if (@rename($log_filepath, $backup_log_filepath) === false) {
332
+ self::errLog("Couldn't rename log $log_filepath to $backup_log_filepath");
333
+ }
334
+ }
335
+
336
+ if (@file_put_contents($log_filepath, $formatted_logging_message, FILE_APPEND) === false) {
337
+ // Not en error worth reporting
338
+ }
339
+ }
340
+ }
341
+
342
+ class DUP_Handler
343
+ {
344
+ const MODE_OFF = 0; // don't write in log
345
+ const MODE_LOG = 1; // write errors in log file
346
+ const MODE_VAR = 2; // put php errors in $varModeLog static var
347
+ const SHUTDOWN_TIMEOUT = 'tm';
348
+
349
+ /**
350
+ *
351
+ * @var bool
352
+ */
353
+ private static $initialized = false;
354
+
355
+ /**
356
+ *
357
+ * @var array
358
+ */
359
+ private static $shutdownReturns = array(
360
+ 'tm' => 'timeout'
361
+ );
362
+
363
+ /**
364
+ *
365
+ * @var int
366
+ */
367
+ private static $handlerMode = self::MODE_LOG;
368
+
369
+ /**
370
+ *
371
+ * @var bool // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100]
372
+ */
373
+ private static $codeReference = true;
374
+
375
+ /**
376
+ *
377
+ * @var bool // print prefix in php error line [PHP ERR][WARN] MSG: .....
378
+ */
379
+ private static $errPrefix = true;
380
+
381
+ /**
382
+ *
383
+ * @var string // php errors in MODE_VAR
384
+ */
385
+ private static $varModeLog = '';
386
+
387
+ /**
388
+ * This function only initializes the error handler the first time it is called
389
+ */
390
+ public static function init_error_handler()
391
+ {
392
+ if (!self::$initialized) {
393
+ @set_error_handler(array(__CLASS__, 'error'));
394
+ @register_shutdown_function(array(__CLASS__, 'shutdown'));
395
+ self::$initialized = true;
396
+ }
397
+ }
398
+
399
+ /**
400
+ * Error handler
401
+ *
402
+ * @param integer $errno Error level
403
+ * @param string $errstr Error message
404
+ * @param string $errfile Error file
405
+ * @param integer $errline Error line
406
+ * @return void
407
+ */
408
+ public static function error($errno, $errstr, $errfile, $errline)
409
+ {
410
+ switch (self::$handlerMode) {
411
+ case self::MODE_OFF:
412
+ if ($errno == E_ERROR) {
413
+ $log_message = self::getMessage($errno, $errstr, $errfile, $errline);
414
+ DUP_Log::error($log_message);
415
+ }
416
+ break;
417
+ case self::MODE_VAR:
418
+ self::$varModeLog .= self::getMessage($errno, $errstr, $errfile, $errline)."\n";
419
+ break;
420
+ case self::MODE_LOG:
421
+ default:
422
+ switch ($errno) {
423
+ case E_ERROR :
424
+ $log_message = self::getMessage($errno, $errstr, $errfile, $errline);
425
+ DUP_Log::error($log_message);
426
+ break;
427
+ case E_NOTICE :
428
+ case E_WARNING :
429
+ default :
430
+ $log_message = self::getMessage($errno, $errstr, $errfile, $errline);
431
+ DUP_Log::Info($log_message);
432
+ break;
433
+ }
434
+ }
435
+ }
436
+
437
+ private static function getMessage($errno, $errstr, $errfile, $errline)
438
+ {
439
+ $result = '';
440
+
441
+ if (self::$errPrefix) {
442
+ $result = '[PHP ERR]';
443
+ switch ($errno) {
444
+ case E_ERROR :
445
+ $result .= '[FATAL]';
446
+ break;
447
+ case E_WARNING :
448
+ $result .= '[WARN]';
449
+ break;
450
+ case E_NOTICE :
451
+ $result .= '[NOTICE]';
452
+ break;
453
+ default :
454
+ $result .= '[ISSUE]';
455
+ break;
456
+ }
457
+ $result .= ' MSG:';
458
+ }
459
+
460
+ $result .= $errstr;
461
+
462
+ if (self::$codeReference) {
463
+ $result .= ' [CODE:'.$errno.'|FILE:'.$errfile.'|LINE:'.$errline.']';
464
+ $result .= "\n".wp_debug_backtrace_summary();
465
+ }
466
+
467
+ return $result;
468
+ }
469
+
470
+ /**
471
+ * if setMode is called without params set as default
472
+ *
473
+ * @param int $mode
474
+ * @param bool $errPrefix // print prefix in php error line [PHP ERR][WARN] MSG: .....
475
+ * @param bool $codeReference // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100]
476
+ */
477
+ public static function setMode($mode = self::MODE_LOG, $errPrefix = true, $codeReference = true)
478
+ {
479
+ switch ($mode) {
480
+ case self::MODE_OFF:
481
+ case self::MODE_VAR:
482
+ self::$handlerMode = $mode;
483
+ break;
484
+ case self::MODE_LOG:
485
+ default:
486
+ self::$handlerMode = self::MODE_LOG;
487
+ }
488
+
489
+ self::$varModeLog = '';
490
+ self::$errPrefix = $errPrefix;
491
+ self::$codeReference = $codeReference;
492
+ }
493
+
494
+ /**
495
+ *
496
+ * @return string // return var log string in MODE_VAR
497
+ */
498
+ public static function getVarLog()
499
+ {
500
+ return self::$varModeLog;
501
+ }
502
+
503
+ /**
504
+ *
505
+ * @return string // return var log string in MODE_VAR and clean var
506
+ */
507
+ public static function getVarLogClean()
508
+ {
509
+ $result = self::$varModeLog;
510
+ self::$varModeLog = '';
511
+ return $result;
512
+ }
513
+
514
+ /**
515
+ *
516
+ * @param string $status // timeout
517
+ * @param string
518
+ */
519
+ public static function setShutdownReturn($status, $str)
520
+ {
521
+ self::$shutdownReturns[$status] = $str;
522
+ }
523
+
524
+ /**
525
+ * Shutdown handler
526
+ *
527
+ * @return void
528
+ */
529
+ public static function shutdown()
530
+ {
531
+ if (($error = error_get_last())) {
532
+ if (preg_match('/^Maximum execution time (?:.+) exceeded$/i', $error['message'])) {
533
+ echo self::$shutdownReturns[self::SHUTDOWN_TIMEOUT];
534
+ }
535
+ self::error($error['type'], $error['message'], $error['file'], $error['line']);
536
+ }
537
+ }
538
+ }
classes/class.password.php CHANGED
@@ -163,7 +163,7 @@ class DUP_PasswordHash
163
  $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
164
 
165
  $output = '$2a$';
166
- $output .= chr(ord('0') + $this->iteration_count_log2 / 10);
167
  $output .= chr(ord('0') + $this->iteration_count_log2 % 10);
168
  $output .= '$';
169
 
163
  $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
164
 
165
  $output = '$2a$';
166
+ $output .= chr(ord('0') + (int)($this->iteration_count_log2 / 10));
167
  $output .= chr(ord('0') + $this->iteration_count_log2 % 10);
168
  $output .= '$';
169
 
classes/package/class.pack.archive.zip.php CHANGED
@@ -1,238 +1,238 @@
1
- <?php
2
- defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
- // Exit if accessed directly
4
- if (! defined('DUPLICATOR_VERSION')) exit;
5
-
6
- require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
7
-
8
- /**
9
- * Creates a zip file using the built in PHP ZipArchive class
10
- */
11
- class DUP_Zip extends DUP_Archive
12
- {
13
- //PRIVATE
14
- private static $compressDir;
15
- private static $countDirs = 0;
16
- private static $countFiles = 0;
17
- private static $sqlPath;
18
- private static $zipPath;
19
- private static $zipFileSize;
20
- private static $zipArchive;
21
- private static $limitItems = 0;
22
- private static $networkFlush = false;
23
- private static $scanReport;
24
-
25
- /**
26
- * Creates the zip file and adds the SQL file to the archive
27
- */
28
- public static function create(DUP_Archive $archive, $buildProgress)
29
- {
30
- try {
31
- $timerAllStart = DUP_Util::getMicrotime();
32
- $package_zip_flush = DUP_Settings::Get('package_zip_flush');
33
-
34
- self::$compressDir = rtrim(wp_normalize_path(DUP_Util::safePath($archive->PackDir)), '/');
35
- self::$sqlPath = DUP_Settings::getSsdirTmpPath()."/{$archive->Package->Database->File}";
36
- self::$zipPath = DUP_Settings::getSsdirTmpPath()."/{$archive->File}";
37
- self::$zipArchive = new ZipArchive();
38
- self::$networkFlush = empty($package_zip_flush) ? false : $package_zip_flush;
39
-
40
- $filterDirs = empty($archive->FilterDirs) ? 'not set' : $archive->FilterDirs;
41
- $filterExts = empty($archive->FilterExts) ? 'not set' : $archive->FilterExts;
42
- $filterFiles = empty($archive->FilterFiles) ? 'not set' : $archive->FilterFiles;
43
- $filterOn = ($archive->FilterOn) ? 'ON' : 'OFF';
44
- $filterDirsFormat = rtrim(str_replace(';', "\n\t", $filterDirs));
45
- $filterFilesFormat = rtrim(str_replace(';', "\n\t", $filterFiles));
46
- $lastDirSuccess = self::$compressDir;
47
-
48
- //LOAD SCAN REPORT
49
- $json = file_get_contents(DUP_Settings::getSsdirTmpPath()."/{$archive->Package->NameHash}_scan.json");
50
- self::$scanReport = json_decode($json);
51
-
52
- DUP_Log::Info("\n********************************************************************************");
53
- DUP_Log::Info("ARCHIVE (ZIP):");
54
- DUP_Log::Info("********************************************************************************");
55
- $isZipOpen = (self::$zipArchive->open(self::$zipPath, ZIPARCHIVE::CREATE) === TRUE);
56
- if (!$isZipOpen) {
57
- $error_message = "Cannot open zip file with PHP ZipArchive.";
58
- $buildProgress->set_failed($error_message);
59
- DUP_Log::error($error_message, "Path location [".self::$zipPath."]", Dup_ErrorBehavior::LogOnly);
60
- $archive->Package->setStatus(DUP_PackageStatus::ERROR);
61
- return;
62
- }
63
- DUP_Log::Info("ARCHIVE DIR: ".self::$compressDir);
64
- DUP_Log::Info("ARCHIVE FILE: ".basename(self::$zipPath));
65
- DUP_Log::Info("FILTERS: *{$filterOn}*");
66
- DUP_Log::Info("DIRS:\n\t{$filterDirsFormat}");
67
- DUP_Log::Info("FILES:\n\t{$filterFilesFormat}");
68
- DUP_Log::Info("EXTS: {$filterExts}");
69
-
70
- DUP_Log::Info("----------------------------------------");
71
- DUP_Log::Info("COMPRESSING");
72
- DUP_Log::Info("SIZE:\t".self::$scanReport->ARC->Size);
73
- DUP_Log::Info("STATS:\tDirs ".self::$scanReport->ARC->DirCount." | Files ".self::$scanReport->ARC->FileCount);
74
-
75
- //ADD SQL
76
- $sql_ark_file_path = $archive->Package->getSqlArkFilePath();
77
- $isSQLInZip = self::$zipArchive->addFile(self::$sqlPath, $sql_ark_file_path);
78
-
79
- if ($isSQLInZip) {
80
- DUP_Log::Info("SQL ADDED: ".basename(self::$sqlPath));
81
- } else {
82
- $error_message = "Unable to add database.sql to archive.";
83
- DUP_Log::error($error_message, "SQL File Path [".self::$sqlPath."]", Dup_ErrorBehavior::LogOnly);
84
- $buildProgress->set_failed($error_message);
85
- $archive->Package->setStatus(DUP_PackageStatus::ERROR);
86
- return;
87
- }
88
- self::$zipArchive->close();
89
- self::$zipArchive->open(self::$zipPath, ZipArchive::CREATE);
90
-
91
- //ZIP DIRECTORIES
92
- $info = '';
93
- foreach (self::$scanReport->ARC->Dirs as $dir) {
94
- $emptyDir = $archive->getLocalDirPath($dir);
95
-
96
- if (is_readable($dir) && self::$zipArchive->addEmptyDir($emptyDir)) {
97
- self::$countDirs++;
98
- $lastDirSuccess = $dir;
99
- } else {
100
- //Don't warn when dirtory is the root path
101
- if (strcmp($dir, rtrim(self::$compressDir, '/')) != 0) {
102
- $dir_path = strlen($dir) ? "[{$dir}]" : "[Read Error] - last successful read was: [{$lastDirSuccess}]";
103
- $info .= "DIR: {$dir_path}\n";
104
- }
105
- }
106
- }
107
-
108
- //LOG Unreadable DIR info
109
- if (strlen($info)) {
110
- DUP_Log::Info("\nWARNING: Unable to zip directories:");
111
- DUP_Log::Info($info);
112
- }
113
-
114
- /**
115
- * count update for integrity check
116
- */
117
- $sumItems = (self::$countDirs + self::$countFiles);
118
-
119
- /* ZIP FILES: Network Flush
120
- * This allows the process to not timeout on fcgi
121
- * setups that need a response every X seconds */
122
- $totalFileCount = count(self::$scanReport->ARC->Files);
123
- $info = '';
124
- if (self::$networkFlush) {
125
- foreach (self::$scanReport->ARC->Files as $file) {
126
- $file_size = @filesize($file);
127
- $localFileName = $archive->getLocalFilePath($file);
128
-
129
- if (is_readable($file)) {
130
- if (defined('DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR') && DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR && $file_size < DUP_Constants::ZIP_STRING_LIMIT && self::$zipArchive->addFromString($localFileName, file_get_contents($file))) {
131
- Dup_Log::Info("Adding {$file} to zip");
132
- self::$limitItems++;
133
- self::$countFiles++;
134
- } elseif (self::$zipArchive->addFile($file, $localFileName)) {
135
- Dup_Log::Info("Adding {$file} to zip");
136
- self::$limitItems++;
137
- self::$countFiles++;
138
- } else {
139
- $info .= "FILE: [{$file}]\n";
140
- }
141
- } else {
142
- $info .= "FILE: [{$file}]\n";
143
- }
144
- //Trigger a flush to the web server after so many files have been loaded.
145
- if (self::$limitItems > DUPLICATOR_ZIP_FLUSH_TRIGGER) {
146
- self::$zipArchive->close();
147
- self::$zipArchive->open(self::$zipPath);
148
- self::$limitItems = 0;
149
- DUP_Util::fcgiFlush();
150
- DUP_Log::Info("Items archived [{$sumItems}] flushing response.");
151
- }
152
-
153
- if(self::$countFiles % 500 == 0) {
154
- // Every so many files update the status so the UI can display
155
- $archive->Package->Status = DupLiteSnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, self::$countFiles);
156
- $archive->Package->update();
157
- }
158
- }
159
- }
160
- //Normal
161
- else {
162
- foreach (self::$scanReport->ARC->Files as $file) {
163
- $file_size = @filesize($file);
164
- $localFileName = $archive->getLocalFilePath($file);
165
-
166
- if (is_readable($file)) {
167
- if (defined('DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR') && DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR && $file_size < DUP_Constants::ZIP_STRING_LIMIT && self::$zipArchive->addFromString($localFileName, file_get_contents($file))) {
168
- self::$countFiles++;
169
- } elseif (self::$zipArchive->addFile($file, $localFileName)) {
170
- self::$countFiles++;
171
- } else {
172
- $info .= "FILE: [{$file}]\n";
173
- }
174
- } else {
175
- $info .= "FILE: [{$file}]\n";
176
- }
177
-
178
- if(self::$countFiles % 500 == 0) {
179
- // Every so many files update the status so the UI can display
180
- $archive->Package->Status = DupLiteSnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, self::$countFiles);
181
- $archive->Package->update();
182
- }
183
- }
184
- }
185
-
186
- //LOG Unreadable FILE info
187
- if (strlen($info)) {
188
- DUP_Log::Info("\nWARNING: Unable to zip files:");
189
- DUP_Log::Info($info);
190
- unset($info);
191
- }
192
-
193
- DUP_Log::Info(print_r(self::$zipArchive, true));
194
-
195
- /**
196
- * count update for integrity check
197
- */
198
- $archive->file_count = self::$countDirs + self::$countFiles;
199
- DUP_Log::Info("FILE ADDED TO ZIP: ".$archive->file_count);
200
-
201
-
202
- //--------------------------------
203
- //LOG FINAL RESULTS
204
- DUP_Util::fcgiFlush();
205
- $zipCloseResult = self::$zipArchive->close();
206
- if($zipCloseResult) {
207
- DUP_Log::Info("COMPRESSION RESULT: '{$zipCloseResult}'");
208
- } else {
209
- $error_message = "ZipArchive close failure.";
210
- DUP_Log::error($error_message,
211
- "The ZipArchive engine is having issues zipping up the files on this server. For more details visit the FAQ\n"
212
- . "I'm getting a ZipArchive close failure when building. How can I resolve this?\n"
213
- . "[https://snapcreek.com/duplicator/docs/faqs-tech/#faq-package-165-q]",
214
- Dup_ErrorBehavior::LogOnly);
215
- $buildProgress->set_failed($error_message);
216
- $archive->Package->setStatus(DUP_PackageStatus::ERROR);
217
- return;
218
- }
219
-
220
- $timerAllEnd = DUP_Util::getMicrotime();
221
- $timerAllSum = DUP_Util::elapsedTime($timerAllEnd, $timerAllStart);
222
-
223
- self::$zipFileSize = @filesize(self::$zipPath);
224
- DUP_Log::Info("COMPRESSED SIZE: ".DUP_Util::byteSize(self::$zipFileSize));
225
- DUP_Log::Info("ARCHIVE RUNTIME: {$timerAllSum}");
226
- DUP_Log::Info("MEMORY STACK: ".DUP_Server::getPHPMemory());
227
-
228
-
229
-
230
- } catch (Exception $e) {
231
- $error_message = "Runtime error in class.pack.archive.zip.php constructor.";
232
- DUP_Log::error($error_message, "Exception: {$e}", Dup_ErrorBehavior::LogOnly);
233
- $buildProgress->set_failed($error_message);
234
- $archive->Package->setStatus(DUP_PackageStatus::ERROR);
235
- return;
236
- }
237
- }
238
  }
1
+ <?php
2
+ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
+ // Exit if accessed directly
4
+ if (! defined('DUPLICATOR_VERSION')) exit;
5
+
6
+ require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
7
+
8
+ /**
9
+ * Creates a zip file using the built in PHP ZipArchive class
10
+ */
11
+ class DUP_Zip extends DUP_Archive
12
+ {
13
+ //PRIVATE
14
+ private static $compressDir;
15
+ private static $countDirs = 0;
16
+ private static $countFiles = 0;
17
+ private static $sqlPath;
18
+ private static $zipPath;
19
+ private static $zipFileSize;
20
+ private static $zipArchive;
21
+ private static $limitItems = 0;
22
+ private static $networkFlush = false;
23
+ private static $scanReport;
24
+
25
+ /**
26
+ * Creates the zip file and adds the SQL file to the archive
27
+ */
28
+ public static function create(DUP_Archive $archive, $buildProgress)
29
+ {
30
+ try {
31
+ $timerAllStart = DUP_Util::getMicrotime();
32
+ $package_zip_flush = DUP_Settings::Get('package_zip_flush');
33
+
34
+ self::$compressDir = rtrim(wp_normalize_path(DUP_Util::safePath($archive->PackDir)), '/');
35
+ self::$sqlPath = DUP_Settings::getSsdirTmpPath()."/{$archive->Package->Database->File}";
36
+ self::$zipPath = DUP_Settings::getSsdirTmpPath()."/{$archive->File}";
37
+ self::$zipArchive = new ZipArchive();
38
+ self::$networkFlush = empty($package_zip_flush) ? false : $package_zip_flush;
39
+
40
+ $filterDirs = empty($archive->FilterDirs) ? 'not set' : $archive->FilterDirs;
41
+ $filterExts = empty($archive->FilterExts) ? 'not set' : $archive->FilterExts;
42
+ $filterFiles = empty($archive->FilterFiles) ? 'not set' : $archive->FilterFiles;
43
+ $filterOn = ($archive->FilterOn) ? 'ON' : 'OFF';
44
+ $filterDirsFormat = rtrim(str_replace(';', "\n\t", $filterDirs));
45
+ $filterFilesFormat = rtrim(str_replace(';', "\n\t", $filterFiles));
46
+ $lastDirSuccess = self::$compressDir;
47
+
48
+ //LOAD SCAN REPORT
49
+ $json = file_get_contents(DUP_Settings::getSsdirTmpPath()."/{$archive->Package->NameHash}_scan.json");
50
+ self::$scanReport = json_decode($json);
51
+
52
+ DUP_Log::Info("\n********************************************************************************");
53
+ DUP_Log::Info("ARCHIVE (ZIP):");
54
+ DUP_Log::Info("********************************************************************************");
55
+ $isZipOpen = (self::$zipArchive->open(self::$zipPath, ZIPARCHIVE::CREATE) === TRUE);
56
+ if (!$isZipOpen) {
57
+ $error_message = "Cannot open zip file with PHP ZipArchive.";
58
+ $buildProgress->set_failed($error_message);
59
+ DUP_Log::error($error_message, "Path location [".self::$zipPath."]", Dup_ErrorBehavior::LogOnly);
60
+ $archive->Package->setStatus(DUP_PackageStatus::ERROR);
61
+ return;
62
+ }
63
+ DUP_Log::Info("ARCHIVE DIR: ".self::$compressDir);
64
+ DUP_Log::Info("ARCHIVE FILE: ".basename(self::$zipPath));
65
+ DUP_Log::Info("FILTERS: *{$filterOn}*");
66
+ DUP_Log::Info("DIRS:\n\t{$filterDirsFormat}");
67
+ DUP_Log::Info("FILES:\n\t{$filterFilesFormat}");
68
+ DUP_Log::Info("EXTS: {$filterExts}");
69
+
70
+ DUP_Log::Info("----------------------------------------");
71
+ DUP_Log::Info("COMPRESSING");
72
+ DUP_Log::Info("SIZE:\t".self::$scanReport->ARC->Size);
73
+ DUP_Log::Info("STATS:\tDirs ".self::$scanReport->ARC->DirCount." | Files ".self::$scanReport->ARC->FileCount);
74
+
75
+ //ADD SQL
76
+ $sql_ark_file_path = $archive->Package->getSqlArkFilePath();
77
+ $isSQLInZip = self::$zipArchive->addFile(self::$sqlPath, $sql_ark_file_path);
78
+
79
+ if ($isSQLInZip) {
80
+ DUP_Log::Info("SQL ADDED: ".basename(self::$sqlPath));
81
+ } else {
82
+ $error_message = "Unable to add database.sql to archive.";
83
+ DUP_Log::error($error_message, "SQL File Path [".self::$sqlPath."]", Dup_ErrorBehavior::LogOnly);
84
+ $buildProgress->set_failed($error_message);
85
+ $archive->Package->setStatus(DUP_PackageStatus::ERROR);
86
+ return;
87
+ }
88
+ self::$zipArchive->close();
89
+ self::$zipArchive->open(self::$zipPath, ZipArchive::CREATE);
90
+
91
+ //ZIP DIRECTORIES
92
+ $info = '';
93
+ foreach (self::$scanReport->ARC->Dirs as $dir) {
94
+ $emptyDir = $archive->getLocalDirPath($dir);
95
+
96
+ if (is_readable($dir) && self::$zipArchive->addEmptyDir($emptyDir)) {
97
+ self::$countDirs++;
98
+ $lastDirSuccess = $dir;
99
+ } else {
100
+ //Don't warn when dirtory is the root path
101
+ if (strcmp($dir, rtrim(self::$compressDir, '/')) != 0) {
102
+ $dir_path = strlen($dir) ? "[{$dir}]" : "[Read Error] - last successful read was: [{$lastDirSuccess}]";
103
+ $info .= "DIR: {$dir_path}\n";
104
+ }
105
+ }
106
+ }
107
+
108
+ //LOG Unreadable DIR info
109
+ if (strlen($info)) {
110
+ DUP_Log::Info("\nWARNING: Unable to zip directories:");
111
+ DUP_Log::Info($info);
112
+ }
113
+
114
+ /**
115
+ * count update for integrity check
116
+ */
117
+ $sumItems = (self::$countDirs + self::$countFiles);
118
+
119
+ /* ZIP FILES: Network Flush
120
+ * This allows the process to not timeout on fcgi
121
+ * setups that need a response every X seconds */
122
+ $totalFileCount = count(self::$scanReport->ARC->Files);
123
+ $info = '';
124
+ if (self::$networkFlush) {
125
+ foreach (self::$scanReport->ARC->Files as $file) {
126
+ $file_size = @filesize($file);
127
+ $localFileName = $archive->getLocalFilePath($file);
128
+
129
+ if (is_readable($file)) {
130
+ if (defined('DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR') && DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR && $file_size < DUP_Constants::ZIP_STRING_LIMIT && self::$zipArchive->addFromString($localFileName, file_get_contents($file))) {
131
+ Dup_Log::Info("Adding {$file} to zip");
132
+ self::$limitItems++;
133
+ self::$countFiles++;
134
+ } elseif (self::$zipArchive->addFile($file, $localFileName)) {
135
+ Dup_Log::Info("Adding {$file} to zip");
136
+ self::$limitItems++;
137
+ self::$countFiles++;
138
+ } else {
139
+ $info .= "FILE: [{$file}]\n";
140
+ }
141
+ } else {
142
+ $info .= "FILE: [{$file}]\n";
143
+ }
144
+ //Trigger a flush to the web server after so many files have been loaded.
145
+ if (self::$limitItems > DUPLICATOR_ZIP_FLUSH_TRIGGER) {
146
+ self::$zipArchive->close();
147
+ self::$zipArchive->open(self::$zipPath);
148
+ self::$limitItems = 0;
149
+ DUP_Util::fcgiFlush();
150
+ DUP_Log::Info("Items archived [{$sumItems}] flushing response.");
151
+ }
152
+
153
+ if(self::$countFiles % 500 == 0) {
154
+ // Every so many files update the status so the UI can display
155
+ $archive->Package->Status = DupLiteSnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, self::$countFiles);
156
+ $archive->Package->update();
157
+ }
158
+ }
159
+ }
160
+ //Normal
161
+ else {
162
+ foreach (self::$scanReport->ARC->Files as $file) {
163
+ $file_size = @filesize($file);
164
+ $localFileName = $archive->getLocalFilePath($file);
165
+
166
+ if (is_readable($file)) {
167
+ if (defined('DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR') && DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR && $file_size < DUP_Constants::ZIP_STRING_LIMIT && self::$zipArchive->addFromString($localFileName, file_get_contents($file))) {
168
+ self::$countFiles++;
169
+ } elseif (self::$zipArchive->addFile($file, $localFileName)) {
170
+ self::$countFiles++;
171
+ } else {
172
+ $info .= "FILE: [{$file}]\n";
173
+ }
174
+ } else {
175
+ $info .= "FILE: [{$file}]\n";
176
+ }
177
+
178
+ if(self::$countFiles % 500 == 0) {
179
+ // Every so many files update the status so the UI can display
180
+ $archive->Package->Status = DupLiteSnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, self::$countFiles);
181
+ $archive->Package->update();
182
+ }
183
+ }
184
+ }
185
+
186
+ //LOG Unreadable FILE info
187
+ if (strlen($info)) {
188
+ DUP_Log::Info("\nWARNING: Unable to zip files:");
189
+ DUP_Log::Info($info);
190
+ unset($info);
191
+ }
192
+
193
+ DUP_Log::Info(print_r(self::$zipArchive, true));
194
+
195
+ /**
196
+ * count update for integrity check
197
+ */
198
+ $archive->file_count = self::$countDirs + self::$countFiles;
199
+ DUP_Log::Info("FILE ADDED TO ZIP: ".$archive->file_count);
200
+
201
+
202
+ //--------------------------------
203
+ //LOG FINAL RESULTS
204
+ DUP_Util::fcgiFlush();
205
+ $zipCloseResult = self::$zipArchive->close();
206
+ if($zipCloseResult) {
207
+ DUP_Log::Info("COMPRESSION RESULT: '{$zipCloseResult}'");
208
+ } else {
209
+ $error_message = "ZipArchive close failure.";
210
+ DUP_Log::error($error_message,
211
+ "The ZipArchive engine is having issues zipping up the files on this server. For more details visit the FAQ\n"
212
+ . "I'm getting a ZipArchive close failure when building. How can I resolve this?\n"
213
+ . "[https://snapcreek.com/duplicator/docs/faqs-tech/#faq-package-165-q]",
214
+ Dup_ErrorBehavior::LogOnly);
215
+ $buildProgress->set_failed($error_message);
216
+ $archive->Package->setStatus(DUP_PackageStatus::ERROR);
217
+ return;
218
+ }
219
+
220
+ $timerAllEnd = DUP_Util::getMicrotime();
221
+ $timerAllSum = DUP_Util::elapsedTime($timerAllEnd, $timerAllStart);
222
+
223
+ self::$zipFileSize = @filesize(self::$zipPath);
224
+ DUP_Log::Info("COMPRESSED SIZE: ".DUP_Util::byteSize(self::$zipFileSize));
225
+ DUP_Log::Info("ARCHIVE RUNTIME: {$timerAllSum}");
226
+ DUP_Log::Info("MEMORY STACK: ".DUP_Server::getPHPMemory());
227
+
228
+
229
+
230
+ } catch (Exception $e) {
231
+ $error_message = "Runtime error in class.pack.archive.zip.php constructor.";
232
+ DUP_Log::error($error_message, "Exception: {$e}", Dup_ErrorBehavior::LogOnly);
233
+ $buildProgress->set_failed($error_message);
234
+ $archive->Package->setStatus(DUP_PackageStatus::ERROR);
235
+ return;
236
+ }
237
+ }
238
  }
classes/package/class.pack.database.php CHANGED
@@ -277,6 +277,7 @@ class DUP_Database
277
  $tblSizeFound = 0;
278
 
279
  //Grab Table Stats
 
280
  foreach ($tables as $table) {
281
  $tblBaseCount++;
282
  $name = $table["Name"];
@@ -295,6 +296,7 @@ class DUP_Database
295
  $info['TableList'][$name]['Rows'] = number_format($rows);
296
  $info['TableList'][$name]['Size'] = DUP_Util::byteSize($size);
297
  $info['TableList'][$name]['USize'] = $size;
 
298
  $tblCount++;
299
 
300
  //Table Uppercase
@@ -318,8 +320,7 @@ class DUP_Database
318
  }
319
  }
320
  }
321
-
322
- $this->setInfoObj();
323
  $this->info->addTriggers();
324
 
325
  $info['Status']['DB_Case'] = preg_match('/[A-Z]/', $wpdb->dbname) ? 'Warn' : 'Good';
@@ -346,18 +347,23 @@ class DUP_Database
346
  return $info;
347
  }
348
 
349
- public function setInfoObj()
 
 
 
 
 
 
350
  {
351
  global $wpdb;
352
- $filterTables = isset($this->FilterTables) ? explode(',', $this->FilterTables) : array();
353
-
354
  $this->info->buildMode = DUP_DB::getBuildMode();
355
  $this->info->version = DUP_DB::getVersion();
356
  $this->info->versionComment = DUP_DB::getVariable('version_comment');
357
  $this->info->varLowerCaseTables = DUP_DB::getVariable('lower_case_table_names');
358
  $this->info->name = $wpdb->dbname;
359
  $this->info->isNameUpperCase = preg_match('/[A-Z]/', $wpdb->dbname) ? 1 : 0;
360
- $this->info->collationList = DUP_DB::getTableCollationList($filterTables);
361
  }
362
 
363
  /**
@@ -568,7 +574,7 @@ class DUP_Database
568
  * 2 - Exception
569
  */
570
  DUP_Log::Info('MYSQL DUMP ERROR '.print_r($mysqlResult, true));
571
- DUP_Log::error(__('Shell mysql dump error. Change SQL Script to the "PHP Code" in the Duplicator > Settings > Packages.', 'duplicator'), implode("\n", DupLiteSnapLibIOU::getLastLinesOfFile($this->tempDbPath,
572
  DUPLICATOR_DB_MYSQLDUMP_ERROR_CONTAINING_LINE_COUNT, DUPLICATOR_DB_MYSQLDUMP_ERROR_CHARS_IN_LINE_COUNT)), Dup_ErrorBehavior::ThrowException);
573
  return false;
574
  }
277
  $tblSizeFound = 0;
278
 
279
  //Grab Table Stats
280
+ $filteredTables = array();
281
  foreach ($tables as $table) {
282
  $tblBaseCount++;
283
  $name = $table["Name"];
296
  $info['TableList'][$name]['Rows'] = number_format($rows);
297
  $info['TableList'][$name]['Size'] = DUP_Util::byteSize($size);
298
  $info['TableList'][$name]['USize'] = $size;
299
+ $filteredTables[] = $name;
300
  $tblCount++;
301
 
302
  //Table Uppercase
320
  }
321
  }
322
  }
323
+ $this->setInfoObj($filteredTables);
 
324
  $this->info->addTriggers();
325
 
326
  $info['Status']['DB_Case'] = preg_match('/[A-Z]/', $wpdb->dbname) ? 'Warn' : 'Good';
347
  return $info;
348
  }
349
 
350
+ /**
351
+ * @param array &$filteredTables Filtered names of tables to include in collation search.
352
+ * Parameter does not change in the function, is passed by reference only to avoid copying.
353
+ *
354
+ * @return void
355
+ */
356
+ public function setInfoObj(&$filteredTables)
357
  {
358
  global $wpdb;
359
+
 
360
  $this->info->buildMode = DUP_DB::getBuildMode();
361
  $this->info->version = DUP_DB::getVersion();
362
  $this->info->versionComment = DUP_DB::getVariable('version_comment');
363
  $this->info->varLowerCaseTables = DUP_DB::getVariable('lower_case_table_names');
364
  $this->info->name = $wpdb->dbname;
365
  $this->info->isNameUpperCase = preg_match('/[A-Z]/', $wpdb->dbname) ? 1 : 0;
366
+ $this->info->collationList = DUP_DB::getTableCollationList($filteredTables);
367
  }
368
 
369
  /**
574
  * 2 - Exception
575
  */
576
  DUP_Log::Info('MYSQL DUMP ERROR '.print_r($mysqlResult, true));
577
+ DUP_Log::error(__('Shell mysql dump error. Change SQL Mode to the "PHP Code" in the Duplicator > Settings > Packages.', 'duplicator'), implode("\n", DupLiteSnapLibIOU::getLastLinesOfFile($this->tempDbPath,
578
  DUPLICATOR_DB_MYSQLDUMP_ERROR_CONTAINING_LINE_COUNT, DUPLICATOR_DB_MYSQLDUMP_ERROR_CHARS_IN_LINE_COUNT)), Dup_ErrorBehavior::ThrowException);
579
  return false;
580
  }
classes/package/class.pack.php CHANGED
@@ -1702,22 +1702,33 @@ class DUP_Package
1702
  $files = DUP_Util::listFiles(DUP_Settings::getSsdirTmpPath());
1703
  $newPath = DUP_Settings::getSsdirPath();
1704
 
1705
- if (function_exists('rename')) {
1706
- foreach ($files as $file) {
1707
- $name = basename($file);
1708
- if (strstr($name, $this->NameHash)) {
1709
- rename($file, "{$newPath}/{$name}");
1710
- }
 
 
 
 
1711
  }
1712
- } else {
1713
- foreach ($files as $file) {
1714
- $name = basename($file);
1715
- if (strstr($name, $this->NameHash)) {
1716
- copy($file, "{$newPath}/{$name}");
1717
- @unlink($file);
 
 
1718
  }
1719
  }
 
 
 
 
1720
  }
 
1721
  }
1722
 
1723
 
1702
  $files = DUP_Util::listFiles(DUP_Settings::getSsdirTmpPath());
1703
  $newPath = DUP_Settings::getSsdirPath();
1704
 
1705
+ $filesToStore = array(
1706
+ $this->Installer->File,
1707
+ $this->Archive->File,
1708
+ );
1709
+
1710
+ foreach ($files as $file) {
1711
+
1712
+ $fileName = basename($file);
1713
+ if (!strstr($fileName, $this->NameHash)) {
1714
+ continue;
1715
  }
1716
+
1717
+ if (in_array($fileName, $filesToStore)) {
1718
+ if (function_exists('rename')) {
1719
+ rename($file, "{$newPath}/{$fileName}");
1720
+ } elseif (function_exists('copy')) {
1721
+ copy($file, "{$newPath}/{$fileName}");
1722
+ } else {
1723
+ throw new Exception('PHP copy and rename functions not found! Contact hosting provider!');
1724
  }
1725
  }
1726
+
1727
+ if (file_exists($file)) {
1728
+ unlink($file);
1729
+ }
1730
  }
1731
+
1732
  }
1733
 
1734
 
classes/package/duparchive/class.pack.archive.duparchive.php CHANGED
@@ -1,8 +1,6 @@
1
  <?php
2
  defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
 
4
- //require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/class.pack.archive.php');
5
- //require_once (DUPLICATOR_PLUGIN_PATH.'classes/utilities/class.u.php');
6
  require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.state.expand.php');
7
  require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.state.create.php');
8
  require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/class.duparchive.loggerbase.php');
@@ -37,10 +35,8 @@ class DUP_DupArchive
37
  DUP_LOG::trace("start");
38
  try {
39
  DUP_Log::Open($package->NameHash);
40
- DUP_Log::trace("c2");
41
 
42
  if ($buildProgress->retries > DUPLICATOR_MAX_BUILD_RETRIES) {
43
- DUP_LOG::trace("c3");
44
  $error_msg = __('Package build appears stuck so marking package as failed. Is the Max Worker Time set too high?.', 'duplicator');
45
  DUP_Log::error(esc_html__('Build Failure', 'duplicator'), esc_html($error_msg), Dup_ErrorBehavior::LogOnly);
46
  //$buildProgress->failed = true;
@@ -49,7 +45,6 @@ class DUP_DupArchive
49
  ;
50
  return true;
51
  } else {
52
- DUP_LOG::trace("c4");
53
  // If all goes well retries will be reset to 0 at the end of this function.
54
  $buildProgress->retries++;
55
  $package->update();
@@ -57,29 +52,21 @@ class DUP_DupArchive
57
 
58
  $done = false;
59
 
60
- DUP_LOG::trace("c5");
61
  DupArchiveEngine::init(new DUP_DupArchive_Logger(), null, $archive);
62
-
63
- DUP_LOG::trace("c6");
64
  DUP_Package::safeTmpCleanup(true);
65
 
66
  $compressDir = rtrim(DUP_Util::safePath($archive->PackDir), '/');
67
  $sqlPath = DUP_Settings::getSsdirTmpPath()."/{$package->Database->File}";
68
  $archivePath = DUP_Settings::getSsdirTmpPath()."/{$archive->File}";
69
  $scanFilepath = DUP_Settings::getSsdirTmpPath()."/{$package->NameHash}_scan.json";
70
-
71
- DUP_LOG::trace("c7");
72
  $skipArchiveFinalization = false;
73
  $json = '';
74
 
75
- DUP_LOG::trace("c8");
76
  if (file_exists($scanFilepath)) {
77
 
78
- DUP_LOG::trace("c9");
79
  $json = file_get_contents($scanFilepath);
80
 
81
  if (empty($json)) {
82
- DUP_LOG::trace("c10");
83
  $errorText = __("Scan file $scanFilepath is empty!", 'duplicator');
84
  $fixText = __("Click on \"Resolve This\" button to fix the JSON settings.", 'duplicator');
85
 
@@ -92,7 +79,6 @@ class DUP_DupArchive
92
  return true;
93
  }
94
  } else {
95
- DUP_LOG::trace("c11");
96
  DUP_Log::trace("**** scan file $scanFilepath doesn't exist!!");
97
  $errorMessage = sprintf(__("ERROR: Can't find Scanfile %s. Please ensure there no non-English characters in the package or schedule name.", 'duplicator'), $scanFilepath);
98
 
@@ -104,7 +90,6 @@ class DUP_DupArchive
104
  return true;
105
  }
106
 
107
- DUP_LOG::trace("c12");
108
  Dup_Log::TraceObject("buildprogress object", $buildProgress, false);
109
 
110
  $scanReport = json_decode($json);
@@ -118,7 +103,6 @@ class DUP_DupArchive
118
  $filterDirsFormat = rtrim(str_replace(';', "\n\t", $filterDirs));
119
  $filterFilesFormat = rtrim(str_replace(';', "\n\t", $filterFiles));
120
 
121
- DUP_LOG::trace("c13");
122
  DUP_Log::info("\n********************************************************************************");
123
  DUP_Log::info("ARCHIVE Type=DUP Mode=DupArchive");
124
  DUP_Log::info("********************************************************************************");
@@ -128,7 +112,6 @@ class DUP_DupArchive
128
  DUP_Log::Info("DIRS:\n\t{$filterDirsFormat}");
129
  DUP_Log::Info("FILES:\n\t{$filterFilesFormat}");
130
  DUP_Log::info("EXTS: {$filterExts}");
131
-
132
  DUP_Log::info("----------------------------------------");
133
  DUP_Log::info("COMPRESSING");
134
  DUP_Log::info("SIZE:\t".$scanReport->ARC->Size);
@@ -138,7 +121,6 @@ class DUP_DupArchive
138
  $error_message = 'Invalid Scan Report Detected';
139
 
140
  DUP_Log::error($error_message, 'Invalid Scan Report Detected', Dup_ErrorBehavior::LogOnly);
141
- //$buildProgress->failed = true;
142
  $buildProgress->set_failed($error_message);
143
  $package->setStatus(DUP_PackageStatus::ERROR);
144
  return true;
@@ -153,33 +135,27 @@ class DUP_DupArchive
153
  $error_message = 'Error adding database.sql to archive';
154
 
155
  DUP_Log::error($error_message, $ex->getMessage(), Dup_ErrorBehavior::LogOnly);
156
- //$buildProgress->failed = true;
157
  $buildProgress->set_failed($error_message);
158
  $package->setStatus(DUP_PackageStatus::ERROR);
159
  return true;
160
  }
161
 
162
  $buildProgress->archive_started = true;
163
-
164
  $buildProgress->retries = 0;
165
 
166
  $createState = DUP_DupArchive_Create_State::createNew($archivePath, $compressDir, self::WorkerTimeInSec, true, true);
167
  $createState->throttleDelayInUs = 0;
168
 
169
  $createState->save();
170
-
171
  $package->Update();
172
  }
173
 
174
  try {
175
-
176
- DUP_LOG::trace("c14");
177
  $createState = DUP_DupArchive_Create_State::get_instance();
178
 
179
  if ($buildProgress->retries > 1) {
180
  // Indicates it had problems before so move into robustness mode
181
  $createState->isRobust = true;
182
-
183
  $createState->save();
184
  }
185
 
@@ -192,16 +168,12 @@ class DUP_DupArchive
192
  $buildProgress->set_build_failures($createState->failures);
193
 
194
  if ($createState->isCriticalFailurePresent()) {
195
-
196
  throw new Exception($createState->getFailureSummary());
197
  }
198
 
199
  $totalFileCount = count($scanReport->ARC->Files);
200
-
201
  $package->Status = DupLiteSnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, $createState->currentFileIndex);
202
-
203
  $buildProgress->retries = 0;
204
-
205
  $createState->save();
206
 
207
  DUP_LOG::TraceObject("Stored Create State", $createState);
@@ -215,7 +187,6 @@ class DUP_DupArchive
215
  }
216
  }
217
  catch (Exception $ex) {
218
- DUP_LOG::trace("c15");
219
  $message = __('Problem adding items to archive.', 'duplicator').' '.$ex->getMessage();
220
 
221
  DUP_Log::error(__('Problems adding items to archive.', 'duplicator'), $message, Dup_ErrorBehavior::LogOnly);
@@ -226,15 +197,11 @@ class DUP_DupArchive
226
  return true;
227
  }
228
 
229
- DUP_LOG::trace("c16");
230
-
231
  //-- Final Wrapup of the Archive
232
  if ((!$skipArchiveFinalization) && ($createState->working == false)) {
233
 
234
  DUP_LOG::Trace("Create state is not working and not skip archive finalization");
235
 
236
- DUP_LOG::trace("c17");
237
-
238
  if (!$buildProgress->installer_built) {
239
 
240
  if ($package->Installer->build($package, false)) {
@@ -247,10 +214,6 @@ class DUP_DupArchive
247
  return;
248
  }
249
 
250
-
251
-
252
- //rsr todo need this somewhere $package->buildCleanup();
253
-
254
  DUP_Log::Trace("Installer has been built so running expand now");
255
 
256
  $expandState = DUP_DupArchive_Expand_State::getInstance(true);
@@ -274,25 +237,19 @@ class DUP_DupArchive
274
  DUP_LOG::traceObject("EXPAND STATE AFTER SAVE", $expandState);
275
  } else {
276
 
277
- DUP_LOG::trace("c18");
278
  try {
279
 
280
  $expandState = DUP_DupArchive_Expand_State::getInstance();
281
 
282
  if ($buildProgress->retries > 1) {
283
-
284
  // Indicates it had problems before so move into robustness mode
285
  $expandState->isRobust = true;
286
-
287
  $expandState->save();
288
  }
289
 
290
  DUP_Log::traceObject('Resumed validation expand state', $expandState);
291
-
292
  DupArchiveEngine::expandArchive($expandState);
293
-
294
  $buildProgress->set_validation_failures($expandState->failures);
295
-
296
  $totalFileCount = count($scanReport->ARC->Files);
297
  $archiveSize = @filesize($expandState->archivePath);
298
 
@@ -303,30 +260,21 @@ class DUP_DupArchive
303
  }
304
  catch (Exception $ex) {
305
  DUP_Log::Trace('Exception:'.$ex->getMessage().':'.$ex->getTraceAsString());
306
- //$buildProgress->failed = true;
307
  $buildProgress->set_failed('Error validating archive');
308
  $package->setStatus(DUP_PackageStatus::ERROR);
309
  return true;
310
  }
311
 
312
  if ($expandState->isCriticalFailurePresent()) {
313
- DUP_LOG::trace("c20");
314
  // Fail immediately if critical failure present - even if havent completed processing the entire archive.
315
-
316
  $error_message = __('Critical failure present in validation', 'duplicator');
317
-
318
  DUP_Log::error($error_message, $expandState->getFailureSummary(), Dup_ErrorBehavior::LogOnly);
319
-
320
- //$buildProgress->failed = true;
321
  $buildProgress->set_failed($error_message);
322
  return true;
323
  } else if (!$expandState->working) {
324
- DUP_LOG::trace("c21");
325
 
326
  $buildProgress->archive_built = true;
327
  $buildProgress->retries = 0;
328
-
329
- // rsr todo is this required?
330
  $package->update();
331
 
332
  $timerAllEnd = DUP_Util::getMicrotime();
@@ -342,15 +290,10 @@ class DUP_DupArchive
342
  DUP_Log::info("VALIDATION WARNINGS: ".$expandState->getFailureSummary(false, true));
343
 
344
  $archive->file_count = $expandState->fileWriteCount + $expandState->directoryWriteCount;
345
-
346
  $package->update();
347
-
348
- DUP_LOG::trace("c22");
349
  $done = true;
350
  } else {
351
- DUP_LOG::trace("c23");
352
  $expandState->save();
353
- DUP_LOG::trace("c24");
354
  }
355
  }
356
  }
1
  <?php
2
  defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
 
 
 
4
  require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.state.expand.php');
5
  require_once (DUPLICATOR_PLUGIN_PATH.'classes/package/duparchive/class.pack.archive.duparchive.state.create.php');
6
  require_once (DUPLICATOR_PLUGIN_PATH.'lib/dup_archive/classes/class.duparchive.loggerbase.php');
35
  DUP_LOG::trace("start");
36
  try {
37
  DUP_Log::Open($package->NameHash);
 
38
 
39
  if ($buildProgress->retries > DUPLICATOR_MAX_BUILD_RETRIES) {
 
40
  $error_msg = __('Package build appears stuck so marking package as failed. Is the Max Worker Time set too high?.', 'duplicator');
41
  DUP_Log::error(esc_html__('Build Failure', 'duplicator'), esc_html($error_msg), Dup_ErrorBehavior::LogOnly);
42
  //$buildProgress->failed = true;
45
  ;
46
  return true;
47
  } else {
 
48
  // If all goes well retries will be reset to 0 at the end of this function.
49
  $buildProgress->retries++;
50
  $package->update();
52
 
53
  $done = false;
54
 
 
55
  DupArchiveEngine::init(new DUP_DupArchive_Logger(), null, $archive);
 
 
56
  DUP_Package::safeTmpCleanup(true);
57
 
58
  $compressDir = rtrim(DUP_Util::safePath($archive->PackDir), '/');
59
  $sqlPath = DUP_Settings::getSsdirTmpPath()."/{$package->Database->File}";
60
  $archivePath = DUP_Settings::getSsdirTmpPath()."/{$archive->File}";
61
  $scanFilepath = DUP_Settings::getSsdirTmpPath()."/{$package->NameHash}_scan.json";
 
 
62
  $skipArchiveFinalization = false;
63
  $json = '';
64
 
 
65
  if (file_exists($scanFilepath)) {
66
 
 
67
  $json = file_get_contents($scanFilepath);
68
 
69
  if (empty($json)) {
 
70
  $errorText = __("Scan file $scanFilepath is empty!", 'duplicator');
71
  $fixText = __("Click on \"Resolve This\" button to fix the JSON settings.", 'duplicator');
72
 
79
  return true;
80
  }
81
  } else {
 
82
  DUP_Log::trace("**** scan file $scanFilepath doesn't exist!!");
83
  $errorMessage = sprintf(__("ERROR: Can't find Scanfile %s. Please ensure there no non-English characters in the package or schedule name.", 'duplicator'), $scanFilepath);
84
 
90
  return true;
91
  }
92
 
 
93
  Dup_Log::TraceObject("buildprogress object", $buildProgress, false);
94
 
95
  $scanReport = json_decode($json);
103
  $filterDirsFormat = rtrim(str_replace(';', "\n\t", $filterDirs));
104
  $filterFilesFormat = rtrim(str_replace(';', "\n\t", $filterFiles));
105
 
 
106
  DUP_Log::info("\n********************************************************************************");
107
  DUP_Log::info("ARCHIVE Type=DUP Mode=DupArchive");
108
  DUP_Log::info("********************************************************************************");
112
  DUP_Log::Info("DIRS:\n\t{$filterDirsFormat}");
113
  DUP_Log::Info("FILES:\n\t{$filterFilesFormat}");
114
  DUP_Log::info("EXTS: {$filterExts}");
 
115
  DUP_Log::info("----------------------------------------");
116
  DUP_Log::info("COMPRESSING");
117
  DUP_Log::info("SIZE:\t".$scanReport->ARC->Size);
121
  $error_message = 'Invalid Scan Report Detected';
122
 
123
  DUP_Log::error($error_message, 'Invalid Scan Report Detected', Dup_ErrorBehavior::LogOnly);
 
124
  $buildProgress->set_failed($error_message);
125
  $package->setStatus(DUP_PackageStatus::ERROR);
126
  return true;
135
  $error_message = 'Error adding database.sql to archive';
136
 
137
  DUP_Log::error($error_message, $ex->getMessage(), Dup_ErrorBehavior::LogOnly);
 
138
  $buildProgress->set_failed($error_message);
139
  $package->setStatus(DUP_PackageStatus::ERROR);
140
  return true;
141
  }
142
 
143
  $buildProgress->archive_started = true;
 
144
  $buildProgress->retries = 0;
145
 
146
  $createState = DUP_DupArchive_Create_State::createNew($archivePath, $compressDir, self::WorkerTimeInSec, true, true);
147
  $createState->throttleDelayInUs = 0;
148
 
149
  $createState->save();
 
150
  $package->Update();
151
  }
152
 
153
  try {
 
 
154
  $createState = DUP_DupArchive_Create_State::get_instance();
155
 
156
  if ($buildProgress->retries > 1) {
157
  // Indicates it had problems before so move into robustness mode
158
  $createState->isRobust = true;
 
159
  $createState->save();
160
  }
161
 
168
  $buildProgress->set_build_failures($createState->failures);
169
 
170
  if ($createState->isCriticalFailurePresent()) {
 
171
  throw new Exception($createState->getFailureSummary());
172
  }
173
 
174
  $totalFileCount = count($scanReport->ARC->Files);
 
175
  $package->Status = DupLiteSnapLibUtil::getWorkPercent(DUP_PackageStatus::ARCSTART, DUP_PackageStatus::ARCVALIDATION, $totalFileCount, $createState->currentFileIndex);
 
176
  $buildProgress->retries = 0;
 
177
  $createState->save();
178
 
179
  DUP_LOG::TraceObject("Stored Create State", $createState);
187
  }
188
  }
189
  catch (Exception $ex) {
 
190
  $message = __('Problem adding items to archive.', 'duplicator').' '.$ex->getMessage();
191
 
192
  DUP_Log::error(__('Problems adding items to archive.', 'duplicator'), $message, Dup_ErrorBehavior::LogOnly);
197
  return true;
198
  }
199
 
 
 
200
  //-- Final Wrapup of the Archive
201
  if ((!$skipArchiveFinalization) && ($createState->working == false)) {
202
 
203
  DUP_LOG::Trace("Create state is not working and not skip archive finalization");
204
 
 
 
205
  if (!$buildProgress->installer_built) {
206
 
207
  if ($package->Installer->build($package, false)) {
214
  return;
215
  }
216
 
 
 
 
 
217
  DUP_Log::Trace("Installer has been built so running expand now");
218
 
219
  $expandState = DUP_DupArchive_Expand_State::getInstance(true);
237
  DUP_LOG::traceObject("EXPAND STATE AFTER SAVE", $expandState);
238
  } else {
239
 
 
240
  try {
241
 
242
  $expandState = DUP_DupArchive_Expand_State::getInstance();
243
 
244
  if ($buildProgress->retries > 1) {
 
245
  // Indicates it had problems before so move into robustness mode
246
  $expandState->isRobust = true;
 
247
  $expandState->save();
248
  }
249
 
250
  DUP_Log::traceObject('Resumed validation expand state', $expandState);
 
251
  DupArchiveEngine::expandArchive($expandState);
 
252
  $buildProgress->set_validation_failures($expandState->failures);
 
253
  $totalFileCount = count($scanReport->ARC->Files);
254
  $archiveSize = @filesize($expandState->archivePath);
255
 
260
  }
261
  catch (Exception $ex) {
262
  DUP_Log::Trace('Exception:'.$ex->getMessage().':'.$ex->getTraceAsString());
 
263
  $buildProgress->set_failed('Error validating archive');
264
  $package->setStatus(DUP_PackageStatus::ERROR);
265
  return true;
266
  }
267
 
268
  if ($expandState->isCriticalFailurePresent()) {
 
269
  // Fail immediately if critical failure present - even if havent completed processing the entire archive.
 
270
  $error_message = __('Critical failure present in validation', 'duplicator');
 
271
  DUP_Log::error($error_message, $expandState->getFailureSummary(), Dup_ErrorBehavior::LogOnly);
 
 
272
  $buildProgress->set_failed($error_message);
273
  return true;
274
  } else if (!$expandState->working) {
 
275
 
276
  $buildProgress->archive_built = true;
277
  $buildProgress->retries = 0;
 
 
278
  $package->update();
279
 
280
  $timerAllEnd = DUP_Util::getMicrotime();
290
  DUP_Log::info("VALIDATION WARNINGS: ".$expandState->getFailureSummary(false, true));
291
 
292
  $archive->file_count = $expandState->fileWriteCount + $expandState->directoryWriteCount;
 
293
  $package->update();
 
 
294
  $done = true;
295
  } else {
 
296
  $expandState->save();
 
297
  }
298
  }
299
  }
classes/utilities/class.u.php CHANGED
@@ -1,860 +1,860 @@
1
- <?php
2
- defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
-
4
- /**
5
- * Recursivly scans a directory and finds all sym-links and unreadable files
6
- *
7
- * Standard: PSR-2
8
- * @link http://www.php-fig.org/psr/psr-2
9
- *
10
- * @package Duplicator
11
- * @subpackage classes/utilities
12
- * @copyright (c) 2017, Snapcreek LLC
13
- *
14
- * @todo Refactor out IO methods into class.io.php file
15
- */
16
- class DUP_Util
17
- {
18
-
19
- /**
20
- * Is PHP 5.2.9 or better running
21
- */
22
- public static $on_php_529_plus;
23
-
24
- /**
25
- * Is PHP 5.3 or better running
26
- */
27
- public static $on_php_53_plus;
28
-
29
- /**
30
- * Is PHP 5.4 or better running
31
- */
32
- public static $on_php_54_plus;
33
-
34
- /**
35
- * Is PHP 7 or better running
36
- */
37
- public static $PHP7_plus;
38
-
39
- /**
40
- * array of ini disable functions
41
- *
42
- * @var array
43
- */
44
- private static $iniDisableFuncs = null;
45
-
46
- /**
47
- * Initialized on load (see end of file)
48
- */
49
- public static function init()
50
- {
51
- self::$on_php_529_plus = version_compare(PHP_VERSION, '5.2.9') >= 0;
52
- self::$on_php_53_plus = version_compare(PHP_VERSION, '5.3.0') >= 0;
53
- self::$on_php_54_plus = version_compare(PHP_VERSION, '5.4.0') >= 0;
54
- self::$PHP7_plus = version_compare(PHP_VERSION, '7.0.0', '>=');
55
- }
56
-
57
- public static function getArchitectureString()
58
- {
59
- $php_int_size = PHP_INT_SIZE;
60
-
61
- switch ($php_int_size) {
62
- case 4:
63
- return esc_html__('32-bit', 'duplicator');
64
- break;
65
- case 8:
66
- return esc_html__('64-bit', 'duplicator');
67
- break;
68
- default:
69
- return esc_html__('Unknown', 'duplicator');
70
- }
71
- }
72
-
73
- public static function objectCopy($srcObject, $destObject, $skipMemberArray = null)
74
- {
75
- foreach ($srcObject as $member_name => $member_value) {
76
- if (!is_object($member_value) && (($skipMemberArray == null) || !in_array($member_name, $skipMemberArray))) {
77
- // Skipping all object members
78
- $destObject->$member_name = $member_value;
79
- }
80
- }
81
- }
82
-
83
- public static function getWPCoreDirs()
84
- {
85
- $wp_core_dirs = array(get_home_path().'wp-admin', get_home_path().'wp-includes');
86
-
87
- //if wp_content is overrided
88
- $wp_path = get_home_path()."wp-content";
89
- if (get_home_path().'wp-content' != WP_CONTENT_DIR) {
90
- $wp_path = WP_CONTENT_DIR;
91
- }
92
- $wp_path = str_replace("\\", "/", $wp_path);
93
-
94
- $wp_core_dirs[] = $wp_path;
95
- $wp_core_dirs[] = $wp_path.'/plugins';
96
- $wp_core_dirs[] = $wp_path.'/themes';
97
-
98
- return $wp_core_dirs;
99
- }
100
-
101
- /**
102
- * return absolute path for the files that are core directories
103
- * @return string array
104
- */
105
- public static function getWPCoreFiles()
106
- {
107
- $wp_cored_dirs = array(get_home_path().'wp-config.php');
108
- return $wp_cored_dirs;
109
- }
110
-
111
- /**
112
- * Groups an array into arrays by a given key, or set of keys, shared between all array members.
113
- *
114
- * Based on {@author Jake Zatecky}'s {@link https://github.com/jakezatecky/array_group_by array_group_by()} function.
115
- * This variant allows $key to be closures.
116
- *
117
- * @param array $array The array to have grouping performed on.
118
- * @param mixed $key,... The key to group or split by. Can be a _string_, an _integer_, a _float_, or a _callable_.
119
- * - If the key is a callback, it must return a valid key from the array.
120
- * - If the key is _NULL_, the iterated element is skipped.
121
- * - string|oink callback ( mixed $item )
122
- *
123
- * @return array|null Returns a multidimensional array or `null` if `$key` is invalid.
124
- */
125
- public static function array_group_by(array $array, $key)
126
- {
127
- if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) {
128
- trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR);
129
- return null;
130
- }
131
- $func = (!is_string($key) && is_callable($key) ? $key : null);
132
- $_key = $key;
133
- // Load the new array, splitting by the target key
134
- $grouped = array();
135
- foreach ($array as $value) {
136
- $key = null;
137
- if (is_callable($func)) {
138
- $key = call_user_func($func, $value);
139
- } elseif (is_object($value) && isset($value->{$_key})) {
140
- $key = $value->{$_key};
141
- } elseif (isset($value[$_key])) {
142
- $key = $value[$_key];
143
- }
144
- if ($key === null) {
145
- continue;
146
- }
147
- $grouped[$key][] = $value;
148
- }
149
- // Recursively build a nested grouping if more parameters are supplied
150
- // Each grouped array value is grouped according to the next sequential key
151
- if (func_num_args() > 2) {
152
- $args = func_get_args();
153
- foreach ($grouped as $key => $value) {
154
- $params = array_merge(array($value), array_slice($args, 2, func_num_args()));
155
- $grouped[$key] = call_user_func_array('DUP_Util::array_group_by', $params);
156
- }
157
- }
158
- return $grouped;
159
- }
160
-
161
- /**
162
- * PHP_SAPI for FCGI requires a data flush of at least 256
163
- * bytes every 40 seconds or else it forces a script halt
164
- *
165
- * @return string A series of 256 space characters
166
- */
167
- public static function fcgiFlush()
168
- {
169
- echo(str_repeat(' ', 300));
170
- @flush();
171
- @ob_flush();
172
- }
173
-
174
- public static function isWpDebug()
175
- {
176
- return defined('WP_DEBUG') && WP_DEBUG;
177
- }
178
-
179
- /**
180
- * Returns the last N lines of a file. Equivalent to tail command
181
- *
182
- * @param string $filepath The full path to the file to be tailed
183
- * @param int $lines The number of lines to return with each tail call
184
- *
185
- * @return string The last N parts of the file
186
- */
187
- public static function tailFile($filepath, $lines = 2)
188
- {
189
- // Open file
190
- $f = @fopen($filepath, "rb");
191
- if ($f === false)
192
- return false;
193
-
194
- // Sets buffer size
195
- $buffer = 256;
196
-
197
- // Jump to last character
198
- fseek($f, -1, SEEK_END);
199
-
200
- // Read it and adjust line number if necessary
201
- // (Otherwise the result would be wrong if file doesn't end with a blank line)
202
- if (fread($f, 1) != "\n")
203
- $lines -= 1;
204
-
205
- // Start reading
206
- $output = '';
207
- $chunk = '';
208
-
209
- // While we would like more
210
- while (ftell($f) > 0 && $lines >= 0) {
211
- // Figure out how far back we should jump
212
- $seek = min(ftell($f), $buffer);
213
- // Do the jump (backwards, relative to where we are)
214
- fseek($f, -$seek, SEEK_CUR);
215
- // Read a chunk and prepend it to our output
216
- $output = ($chunk = fread($f, $seek)).$output;
217
- // Jump back to where we started reading
218
- fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
219
- // Decrease our line counter
220
- $lines -= substr_count($chunk, "\n");
221
- }
222
-
223
- // While we have too many lines
224
- // (Because of buffer size we might have read too many)
225
- while ($lines++ < 0) {
226
- // Find first newline and remove all text before that
227
- $output = substr($output, strpos($output, "\n") + 1);
228
- }
229
- fclose($f);
230
- return trim($output);
231
- }
232
-
233
- /**
234
- * Display human readable byte sizes
235
- *
236
- * @param int $size The size in bytes
237
- *
238
- * @return string The size of bytes readable such as 100KB, 20MB, 1GB etc.
239
- */
240
- public static function byteSize($size, $roundBy = 2)
241
- {
242
- try {
243
- $units = array('B', 'KB', 'MB', 'GB', 'TB');
244
- for ($i = 0; $size >= 1024 && $i < 4; $i++) {
245
- $size /= 1024;
246
- }
247
- return round($size, $roundBy).$units[$i];
248
- }
249
- catch (Exception $e) {
250
- return "n/a";
251
- }
252
- }
253
-
254
- /**
255
- * Makes path safe for any OS
256
- * Paths should ALWAYS READ be "/"
257
- * uni: /home/path/file.txt
258
- * win: D:/home/path/file.txt
259
- *
260
- * @param string $path The path to make safe
261
- *
262
- * @return string A path with all slashes facing "/"
263
- */
264
- public static function safePath($path)
265
- {
266
- return str_replace("\\", "/", $path);
267
- }
268
-
269
- /**
270
- * Get current microtime as a float. Method is used for simple profiling
271
- *
272
- * @see elapsedTime
273
- *
274
- * @return string A float in the form "msec sec", where sec is the number of seconds since the Unix epoch
275
- */
276
- public static function getMicrotime()
277
- {
278
- return microtime(true);
279
- }
280
-
281
- /**
282
- * Append the value to the string if it doesn't already exist
283
- *
284
- * @param string $string The string to append to
285
- * @param string $value The string to append to the $string
286
- *
287
- * @return string Returns the string with the $value appended once
288
- */
289
- public static function appendOnce($string, $value)
290
- {
291
- return $string.(substr($string, -1) == $value ? '' : $value);
292
- }
293
-
294
- /**
295
- * Return a string with the elapsed time
296
- *
297
- * @see getMicrotime()
298
- *
299
- * @param mixed number $end The final time in the sequence to measure
300
- * @param mixed number $start The start time in the sequence to measure
301
- *
302
- * @return string The time elapsed from $start to $end
303
- */
304
- public static function elapsedTime($end, $start)
305
- {
306
- return sprintf("%.2f sec.", abs($end - $start));
307
- }
308
-
309
- /**
310
- * List all of the files of a path
311
- *
312
- * @param string $path The full path to a system directory
313
- *
314
- * @return array of all files in that path
315
- *
316
- * Notes:
317
- * - Avoid using glob() as GLOB_BRACE is not an option on some operating systems
318
- * - Pre PHP 5.3 DirectoryIterator will crash on unreadable files
319
- * - Scandir will not crash on unreadable items, but will not return results
320
- */
321
- public static function listFiles($path = '.')
322
- {
323
- try {
324
- $files = array();
325
- if ($dh = opendir($path)) {
326
- while (($file = readdir($dh)) !== false) {
327
- if ($file == '.' || $file == '..')
328
- continue;
329
- $full_file_path = trailingslashit($path).$file;
330
- $files[] = str_replace("\\", '/', $full_file_path);
331
- }
332
- @closedir($dh);
333
- }
334
- return $files;
335
- }
336
- catch (Exception $exc) {
337
- $result = array();
338
- $files = @scandir($path);
339
- if (is_array($files)) {
340
- foreach ($files as $file) {
341
- $result[] = str_replace("\\", '/', $path).$file;
342
- }
343
- }
344
- return $result;
345
- }
346
- }
347
-
348
- /**
349
- * List all of the directories of a path
350
- *
351
- * @param string $path The full path to a system directory
352
- *
353
- * @return array of all dirs in the $path
354
- */
355
- public static function listDirs($path = '.')
356
- {
357
- $dirs = array();
358
-
359
- foreach (new DirectoryIterator($path) as $file) {
360
- if ($file->isDir() && !$file->isDot()) {
361
- $dirs[] = DUP_Util::safePath($file->getPathname());
362
- }
363
- }
364
- return $dirs;
365
- }
366
-
367
- /**
368
- * Does the directory have content
369
- *
370
- * @param string $path The full path to a system directory
371
- *
372
- * @return bool Returns true if directory is empty
373
- */
374
- public static function isDirectoryEmpty($path)
375
- {
376
- if (!is_readable($path))
377
- return NULL;
378
- return (count(scandir($path)) == 2);
379
- }
380
-
381
- /**
382
- * Size of the directory recursively in bytes
383
- *
384
- * @param string $path The full path to a system directory
385
- *
386
- * @return int Returns the size of the directory in bytes
387
- *
388
- */
389
- public static function getDirectorySize($path)
390
- {
391
- if (!file_exists($path))
392
- return 0;
393
- if (is_file($path))
394
- return filesize($path);
395
-
396
- $size = 0;
397
- $list = glob($path."/*");
398
- if (!empty($list)) {
399
- foreach ($list as $file)
400
- $size += self::getDirectorySize($file);
401
- }
402
- return $size;
403
- }
404
-
405
- /**
406
- * Can shell_exec be called on this server
407
- *
408
- * @return bool Returns true if shell_exec can be called on server
409
- *
410
- */
411
- public static function hasShellExec()
412
- {
413
- $cmds = array('shell_exec', 'escapeshellarg', 'escapeshellcmd', 'extension_loaded');
414
-
415
- //Function disabled at server level
416
- if (array_intersect($cmds, array_map('trim', explode(',', @ini_get('disable_functions')))))
417
- return apply_filters('duplicator_is_shellzip_available', false);
418
-
419
- //Suhosin: http://www.hardened-php.net/suhosin/
420
- //Will cause PHP to silently fail
421
- if (extension_loaded('suhosin')) {
422
- $suhosin_ini = @ini_get("suhosin.executor.func.blacklist");
423
- if (array_intersect($cmds, array_map('trim', explode(',', $suhosin_ini))))
424
- return apply_filters('duplicator_is_shellzip_available', false);
425
- }
426
-
427
- if (! function_exists('shell_exec')) {
428
- return apply_filters('duplicator_is_shellzip_available', false);
429
- }
430
-
431
- // Can we issue a simple echo command?
432
- if (!@shell_exec('echo duplicator'))
433
- return apply_filters('duplicator_is_shellzip_available', false);
434
-
435
- return apply_filters('duplicator_is_shellzip_available', true);
436
- }
437
-
438
- /**
439
- * Is the server running Windows operating system
440
- *
441
- * @return bool Returns true if operating system is Windows
442
- *
443
- */
444
- public static function isWindows()
445
- {
446
- if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
447
- return true;
448
- }
449
- return false;
450
- }
451
-
452
- /**
453
- * Wrap to prevent malware scanners from reporting false/positive
454
- * Switched from our old method to avoid WordFence reporting a false positive
455
- *
456
- * @param string $string The string to decrypt i.e. base64_decode
457
- *
458
- * @return string Returns the string base64 decoded
459
- */
460
- public static function installerUnscramble($string)
461
- {
462
- return base64_decode($string);
463
- }
464
-
465
- /**
466
- * Wrap to prevent malware scanners from reporting false/positive
467
- * Switched from our old method to avoid WordFence reporting a false positive
468
- *
469
- * @param string $string The string to decrypt i.e. base64_encode
470
- *
471
- * @return string Returns the string base64 encode
472
- */
473
- public static function installerScramble($string)
474
- {
475
- return base64_encode($string);
476
- }
477
- const SECURE_ISSUE_DIE = 'die';
478
- const SECURE_ISSUE_THROW = 'throw';
479
- const SECURE_ISSUE_RETURN = 'return';
480
-
481
- /**
482
- * Does the current user have the capability
483
- *
484
- * @param type $permission
485
- * @param type $exit // SECURE_ISSUE_DIE die script with die function
486
- * SECURE_ISSUE_THROW throw an exception if fail
487
- * SECURE_ISSUE_RETURN return false if fail
488
- *
489
- * @return boolean // return false is fail and $exit is SECURE_ISSUE_THROW
490
- * // true if success
491
- *
492
- * @throws Exception // thow exception if $exit is SECURE_ISSUE_THROW
493
- */
494
- public static function hasCapability($permission = 'read', $exit = self::SECURE_ISSUE_DIE)
495
- {
496
- $capability = apply_filters('wpfront_user_role_editor_duplicator_translate_capability', $permission);
497
-
498
- if (!current_user_can($capability)) {
499
- $exitMsg = __('You do not have sufficient permissions to access this page.', 'duplicator');
500
- DUP_LOG::Trace('You do not have sufficient permissions to access this page. PERMISSION: '.$permission);
501
-
502
- switch ($exit) {
503
- case self::SECURE_ISSUE_THROW:
504
- throw new Exception($exitMsg);
505
- case self::SECURE_ISSUE_RETURN:
506
- return false;
507
- case self::SECURE_ISSUE_DIE:
508
- default:
509
- wp_die($exitMsg);
510
- }
511
- }
512
- return true;
513
- }
514
-
515
- /**
516
- * Gets the name of the owner of the current PHP script
517
- *
518
- * @return string The name of the owner of the current PHP script
519
- */
520
- public static function getCurrentUser()
521
- {
522
- $unreadable = 'Undetectable';
523
- if (function_exists('get_current_user') && is_callable('get_current_user')) {
524
- $user = get_current_user();
525
- return strlen($user) ? $user : $unreadable;
526
- }
527
- return $unreadable;
528
- }
529
-
530
- /**
531
- * Gets the owner of the PHP process
532
- *
533
- * @return string Gets the owner of the PHP process
534
- */
535
- public static function getProcessOwner()
536
- {
537
- $unreadable = 'Undetectable';
538
- $user = '';
539
- try {
540
- if (function_exists('exec')) {
541
- $user = @exec('whoami');
542
- }
543
-
544
- if (!strlen($user) && function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
545
- $user = posix_getpwuid(posix_geteuid());
546
- $user = $user['name'];
547
- }
548
-
549
- return strlen($user) ? $user : $unreadable;
550
- }
551
- catch (Exception $ex) {
552
- return $unreadable;
553
- }
554
- }
555
-
556
- /**
557
- * Creates the snapshot directory if it doesn't already exist
558
- *
559
- * @return bool
560
- */
561
- public static function initSnapshotDirectory()
562
- {
563
- $error = false;
564
-
565
- $path_wproot = duplicator_get_abs_path();
566
- $path_ssdir = DUP_Settings::getSsdirPath();
567
- $path_plugin = DUP_Util::safePath(DUPLICATOR_PLUGIN_PATH);
568
-
569
- if (!file_exists($path_ssdir)) {
570
- $old_root_perm = @fileperms($path_wproot);
571
-
572
- //--------------------------------
573
- //CHMOD DIRECTORY ACCESS
574
- //wordpress root directory
575
- DupLiteSnapLibIOU::chmod($path_wproot, 'u+rwx');
576
-
577
- //snapshot directory
578
- if (DupLiteSnapLibIOU::dirWriteCheckOrMkdir($path_ssdir, 'u+rwx,go+rx') == false) {
579
- $error = true;
580
- }
581
-
582
- // restore original root perms
583
- DupLiteSnapLibIOU::chmod($path_wproot, $old_root_perm);
584
-
585
- if ($error) {
586
- return false;
587
- }
588
- }
589
-
590
- DupLiteSnapLibIOU::chmod($path_ssdir, 'u+rwx,go+rx');
591
-
592
- DupLiteSnapLibIOU::dirWriteCheckOrMkdir(DUP_Settings::getSsdirTmpPath(), 'u+rwx');
593
-
594
- //plugins dir/files
595
- DupLiteSnapLibIOU::dirWriteCheckOrMkdir($path_plugin.'files', 'u+rwx');
596
-
597
- //--------------------------------
598
- //FILE CREATION
599
- //SSDIR: Create Index File
600
- $fileName = $path_ssdir.'/index.php';
601
- if (!file_exists($fileName)) {
602
- $ssfile = @fopen($fileName, 'w');
603
- @fwrite($ssfile,
604
- '<?php error_reporting(0); if (stristr(php_sapi_name(), "fcgi")) { $url = "http://" . $_SERVER["HTTP_HOST"]; header("Location: {$url}/404.html");} else { header("HTTP/1.1 404 Not Found", true, 404);} exit(); ?>');
605
- @fclose($ssfile);
606
- }
607
-
608
- //SSDIR: Create .htaccess
609
- $storage_htaccess_off = DUP_Settings::Get('storage_htaccess_off');
610
- $fileName = $path_ssdir.'/.htaccess';
611
- if ($storage_htaccess_off) {
612
- @unlink($fileName);
613
- } else if (!file_exists($fileName)) {
614
- $htfile = @fopen($fileName, 'w');
615
- $htoutput = "Options -Indexes";
616
- @fwrite($htfile, $htoutput);
617
- @fclose($htfile);
618
- }
619
-
620
- //SSDIR: Robots.txt file
621
- $fileName = $path_ssdir.'/robots.txt';
622
- if (!file_exists($fileName)) {
623
- $robotfile = @fopen($fileName, 'w');
624
- @fwrite($robotfile,
625
- "User-agent: * \n"
626
- ."Disallow: /".DUP_Settings::SSDIR_NAME_LEGACY."/\n"
627
- ."Disallow: /".DUP_Settings::SSDIR_NAME_NEW."/");
628
- @fclose($robotfile);
629
- }
630
-
631
- return true;
632
- }
633
-
634
- /**
635
- * Attempts to get the file zip path on a users system
636
- *
637
- * @return null
638
- */
639
- public static function getZipPath()
640
- {
641
- $filepath = null;
642
-
643
- if (self::hasShellExec()) {
644
- if (shell_exec('hash zip 2>&1') == NULL) {
645
- $filepath = 'zip';
646
- } else {
647
- $possible_paths = array(
648
- '/usr/bin/zip',
649
- '/opt/local/bin/zip'
650
- //'C:/Program\ Files\ (x86)/GnuWin32/bin/zip.exe');
651
- );
652
-
653
- foreach ($possible_paths as $path) {
654
- if (@file_exists($path)) {
655
- $filepath = $path;
656
- break;
657
- }
658
- }
659
- }
660
- }
661
-
662
- return $filepath;
663
- }
664
-
665
- /**
666
- * Is the server PHP 5.3 or better
667
- *
668
- * @return bool Returns true if the server PHP 5.3 or better
669
- */
670
- public static function PHP53()
671
- {
672
- return version_compare(PHP_VERSION, '5.3.2', '>=');
673
- }
674
-
675
- /**
676
- * Returns an array of the WordPress core tables.
677
- *
678
- * @return array Returns all WP core tables
679
- */
680
- public static function getWPCoreTables()
681
- {
682
- global $wpdb;
683
- $result = array();
684
- foreach (self::getWPCoreTablesEnd() as $tend) {
685
- $result[] = $wpdb->prefix.$tend;
686
- }
687
- return $result;
688
- }
689
-
690
- public static function getWPCoreTablesEnd()
691
- {
692
- return array(
693
- 'commentmeta',
694
- 'comments',
695
- 'links',
696
- 'options',
697
- 'postmeta',
698
- 'posts',
699
- 'term_relationships',
700
- 'term_taxonomy',
701
- 'termmeta',
702
- 'terms',
703
- 'usermeta',
704
- 'blogs',
705
- 'blog_versions',
706
- 'blogmeta',
707
- 'users',
708
- 'site',
709
- 'sitemeta',
710
- 'signups',
711
- 'registration_log',
712
- 'blog_versions');
713
- }
714
-
715
- public static function isWPCoreTable($table)
716
- {
717
- global $wpdb;
718
-
719
- if (strpos($table, $wpdb->prefix) !== 0) {
720
- return false;
721
- }
722
-
723
- $subTName = substr($table, strlen($wpdb->prefix));
724
- $coreEnds = self::getWPCoreTablesEnd();
725
-
726
- if (in_array($subTName, $coreEnds)) {
727
- return true;
728
- } else if (is_multisite()) {
729
- $exTable = explode('_', $subTName);
730
- if (count($exTable) >= 2 && is_numeric($exTable[0])) {
731
- $tChekc = implode('_', array_slice($exTable, 1));
732
- if (get_blog_details((int) $exTable[0], false) !== false && in_array($tChekc, $coreEnds)) {
733
- return true;
734
- }
735
- }
736
- }
737
-
738
- return false;
739
- }
740
-
741
- public static function getWPBlogIdTable($table)
742
- {
743
- global $wpdb;
744
-
745
- if (!is_multisite() || strpos($table, $wpdb->prefix) !== 0) {
746
- return 0;
747
- }
748
-
749
- $subTName = substr($table, strlen($wpdb->prefix));
750
- $exTable = explode('_', $subTName);
751
- if (count($exTable) >= 2 && is_numeric($exTable[0]) && get_blog_details((int) $exTable[0], false) !== false) {
752
- return (int) $exTable[0];
753
- } else {
754
- return 0;
755
- }
756
- }
757
-
758
- /**
759
- * Check given table is exist in real
760
- *
761
- * @param $table string Table name
762
- * @return booleam
763
- */
764
- public static function isTableExists($table)
765
- {
766
- // It will clear the $GLOBALS['wpdb']->last_error var
767
- $GLOBALS['wpdb']->flush();
768
- $sql = "SELECT 1 FROM `".esc_sql($table)."` LIMIT 1;";
769
- $ret = $GLOBALS['wpdb']->get_var($sql);
770
- if (empty($GLOBALS['wpdb']->last_error))
771
- return true;
772
- return false;
773
- }
774
-
775
- /**
776
- * Finds if its a valid executable or not
777
- *
778
- * @param type $exe A non zero length executable path to find if that is executable or not.
779
- * @param type $expectedValue expected value for the result
780
- * @return boolean
781
- */
782
- public static function isExecutable($cmd)
783
- {
784
- if (strlen($cmd) < 1)
785
- return false;
786
-
787
- if (@is_executable($cmd)) {
788
- return true;
789
- }
790
-
791
- $output = shell_exec($cmd);
792
- if (!is_null($output)) {
793
- return true;
794
- }
795
-
796
- $output = shell_exec($cmd.' -?');
797
- if (!is_null($output)) {
798
- return true;
799
- }
800
-
801
- return false;
802
- }
803
-
804
- /**
805
- * Display human readable byte sizes
806
- *
807
- * @param string $size The size in bytes
808
- *
809
- * @return string Human readable bytes such as 50MB, 1GB
810
- */
811
- public static function readableByteSize($size)
812
- {
813
- try {
814
- $units = array('B', 'KB', 'MB', 'GB', 'TB');
815
- for ($i = 0; $size >= 1024 && $i < 4; $i++)
816
- $size /= 1024;
817
- return round($size, 2).$units[$i];
818
- }
819
- catch (Exception $e) {
820
- return "n/a";
821
- }
822
- }
823
-
824
- public static function getTablePrefix()
825
- {
826
- global $wpdb;
827
- $tablePrefix = (is_multisite() && is_plugin_active_for_network('duplicator/duplicator.php')) ? $wpdb->base_prefix : $wpdb->prefix;
828
- return $tablePrefix;
829
- }
830
-
831
- /**
832
- * return ini disable functions array
833
- *
834
- * @return array
835
- */
836
- public static function getIniDisableFuncs()
837
- {
838
- if (is_null(self::$iniDisableFuncs)) {
839
- $tmpFuncs = ini_get('disable_functions');
840
- $tmpFuncs = explode(',', $tmpFuncs);
841
- self::$iniDisableFuncs = array();
842
- foreach ($tmpFuncs as $cFunc) {
843
- self::$iniDisableFuncs[] = trim($cFunc);
844
- }
845
- }
846
-
847
- return self::$iniDisableFuncs;
848
- }
849
-
850
- /**
851
- * Check if function exists and isn't in ini disable_functions
852
- *
853
- * @param string $function_name
854
- * @return bool
855
- */
856
- public static function isIniFunctionEnalbe($function_name)
857
- {
858
- return function_exists($function_name) && !in_array($function_name, self::getIniDisableFuncs());
859
- }
860
  }
1
+ <?php
2
+ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
+
4
+ /**
5
+ * Recursivly scans a directory and finds all sym-links and unreadable files
6
+ *
7
+ * Standard: PSR-2
8
+ * @link http://www.php-fig.org/psr/psr-2
9
+ *
10
+ * @package Duplicator
11
+ * @subpackage classes/utilities
12
+ * @copyright (c) 2017, Snapcreek LLC
13
+ *
14
+ * @todo Refactor out IO methods into class.io.php file
15
+ */
16
+ class DUP_Util
17
+ {
18
+
19
+ /**
20
+ * Is PHP 5.2.9 or better running
21
+ */
22
+ public static $on_php_529_plus;
23
+
24
+ /**
25
+ * Is PHP 5.3 or better running
26
+ */
27
+ public static $on_php_53_plus;
28
+
29
+ /**
30
+ * Is PHP 5.4 or better running
31
+ */
32
+ public static $on_php_54_plus;
33
+
34
+ /**
35
+ * Is PHP 7 or better running
36
+ */
37
+ public static $PHP7_plus;
38
+
39
+ /**
40
+ * array of ini disable functions
41
+ *
42
+ * @var array
43
+ */
44
+ private static $iniDisableFuncs = null;
45
+
46
+ /**
47
+ * Initialized on load (see end of file)
48
+ */
49
+ public static function init()
50
+ {
51
+ self::$on_php_529_plus = version_compare(PHP_VERSION, '5.2.9') >= 0;
52
+ self::$on_php_53_plus = version_compare(PHP_VERSION, '5.3.0') >= 0;
53
+ self::$on_php_54_plus = version_compare(PHP_VERSION, '5.4.0') >= 0;
54
+ self::$PHP7_plus = version_compare(PHP_VERSION, '7.0.0', '>=');
55
+ }
56
+
57
+ public static function getArchitectureString()
58
+ {
59
+ $php_int_size = PHP_INT_SIZE;
60
+
61
+ switch ($php_int_size) {
62
+ case 4:
63
+ return esc_html__('32-bit', 'duplicator');
64
+ break;
65
+ case 8:
66
+ return esc_html__('64-bit', 'duplicator');
67
+ break;
68
+ default:
69
+ return esc_html__('Unknown', 'duplicator');
70
+ }
71
+ }
72
+
73
+ public static function objectCopy($srcObject, $destObject, $skipMemberArray = null)
74
+ {
75
+ foreach ($srcObject as $member_name => $member_value) {
76
+ if (!is_object($member_value) && (($skipMemberArray == null) || !in_array($member_name, $skipMemberArray))) {
77
+ // Skipping all object members
78
+ $destObject->$member_name = $member_value;
79
+ }
80
+ }
81
+ }
82
+
83
+ public static function getWPCoreDirs()
84
+ {
85
+ $wp_core_dirs = array(get_home_path().'wp-admin', get_home_path().'wp-includes');
86
+
87
+ //if wp_content is overrided
88
+ $wp_path = get_home_path()."wp-content";
89
+ if (get_home_path().'wp-content' != WP_CONTENT_DIR) {
90
+ $wp_path = WP_CONTENT_DIR;
91
+ }
92
+ $wp_path = str_replace("\\", "/", $wp_path);
93
+
94
+ $wp_core_dirs[] = $wp_path;
95
+ $wp_core_dirs[] = $wp_path.'/plugins';
96
+ $wp_core_dirs[] = $wp_path.'/themes';
97
+
98
+ return $wp_core_dirs;
99
+ }
100
+
101
+ /**
102
+ * return absolute path for the files that are core directories
103
+ * @return string array
104
+ */
105
+ public static function getWPCoreFiles()
106
+ {
107
+ $wp_cored_dirs = array(get_home_path().'wp-config.php');
108
+ return $wp_cored_dirs;
109
+ }
110
+
111
+ /**
112
+ * Groups an array into arrays by a given key, or set of keys, shared between all array members.
113
+ *
114
+ * Based on {@author Jake Zatecky}'s {@link https://github.com/jakezatecky/array_group_by array_group_by()} function.
115
+ * This variant allows $key to be closures.
116
+ *
117
+ * @param array $array The array to have grouping performed on.
118
+ * @param mixed $key,... The key to group or split by. Can be a _string_, an _integer_, a _float_, or a _callable_.
119
+ * - If the key is a callback, it must return a valid key from the array.
120
+ * - If the key is _NULL_, the iterated element is skipped.
121
+ * - string|oink callback ( mixed $item )
122
+ *
123
+ * @return array|null Returns a multidimensional array or `null` if `$key` is invalid.
124
+ */
125
+ public static function array_group_by(array $array, $key)
126
+ {
127
+ if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) {
128
+ trigger_error('array_group_by(): The key should be a string, an integer, or a callback', E_USER_ERROR);
129
+ return null;
130
+ }
131
+ $func = (!is_string($key) && is_callable($key) ? $key : null);
132
+ $_key = $key;
133
+ // Load the new array, splitting by the target key
134
+ $grouped = array();
135
+ foreach ($array as $value) {
136
+ $key = null;
137
+ if (is_callable($func)) {
138
+ $key = call_user_func($func, $value);
139
+ } elseif (is_object($value) && isset($value->{$_key})) {
140
+ $key = $value->{$_key};
141
+ } elseif (isset($value[$_key])) {
142
+ $key = $value[$_key];
143
+ }
144
+ if ($key === null) {
145
+ continue;
146
+ }
147
+ $grouped[$key][] = $value;
148
+ }
149
+ // Recursively build a nested grouping if more parameters are supplied
150
+ // Each grouped array value is grouped according to the next sequential key
151
+ if (func_num_args() > 2) {
152
+ $args = func_get_args();
153
+ foreach ($grouped as $key => $value) {
154
+ $params = array_merge(array($value), array_slice($args, 2, func_num_args()));
155
+ $grouped[$key] = call_user_func_array('DUP_Util::array_group_by', $params);
156
+ }
157
+ }
158
+ return $grouped;
159
+ }
160
+
161
+ /**
162
+ * PHP_SAPI for FCGI requires a data flush of at least 256
163
+ * bytes every 40 seconds or else it forces a script halt
164
+ *
165
+ * @return string A series of 256 space characters
166
+ */
167
+ public static function fcgiFlush()
168
+ {
169
+ echo(str_repeat(' ', 300));
170
+ @flush();
171
+ @ob_flush();
172
+ }
173
+
174
+ public static function isWpDebug()
175
+ {
176
+ return defined('WP_DEBUG') && WP_DEBUG;
177
+ }
178
+
179
+ /**
180
+ * Returns the last N lines of a file. Equivalent to tail command
181
+ *
182
+ * @param string $filepath The full path to the file to be tailed
183
+ * @param int $lines The number of lines to return with each tail call
184
+ *
185
+ * @return string The last N parts of the file
186
+ */
187
+ public static function tailFile($filepath, $lines = 2)
188
+ {
189
+ // Open file
190
+ $f = @fopen($filepath, "rb");
191
+ if ($f === false)
192
+ return false;
193
+
194
+ // Sets buffer size
195
+ $buffer = 256;
196
+
197
+ // Jump to last character
198
+ fseek($f, -1, SEEK_END);
199
+
200
+ // Read it and adjust line number if necessary
201
+ // (Otherwise the result would be wrong if file doesn't end with a blank line)
202
+ if (fread($f, 1) != "\n")
203
+ $lines -= 1;
204
+
205
+ // Start reading
206
+ $output = '';
207
+ $chunk = '';
208
+
209
+ // While we would like more
210
+ while (ftell($f) > 0 && $lines >= 0) {
211
+ // Figure out how far back we should jump
212
+ $seek = min(ftell($f), $buffer);
213
+ // Do the jump (backwards, relative to where we are)
214
+ fseek($f, -$seek, SEEK_CUR);
215
+ // Read a chunk and prepend it to our output
216
+ $output = ($chunk = fread($f, $seek)).$output;
217
+ // Jump back to where we started reading
218
+ fseek($f, -mb_strlen($chunk, '8bit'), SEEK_CUR);
219
+ // Decrease our line counter
220
+ $lines -= substr_count($chunk, "\n");
221
+ }
222
+
223
+ // While we have too many lines
224
+ // (Because of buffer size we might have read too many)
225
+ while ($lines++ < 0) {
226
+ // Find first newline and remove all text before that
227
+ $output = substr($output, strpos($output, "\n") + 1);
228
+ }
229
+ fclose($f);
230
+ return trim($output);
231
+ }
232
+
233
+ /**
234
+ * Display human readable byte sizes
235
+ *
236
+ * @param int $size The size in bytes
237
+ *
238
+ * @return string The size of bytes readable such as 100KB, 20MB, 1GB etc.
239
+ */
240
+ public static function byteSize($size, $roundBy = 2)
241
+ {
242
+ try {
243
+ $units = array('B', 'KB', 'MB', 'GB', 'TB');
244
+ for ($i = 0; $size >= 1024 && $i < 4; $i++) {
245
+ $size /= 1024;
246
+ }
247
+ return round($size, $roundBy).$units[$i];
248
+ }
249
+ catch (Exception $e) {
250
+ return "n/a";
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Makes path safe for any OS
256
+ * Paths should ALWAYS READ be "/"
257
+ * uni: /home/path/file.txt
258
+ * win: D:/home/path/file.txt
259
+ *
260
+ * @param string $path The path to make safe
261
+ *
262
+ * @return string A path with all slashes facing "/"
263
+ */
264
+ public static function safePath($path)
265
+ {
266
+ return str_replace("\\", "/", $path);
267
+ }
268
+
269
+ /**
270
+ * Get current microtime as a float. Method is used for simple profiling
271
+ *
272
+ * @see elapsedTime
273
+ *
274
+ * @return string A float in the form "msec sec", where sec is the number of seconds since the Unix epoch
275
+ */
276
+ public static function getMicrotime()
277
+ {
278
+ return microtime(true);
279
+ }
280
+
281
+ /**
282
+ * Append the value to the string if it doesn't already exist
283
+ *
284
+ * @param string $string The string to append to
285
+ * @param string $value The string to append to the $string
286
+ *
287
+ * @return string Returns the string with the $value appended once
288
+ */
289
+ public static function appendOnce($string, $value)
290
+ {
291
+ return $string.(substr($string, -1) == $value ? '' : $value);
292
+ }
293
+
294
+ /**
295
+ * Return a string with the elapsed time
296
+ *
297
+ * @see getMicrotime()
298
+ *
299
+ * @param mixed number $end The final time in the sequence to measure
300
+ * @param mixed number $start The start time in the sequence to measure
301
+ *
302
+ * @return string The time elapsed from $start to $end
303
+ */
304
+ public static function elapsedTime($end, $start)
305
+ {
306
+ return sprintf("%.2f sec.", abs($end - $start));
307
+ }
308
+
309
+ /**
310
+ * List all of the files of a path
311
+ *
312
+ * @param string $path The full path to a system directory
313
+ *
314
+ * @return array of all files in that path
315
+ *
316
+ * Notes:
317
+ * - Avoid using glob() as GLOB_BRACE is not an option on some operating systems
318
+ * - Pre PHP 5.3 DirectoryIterator will crash on unreadable files
319
+ * - Scandir will not crash on unreadable items, but will not return results
320
+ */
321
+ public static function listFiles($path = '.')
322
+ {
323
+ try {
324
+ $files = array();
325
+ if ($dh = opendir($path)) {
326
+ while (($file = readdir($dh)) !== false) {
327
+ if ($file == '.' || $file == '..')
328
+ continue;
329
+ $full_file_path = trailingslashit($path).$file;
330
+ $files[] = str_replace("\\", '/', $full_file_path);
331
+ }
332
+ @closedir($dh);
333
+ }
334
+ return $files;
335
+ }
336
+ catch (Exception $exc) {
337
+ $result = array();
338
+ $files = @scandir($path);
339
+ if (is_array($files)) {
340
+ foreach ($files as $file) {
341
+ $result[] = str_replace("\\", '/', $path).$file;
342
+ }
343
+ }
344
+ return $result;
345
+ }
346
+ }
347
+
348
+ /**
349
+ * List all of the directories of a path
350
+ *
351
+ * @param string $path The full path to a system directory
352
+ *
353
+ * @return array of all dirs in the $path
354
+ */
355
+ public static function listDirs($path = '.')
356
+ {
357
+ $dirs = array();
358
+
359
+ foreach (new DirectoryIterator($path) as $file) {
360
+ if ($file->isDir() && !$file->isDot()) {
361
+ $dirs[] = DUP_Util::safePath($file->getPathname());
362
+ }
363
+ }
364
+ return $dirs;
365
+ }
366
+
367
+ /**
368
+ * Does the directory have content
369
+ *
370
+ * @param string $path The full path to a system directory
371
+ *
372
+ * @return bool Returns true if directory is empty
373
+ */
374
+ public static function isDirectoryEmpty($path)
375
+ {
376
+ if (!is_readable($path))
377
+ return NULL;
378
+ return (count(scandir($path)) == 2);
379
+ }
380
+
381
+ /**
382
+ * Size of the directory recursively in bytes
383
+ *
384
+ * @param string $path The full path to a system directory
385
+ *
386
+ * @return int Returns the size of the directory in bytes
387
+ *
388
+ */
389
+ public static function getDirectorySize($path)
390
+ {
391
+ if (!file_exists($path))
392
+ return 0;
393
+ if (is_file($path))
394
+ return filesize($path);
395
+
396
+ $size = 0;
397
+ $list = glob($path."/*");
398
+ if (!empty($list)) {
399
+ foreach ($list as $file)
400
+ $size += self::getDirectorySize($file);
401
+ }
402
+ return $size;
403
+ }
404
+
405
+ /**
406
+ * Can shell_exec be called on this server
407
+ *
408
+ * @return bool Returns true if shell_exec can be called on server
409
+ *
410
+ */
411
+ public static function hasShellExec()
412
+ {
413
+ $cmds = array('shell_exec', 'escapeshellarg', 'escapeshellcmd', 'extension_loaded');
414
+
415
+ //Function disabled at server level
416
+ if (array_intersect($cmds, array_map('trim', explode(',', @ini_get('disable_functions')))))
417
+ return apply_filters('duplicator_is_shellzip_available', false);
418
+
419
+ //Suhosin: http://www.hardened-php.net/suhosin/
420
+ //Will cause PHP to silently fail
421
+ if (extension_loaded('suhosin')) {
422
+ $suhosin_ini = @ini_get("suhosin.executor.func.blacklist");
423
+ if (array_intersect($cmds, array_map('trim', explode(',', $suhosin_ini))))
424
+ return apply_filters('duplicator_is_shellzip_available', false);
425
+ }
426
+
427
+ if (! function_exists('shell_exec')) {
428
+ return apply_filters('duplicator_is_shellzip_available', false);
429
+ }
430
+
431
+ // Can we issue a simple echo command?
432
+ if (!@shell_exec('echo duplicator'))
433
+ return apply_filters('duplicator_is_shellzip_available', false);
434
+
435
+ return apply_filters('duplicator_is_shellzip_available', true);
436
+ }
437
+
438
+ /**
439
+ * Is the server running Windows operating system
440
+ *
441
+ * @return bool Returns true if operating system is Windows
442
+ *
443
+ */
444
+ public static function isWindows()
445
+ {
446
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
447
+ return true;
448
+ }
449
+ return false;
450
+ }
451
+
452
+ /**
453
+ * Wrap to prevent malware scanners from reporting false/positive
454
+ * Switched from our old method to avoid WordFence reporting a false positive
455
+ *
456
+ * @param string $string The string to decrypt i.e. base64_decode
457
+ *
458
+ * @return string Returns the string base64 decoded
459
+ */
460
+ public static function installerUnscramble($string)
461
+ {
462
+ return base64_decode($string);
463
+ }
464
+
465
+ /**
466
+ * Wrap to prevent malware scanners from reporting false/positive
467
+ * Switched from our old method to avoid WordFence reporting a false positive
468
+ *
469
+ * @param string $string The string to decrypt i.e. base64_encode
470
+ *
471
+ * @return string Returns the string base64 encode
472
+ */
473
+ public static function installerScramble($string)
474
+ {
475
+ return base64_encode($string);
476
+ }
477
+ const SECURE_ISSUE_DIE = 'die';
478
+ const SECURE_ISSUE_THROW = 'throw';
479
+ const SECURE_ISSUE_RETURN = 'return';
480
+
481
+ /**
482
+ * Does the current user have the capability
483
+ *
484
+ * @param type $permission
485
+ * @param type $exit // SECURE_ISSUE_DIE die script with die function
486
+ * SECURE_ISSUE_THROW throw an exception if fail
487
+ * SECURE_ISSUE_RETURN return false if fail
488
+ *
489
+ * @return boolean // return false is fail and $exit is SECURE_ISSUE_THROW
490
+ * // true if success
491
+ *
492
+ * @throws Exception // thow exception if $exit is SECURE_ISSUE_THROW
493
+ */
494
+ public static function hasCapability($permission = 'read', $exit = self::SECURE_ISSUE_DIE)
495
+ {
496
+ $capability = apply_filters('wpfront_user_role_editor_duplicator_translate_capability', $permission);
497
+
498
+ if (!current_user_can($capability)) {
499
+ $exitMsg = __('You do not have sufficient permissions to access this page.', 'duplicator');
500
+ DUP_LOG::Trace('You do not have sufficient permissions to access this page. PERMISSION: '.$permission);
501
+
502
+ switch ($exit) {
503
+ case self::SECURE_ISSUE_THROW:
504
+ throw new Exception($exitMsg);
505
+ case self::SECURE_ISSUE_RETURN:
506
+ return false;
507
+ case self::SECURE_ISSUE_DIE:
508
+ default:
509
+ wp_die($exitMsg);
510
+ }
511
+ }
512
+ return true;
513
+ }
514
+
515
+ /**
516
+ * Gets the name of the owner of the current PHP script
517
+ *
518
+ * @return string The name of the owner of the current PHP script
519
+ */
520
+ public static function getCurrentUser()
521
+ {
522
+ $unreadable = 'Undetectable';
523
+ if (function_exists('get_current_user') && is_callable('get_current_user')) {
524
+ $user = get_current_user();
525
+ return strlen($user) ? $user : $unreadable;
526
+ }
527
+ return $unreadable;
528
+ }
529
+
530
+ /**
531
+ * Gets the owner of the PHP process
532
+ *
533
+ * @return string Gets the owner of the PHP process
534
+ */
535
+ public static function getProcessOwner()
536
+ {
537
+ $unreadable = 'Undetectable';
538
+ $user = '';
539
+ try {
540
+ if (function_exists('exec')) {
541
+ $user = @exec('whoami');
542
+ }
543
+
544
+ if (!strlen($user) && function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
545
+ $user = posix_getpwuid(posix_geteuid());
546
+ $user = $user['name'];
547
+ }
548
+
549
+ return strlen($user) ? $user : $unreadable;
550
+ }
551
+ catch (Exception $ex) {
552
+ return $unreadable;
553
+ }
554
+ }
555
+
556
+ /**
557
+ * Creates the snapshot directory if it doesn't already exist
558
+ *
559
+ * @return bool
560
+ */
561
+ public static function initSnapshotDirectory()
562
+ {
563
+ $error = false;
564
+
565
+ $path_wproot = duplicator_get_abs_path();
566
+ $path_ssdir = DUP_Settings::getSsdirPath();
567
+ $path_plugin = DUP_Util::safePath(DUPLICATOR_PLUGIN_PATH);
568
+
569
+ if (!file_exists($path_ssdir)) {
570
+ $old_root_perm = @fileperms($path_wproot);
571
+
572
+ //--------------------------------
573
+ //CHMOD DIRECTORY ACCESS
574
+ //wordpress root directory
575
+ DupLiteSnapLibIOU::chmod($path_wproot, 'u+rwx');
576
+
577
+ //snapshot directory
578
+ if (DupLiteSnapLibIOU::dirWriteCheckOrMkdir($path_ssdir, 'u+rwx,go+rx') == false) {
579
+ $error = true;
580
+ }
581
+
582
+ // restore original root perms
583
+ DupLiteSnapLibIOU::chmod($path_wproot, $old_root_perm);
584
+
585
+ if ($error) {
586
+ return false;
587
+ }
588
+ }
589
+
590
+ DupLiteSnapLibIOU::chmod($path_ssdir, 'u+rwx,go+rx');
591
+
592
+ DupLiteSnapLibIOU::dirWriteCheckOrMkdir(DUP_Settings::getSsdirTmpPath(), 'u+rwx');
593
+
594
+ //plugins dir/files
595
+ DupLiteSnapLibIOU::dirWriteCheckOrMkdir($path_plugin.'files', 'u+rwx');
596
+
597
+ //--------------------------------
598
+ //FILE CREATION
599
+ //SSDIR: Create Index File
600
+ $fileName = $path_ssdir.'/index.php';
601
+ if (!file_exists($fileName)) {
602
+ $ssfile = @fopen($fileName, 'w');
603
+ @fwrite($ssfile,
604
+ '<?php error_reporting(0); if (stristr(php_sapi_name(), "fcgi")) { $url = "http://" . $_SERVER["HTTP_HOST"]; header("Location: {$url}/404.html");} else { header("HTTP/1.1 404 Not Found", true, 404);} exit(); ?>');
605
+ @fclose($ssfile);
606
+ }
607
+
608
+ //SSDIR: Create .htaccess
609
+ $storage_htaccess_off = DUP_Settings::Get('storage_htaccess_off');
610
+ $fileName = $path_ssdir.'/.htaccess';
611
+ if ($storage_htaccess_off) {
612
+ @unlink($fileName);
613
+ } else if (!file_exists($fileName)) {
614
+ $htfile = @fopen($fileName, 'w');
615
+ $htoutput = "Options -Indexes";
616
+ @fwrite($htfile, $htoutput);
617
+ @fclose($htfile);
618
+ }
619
+
620
+ //SSDIR: Robots.txt file
621
+ $fileName = $path_ssdir.'/robots.txt';
622
+ if (!file_exists($fileName)) {
623
+ $robotfile = @fopen($fileName, 'w');
624
+ @fwrite($robotfile,
625
+ "User-agent: * \n"
626
+ ."Disallow: /".DUP_Settings::SSDIR_NAME_LEGACY."/\n"
627
+ ."Disallow: /".DUP_Settings::SSDIR_NAME_NEW."/");
628
+ @fclose($robotfile);
629
+ }
630
+
631
+ return true;
632
+ }
633
+
634
+ /**
635
+ * Attempts to get the file zip path on a users system
636
+ *
637
+ * @return null
638
+ */
639
+ public static function getZipPath()
640
+ {
641
+ $filepath = null;
642
+
643
+ if (self::hasShellExec()) {
644
+ if (shell_exec('hash zip 2>&1') == NULL) {
645
+ $filepath = 'zip';
646
+ } else {
647
+ $possible_paths = array(
648
+ '/usr/bin/zip',
649
+ '/opt/local/bin/zip'
650
+ //'C:/Program\ Files\ (x86)/GnuWin32/bin/zip.exe');
651
+ );
652
+
653
+ foreach ($possible_paths as $path) {
654
+ if (@file_exists($path)) {
655
+ $filepath = $path;
656
+ break;
657
+ }
658
+ }
659
+ }
660
+ }
661
+
662
+ return $filepath;
663
+ }
664
+
665
+ /**
666
+ * Is the server PHP 5.3 or better
667
+ *
668
+ * @return bool Returns true if the server PHP 5.3 or better
669
+ */
670
+ public static function PHP53()
671
+ {
672
+ return version_compare(PHP_VERSION, '5.3.2', '>=');
673
+ }
674
+
675
+ /**
676
+ * Returns an array of the WordPress core tables.
677
+ *
678
+ * @return array Returns all WP core tables
679
+ */
680
+ public static function getWPCoreTables()
681
+ {
682
+ global $wpdb;
683
+ $result = array();
684
+ foreach (self::getWPCoreTablesEnd() as $tend) {
685
+ $result[] = $wpdb->prefix.$tend;
686
+ }
687
+ return $result;
688
+ }
689
+
690
+ public static function getWPCoreTablesEnd()
691
+ {
692
+ return array(
693
+ 'commentmeta',
694
+ 'comments',
695
+ 'links',
696
+ 'options',
697
+ 'postmeta',
698
+ 'posts',
699
+ 'term_relationships',
700
+ 'term_taxonomy',
701
+ 'termmeta',
702
+ 'terms',
703
+ 'usermeta',
704
+ 'blogs',
705
+ 'blog_versions',
706
+ 'blogmeta',
707
+ 'users',
708
+ 'site',
709
+ 'sitemeta',
710
+ 'signups',
711
+ 'registration_log',
712
+ 'blog_versions');
713
+ }
714
+
715
+ public static function isWPCoreTable($table)
716
+ {
717
+ global $wpdb;
718
+
719
+ if (strpos($table, $wpdb->prefix) !== 0) {
720
+ return false;
721
+ }
722
+
723
+ $subTName = substr($table, strlen($wpdb->prefix));
724
+ $coreEnds = self::getWPCoreTablesEnd();
725
+
726
+ if (in_array($subTName, $coreEnds)) {
727
+ return true;
728
+ } else if (is_multisite()) {
729
+ $exTable = explode('_', $subTName);
730
+ if (count($exTable) >= 2 && is_numeric($exTable[0])) {
731
+ $tChekc = implode('_', array_slice($exTable, 1));
732
+ if (get_blog_details((int) $exTable[0], false) !== false && in_array($tChekc, $coreEnds)) {
733
+ return true;
734
+ }
735
+ }
736
+ }
737
+
738
+ return false;
739
+ }
740
+
741
+ public static function getWPBlogIdTable($table)
742
+ {
743
+ global $wpdb;
744
+
745
+ if (!is_multisite() || strpos($table, $wpdb->prefix) !== 0) {
746
+ return 0;
747
+ }
748
+
749
+ $subTName = substr($table, strlen($wpdb->prefix));
750
+ $exTable = explode('_', $subTName);
751
+ if (count($exTable) >= 2 && is_numeric($exTable[0]) && get_blog_details((int) $exTable[0], false) !== false) {
752
+ return (int) $exTable[0];
753
+ } else {
754
+ return 0;
755
+ }
756
+ }
757
+
758
+ /**
759
+ * Check given table is exist in real
760
+ *
761
+ * @param $table string Table name
762
+ * @return booleam
763
+ */
764
+ public static function isTableExists($table)
765
+ {
766
+ // It will clear the $GLOBALS['wpdb']->last_error var
767
+ $GLOBALS['wpdb']->flush();
768
+ $sql = "SELECT 1 FROM `".esc_sql($table)."` LIMIT 1;";
769
+ $ret = $GLOBALS['wpdb']->get_var($sql);
770
+ if (empty($GLOBALS['wpdb']->last_error))
771
+ return true;
772
+ return false;
773
+ }
774
+
775
+ /**
776
+ * Finds if its a valid executable or not
777
+ *
778
+ * @param type $exe A non zero length executable path to find if that is executable or not.
779
+ * @param type $expectedValue expected value for the result
780
+ * @return boolean
781
+ */
782
+ public static function isExecutable($cmd)
783
+ {
784
+ if (strlen($cmd) < 1)
785
+ return false;
786
+
787
+ if (@is_executable($cmd)) {
788
+ return true;
789
+ }
790
+
791
+ $output = shell_exec($cmd);
792
+ if (!is_null($output)) {
793
+ return true;
794
+ }
795
+
796
+ $output = shell_exec($cmd.' -?');
797
+ if (!is_null($output)) {
798
+ return true;
799
+ }
800
+
801
+ return false;
802
+ }
803
+
804
+ /**
805
+ * Display human readable byte sizes
806
+ *
807
+ * @param string $size The size in bytes
808
+ *
809
+ * @return string Human readable bytes such as 50MB, 1GB
810
+ */
811
+ public static function readableByteSize($size)
812
+ {
813
+ try {
814
+ $units = array('B', 'KB', 'MB', 'GB', 'TB');
815
+ for ($i = 0; $size >= 1024 && $i < 4; $i++)
816
+ $size /= 1024;
817
+ return round($size, 2).$units[$i];
818
+ }
819
+ catch (Exception $e) {
820
+ return "n/a";
821
+ }
822
+ }
823
+
824
+ public static function getTablePrefix()
825
+ {
826
+ global $wpdb;
827
+ $tablePrefix = (is_multisite() && is_plugin_active_for_network('duplicator/duplicator.php')) ? $wpdb->base_prefix : $wpdb->prefix;
828
+ return $tablePrefix;
829
+ }
830
+
831
+ /**
832
+ * return ini disable functions array
833
+ *
834
+ * @return array
835
+ */
836
+ public static function getIniDisableFuncs()
837
+ {
838
+ if (is_null(self::$iniDisableFuncs)) {
839
+ $tmpFuncs = ini_get('disable_functions');
840
+ $tmpFuncs = explode(',', $tmpFuncs);
841
+ self::$iniDisableFuncs = array();
842
+ foreach ($tmpFuncs as $cFunc) {
843
+ self::$iniDisableFuncs[] = trim($cFunc);
844
+ }
845
+ }
846
+
847
+ return self::$iniDisableFuncs;
848
+ }
849
+
850
+ /**
851
+ * Check if function exists and isn't in ini disable_functions
852
+ *
853
+ * @param string $function_name
854
+ * @return bool
855
+ */
856
+ public static function isIniFunctionEnalbe($function_name)
857
+ {
858
+ return function_exists($function_name) && !in_array($function_name, self::getIniDisableFuncs());
859
+ }
860
  }
ctrls/class.web.services.php CHANGED
@@ -92,7 +92,7 @@ class DUP_Web_Services
92
  )
93
  ),
94
  'hash' => array(
95
- 'filter' => FILTER_SANITIZE_STRING,
96
  'flags' => FILTER_REQUIRE_SCALAR,
97
  'options' => array(
98
  'default' => false
@@ -178,7 +178,7 @@ class DUP_Web_Services
178
  throw new Exception('Security issue');
179
  }
180
 
181
- $notice_id = DupLiteSnapLibUtil::filterInputRequest('notice_id', FILTER_SANITIZE_STRING);
182
 
183
  if (empty($notice_id)) {
184
  throw new Exception(__('Invalid Request', 'duplicator'));
@@ -206,13 +206,13 @@ class DUP_Web_Services
206
  try {
207
  DUP_Util::hasCapability('export', DUP_Util::SECURE_ISSUE_THROW);
208
 
209
- $nonce = filter_input(INPUT_POST, 'nonce', FILTER_SANITIZE_STRING);
210
  if (!wp_verify_nonce($nonce, 'duplicator_admin_notice_to_dismiss')) {
211
  DUP_Log::trace('Security issue');
212
  throw new Exception('Security issue');
213
  }
214
 
215
- $noticeToDismiss = filter_input(INPUT_POST, 'notice', FILTER_SANITIZE_STRING);
216
  switch ($noticeToDismiss) {
217
  case DUP_UI_Notice::OPTION_KEY_ACTIVATE_PLUGINS_AFTER_INSTALL:
218
  case DUP_UI_Notice::OPTION_KEY_NEW_NOTICE_TEMPLATE:
92
  )
93
  ),
94
  'hash' => array(
95
+ 'filter' => FILTER_UNSAFE_RAW,
96
  'flags' => FILTER_REQUIRE_SCALAR,
97
  'options' => array(
98
  'default' => false
178
  throw new Exception('Security issue');
179
  }
180
 
181
+ $notice_id = DupLiteSnapLibUtil::filterInputRequest('notice_id', FILTER_UNSAFE_RAW);
182
 
183
  if (empty($notice_id)) {
184
  throw new Exception(__('Invalid Request', 'duplicator'));
206
  try {
207
  DUP_Util::hasCapability('export', DUP_Util::SECURE_ISSUE_THROW);
208
 
209
+ $nonce = filter_input(INPUT_POST, 'nonce', FILTER_UNSAFE_RAW);
210
  if (!wp_verify_nonce($nonce, 'duplicator_admin_notice_to_dismiss')) {
211
  DUP_Log::trace('Security issue');
212
  throw new Exception('Security issue');
213
  }
214
 
215
+ $noticeToDismiss = filter_input(INPUT_POST, 'notice', FILTER_UNSAFE_RAW);
216
  switch ($noticeToDismiss) {
217
  case DUP_UI_Notice::OPTION_KEY_ACTIVATE_PLUGINS_AFTER_INSTALL:
218
  case DUP_UI_Notice::OPTION_KEY_NEW_NOTICE_TEMPLATE:
ctrls/ctrl.ui.php CHANGED
@@ -1,165 +1,165 @@
1
- <?php
2
- defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
- // Exit if accessed directly
4
- if (! defined('DUPLICATOR_VERSION')) exit;
5
-
6
- require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
7
- require_once(DUPLICATOR_PLUGIN_PATH . '/classes/ui/class.ui.viewstate.php');
8
-
9
- /**
10
- * Controller for Tools
11
- * @package Duplicator\ctrls
12
- */
13
- class DUP_CTRL_UI extends DUP_CTRL_Base
14
- {
15
-
16
- function __construct()
17
- {
18
- add_action('wp_ajax_DUP_CTRL_UI_SaveViewState', array($this, 'SaveViewState'));
19
- }
20
-
21
-
22
- /**
23
- * Calls the SaveViewState and returns a JSON result
24
- *
25
- * @param string $_POST['key'] A unique key that identifies the state of the UI element
26
- * @param bool $_POST['value'] The value to store for the state of the UI element
27
- *
28
- * @notes: Testing: See Testing Interface
29
- * URL = /wp-admin/admin-ajax.php?action=DUP_CTRL_UI_SaveViewState
30
- *
31
- * <code>
32
- * //JavaScript Ajax Request
33
- * Duplicator.UI.SaveViewState('dup-pack-archive-panel', 1);
34
- *
35
- * //Call PHP Code
36
- * $view_state = DUP_UI_ViewState::getValue('dup-pack-archive-panel');
37
- * $ui_css_archive = ($view_state == 1) ? 'display:block' : 'display:none';
38
- * </code>
39
- */
40
- public function SaveViewState()
41
- {
42
- DUP_Handler::init_error_handler();
43
- check_ajax_referer('DUP_CTRL_UI_SaveViewState', 'nonce');
44
- DUP_Util::hasCapability('export');
45
-
46
- $payload = array(
47
- 'success' => false,
48
- 'message' => '',
49
- 'key' => '',
50
- 'value' => ''
51
- );
52
- $isValid = true;
53
-
54
- $inputData = filter_input_array(INPUT_POST, array(
55
- 'states' => array(
56
- 'filter' => FILTER_SANITIZE_STRING,
57
- 'flags' => FILTER_FORCE_ARRAY,
58
- 'options' => array(
59
- 'default' => array()
60
- )
61
- ),
62
- 'key' => array(
63
- 'filter' => FILTER_SANITIZE_STRING,
64
- 'options' => array(
65
- 'default' => false
66
- )
67
- ),
68
- 'value' => array(
69
- 'filter' => FILTER_SANITIZE_STRING,
70
- 'options' => array(
71
- 'default' => false
72
- )
73
- )
74
- ));
75
-
76
- if (is_array($inputData) && is_array($inputData['states'])) {
77
- foreach ($inputData['states'] as $index => $state) {
78
- $filteredState = filter_var_array($state, array(
79
- 'key' => array(
80
- 'filter' => FILTER_SANITIZE_STRING,
81
- 'options' => array(
82
- 'default' => false
83
- )
84
- ),
85
- 'value' => array(
86
- 'filter' => FILTER_SANITIZE_STRING,
87
- 'options' => array(
88
- 'default' => false
89
- )
90
- )
91
- ));
92
-
93
- if ($filteredState['key'] === false && $filteredState['value']) {
94
- $isValid = false;
95
- break;
96
- }
97
- $inputData['states'][$index] = $filteredState;
98
- }
99
- }
100
-
101
- if ($inputData['key'] === false || $inputData['value'] === false) {
102
- $isValid = false;
103
- }
104
-
105
- $result = new DUP_CTRL_Result($this);
106
- try {
107
- if (!$isValid) {
108
- throw new Exception(__('Invalid Request.', 'duplicator'));
109
- }
110
-
111
- if (!empty($inputData['states'])) {
112
- $view_state = DUP_UI_ViewState::getArray();
113
- $last_key = '';
114
- foreach ($inputData['states'] as $state) {
115
- $view_state[$state['key']] = $state['value'];
116
- $last_key = $state['key'];
117
- }
118
- $payload['success'] = DUP_UI_ViewState::setArray($view_state);
119
- $payload['key'] = esc_html($last_key);
120
- $payload['value'] = esc_html($view_state[$last_key]);
121
- } else {
122
- $payload['success'] = DUP_UI_ViewState::save($inputData['key'], $inputData['value']);
123
- $payload['key'] = esc_html($inputData['key']);
124
- $payload['value'] = esc_html($inputData['value']);
125
- }
126
-
127
- //RETURN RESULT
128
- $test = ($payload['success'])
129
- ? DUP_CTRL_Status::SUCCESS
130
- : DUP_CTRL_Status::FAILED;
131
- return $result->process($payload, $test);
132
- } catch (Exception $exc) {
133
- $result->processError($exc);
134
- }
135
- }
136
-
137
- /**
138
- * Returns a JSON list of all saved view state items
139
- *
140
- *
141
- * <code>
142
- * See SaveViewState()
143
- * </code>
144
- */
145
- public function GetViewStateList()
146
- {
147
- $result = new DUP_CTRL_Result($this);
148
-
149
- try
150
- {
151
- //CONTROLLER LOGIC
152
- $payload = DUP_UI_ViewState::getArray();
153
-
154
- //RETURN RESULT
155
- $test = (is_array($payload) && count($payload))
156
- ? DUP_CTRL_Status::SUCCESS
157
- : DUP_CTRL_Status::FAILED;
158
- return $result->process($payload, $test);
159
- }
160
- catch (Exception $exc)
161
- {
162
- $result->processError($exc);
163
- }
164
- }
165
- }
1
+ <?php
2
+ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
+ // Exit if accessed directly
4
+ if (! defined('DUPLICATOR_VERSION')) exit;
5
+
6
+ require_once(DUPLICATOR_PLUGIN_PATH . '/ctrls/ctrl.base.php');
7
+ require_once(DUPLICATOR_PLUGIN_PATH . '/classes/ui/class.ui.viewstate.php');
8
+
9
+ /**
10
+ * Controller for Tools
11
+ * @package Duplicator\ctrls
12
+ */
13
+ class DUP_CTRL_UI extends DUP_CTRL_Base
14
+ {
15
+
16
+ function __construct()
17
+ {
18
+ add_action('wp_ajax_DUP_CTRL_UI_SaveViewState', array($this, 'SaveViewState'));
19
+ }
20
+
21
+
22
+ /**
23
+ * Calls the SaveViewState and returns a JSON result
24
+ *
25
+ * @param string $_POST['key'] A unique key that identifies the state of the UI element
26
+ * @param bool $_POST['value'] The value to store for the state of the UI element
27
+ *
28
+ * @notes: Testing: See Testing Interface
29
+ * URL = /wp-admin/admin-ajax.php?action=DUP_CTRL_UI_SaveViewState
30
+ *
31
+ * <code>
32
+ * //JavaScript Ajax Request
33
+ * Duplicator.UI.SaveViewState('dup-pack-archive-panel', 1);
34
+ *
35
+ * //Call PHP Code
36
+ * $view_state = DUP_UI_ViewState::getValue('dup-pack-archive-panel');
37
+ * $ui_css_archive = ($view_state == 1) ? 'display:block' : 'display:none';
38
+ * </code>
39
+ */
40
+ public function SaveViewState()
41
+ {
42
+ DUP_Handler::init_error_handler();
43
+ check_ajax_referer('DUP_CTRL_UI_SaveViewState', 'nonce');
44
+ DUP_Util::hasCapability('export');
45
+
46
+ $payload = array(
47
+ 'success' => false,
48
+ 'message' => '',
49
+ 'key' => '',
50
+ 'value' => ''
51
+ );
52
+ $isValid = true;
53
+
54
+ $inputData = filter_input_array(INPUT_POST, array(
55
+ 'states' => array(
56
+ 'filter' => FILTER_UNSAFE_RAW,
57
+ 'flags' => FILTER_FORCE_ARRAY,
58
+ 'options' => array(
59
+ 'default' => array()
60
+ )
61
+ ),
62
+ 'key' => array(
63
+ 'filter' => FILTER_UNSAFE_RAW,
64
+ 'options' => array(
65
+ 'default' => false
66
+ )
67
+ ),
68
+ 'value' => array(
69
+ 'filter' => FILTER_UNSAFE_RAW,
70
+ 'options' => array(
71
+ 'default' => false
72
+ )
73
+ )
74
+ ));
75
+
76
+ if (is_array($inputData) && is_array($inputData['states'])) {
77
+ foreach ($inputData['states'] as $index => $state) {
78
+ $filteredState = filter_var_array($state, array(
79
+ 'key' => array(
80
+ 'filter' => FILTER_UNSAFE_RAW,
81
+ 'options' => array(
82
+ 'default' => false
83
+ )
84
+ ),
85
+ 'value' => array(
86
+ 'filter' => FILTER_UNSAFE_RAW,
87
+ 'options' => array(
88
+ 'default' => false
89
+ )
90
+ )
91
+ ));
92
+
93
+ if ($filteredState['key'] === false && $filteredState['value']) {
94
+ $isValid = false;
95
+ break;
96
+ }
97
+ $inputData['states'][$index] = $filteredState;
98
+ }
99
+ }
100
+
101
+ if ($inputData['key'] === false || $inputData['value'] === false) {
102
+ $isValid = false;
103
+ }
104
+
105
+ $result = new DUP_CTRL_Result($this);
106
+ try {
107
+ if (!$isValid) {
108
+ throw new Exception(__('Invalid Request.', 'duplicator'));
109
+ }
110
+
111
+ if (!empty($inputData['states'])) {
112
+ $view_state = DUP_UI_ViewState::getArray();
113
+ $last_key = '';
114
+ foreach ($inputData['states'] as $state) {
115
+ $view_state[$state['key']] = $state['value'];
116
+ $last_key = $state['key'];
117
+ }
118
+ $payload['success'] = DUP_UI_ViewState::setArray($view_state);
119
+ $payload['key'] = esc_html($last_key);
120
+ $payload['value'] = esc_html($view_state[$last_key]);
121
+ } else {
122
+ $payload['success'] = DUP_UI_ViewState::save($inputData['key'], $inputData['value']);
123
+ $payload['key'] = esc_html($inputData['key']);
124
+ $payload['value'] = esc_html($inputData['value']);
125
+ }
126
+
127
+ //RETURN RESULT
128
+ $test = ($payload['success'])
129
+ ? DUP_CTRL_Status::SUCCESS
130
+ : DUP_CTRL_Status::FAILED;
131
+ return $result->process($payload, $test);
132
+ } catch (Exception $exc) {
133
+ $result->processError($exc);
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Returns a JSON list of all saved view state items
139
+ *
140
+ *
141
+ * <code>
142
+ * See SaveViewState()
143
+ * </code>
144
+ */
145
+ public function GetViewStateList()
146
+ {
147
+ $result = new DUP_CTRL_Result($this);
148
+
149
+ try
150
+ {
151
+ //CONTROLLER LOGIC
152
+ $payload = DUP_UI_ViewState::getArray();
153
+
154
+ //RETURN RESULT
155
+ $test = (is_array($payload) && count($payload))
156
+ ? DUP_CTRL_Status::SUCCESS
157
+ : DUP_CTRL_Status::FAILED;
158
+ return $result->process($payload, $test);
159
+ }
160
+ catch (Exception $exc)
161
+ {
162
+ $result->processError($exc);
163
+ }
164
+ }
165
+ }
deactivation.php CHANGED
@@ -363,21 +363,21 @@ if (!function_exists('duplicator_submit_uninstall_reason_action')) {
363
  $isValid = true;
364
  $inputData = filter_input_array(INPUT_POST, array(
365
  'reason_id' => array(
366
- 'filter' => FILTER_SANITIZE_STRING,
367
  'flags' => FILTER_REQUIRE_SCALAR,
368
  'options' => array(
369
  'default' => false
370
  )
371
  ),
372
  'plugin' => array(
373
- 'filter' => FILTER_SANITIZE_STRING,
374
  'flags' => FILTER_REQUIRE_SCALAR,
375
  'options' => array(
376
  'default' => false
377
  )
378
  ),
379
  'reason_info' => array(
380
- 'filter' => FILTER_SANITIZE_STRING,
381
  'flags' => FILTER_REQUIRE_SCALAR,
382
  'options' => array(
383
  'default' => ''
363
  $isValid = true;
364
  $inputData = filter_input_array(INPUT_POST, array(
365
  'reason_id' => array(
366
+ 'filter' => FILTER_UNSAFE_RAW,
367
  'flags' => FILTER_REQUIRE_SCALAR,
368
  'options' => array(
369
  'default' => false
370
  )
371
  ),
372
  'plugin' => array(
373
+ 'filter' => FILTER_UNSAFE_RAW,
374
  'flags' => FILTER_REQUIRE_SCALAR,
375
  'options' => array(
376
  'default' => false
377
  )
378
  ),
379
  'reason_info' => array(
380
+ 'filter' => FILTER_UNSAFE_RAW,
381
  'flags' => FILTER_REQUIRE_SCALAR,
382
  'options' => array(
383
  'default' => ''
define.php CHANGED
@@ -5,8 +5,8 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
5
 
6
  if (function_exists('plugin_dir_url'))
7
  {
8
- define('DUPLICATOR_VERSION', '1.4.4');
9
- define('DUPLICATOR_VERSION_BUILD', '2022-02-01_14:00');
10
  define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
11
  define('DUPLICATOR_SITE_URL', get_site_url());
12
 
5
 
6
  if (function_exists('plugin_dir_url'))
7
  {
8
+ define('DUPLICATOR_VERSION', '1.4.5');
9
+ define('DUPLICATOR_VERSION_BUILD', '2022-04-12_19:00');
10
  define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
11
  define('DUPLICATOR_SITE_URL', get_site_url());
12
 
duplicator.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Duplicator
4
  Plugin URI: https://snapcreek.com/duplicator/duplicator-free/
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.4.4
7
  Requires at least: 4.0
8
  Tested up to: 5.9
9
  Requires PHP: 5.3.8
3
  Plugin Name: Duplicator
4
  Plugin URI: https://snapcreek.com/duplicator/duplicator-free/
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.4.5
7
  Requires at least: 4.0
8
  Tested up to: 5.9
9
  Requires PHP: 5.3.8
installer/dup-installer/assets/inc.js.php CHANGED
@@ -1,227 +1,227 @@
1
- <?php defined('ABSPATH') || defined('DUPXABSPATH') || exit; ?>
2
- <script>
3
- //Unique namespace
4
- DUPX = new Object();
5
- DUPX.Util = new Object();
6
- DUPX.Const = new Object();
7
- DUPX.GLB_DEBUG = <?php echo ($_GET['debug'] || $GLOBALS['DEBUG_JS']) ? 'true' : 'false'; ?>;
8
-
9
- DUPX.parseJSON = function(mixData) {
10
- try {
11
- var parsed = JSON.parse(mixData);
12
- return parsed;
13
- } catch (e) {
14
- console.log("JSON parse failed - 1");
15
- console.log(mixData);
16
- }
17
-
18
- if (mixData.indexOf('[') > -1 && mixData.indexOf('{') > -1) {
19
- if (mixData.indexOf('{') < mixData.indexOf('[')) {
20
- var startBracket = '{';
21
- var endBracket = '}';
22
- } else {
23
- var startBracket = '[';
24
- var endBracket = ']';
25
- }
26
- } else if (mixData.indexOf('[') > -1 && mixData.indexOf('{') === -1) {
27
- var startBracket = '[';
28
- var endBracket = ']';
29
- } else {
30
- var startBracket = '{';
31
- var endBracket = '}';
32
- }
33
-
34
- var jsonStartPos = mixData.indexOf(startBracket);
35
- var jsonLastPos = mixData.lastIndexOf(endBracket);
36
- if (jsonStartPos > -1 && jsonLastPos > -1) {
37
- var expectedJsonStr = mixData.slice(jsonStartPos, jsonLastPos + 1);
38
- try {
39
- var parsed = JSON.parse(expectedJsonStr);
40
- return parsed;
41
- } catch (e) {
42
- console.log("JSON parse failed - 2");
43
- console.log(mixData);
44
- throw e;
45
- return false;
46
- }
47
- }
48
- throw "could not parse the JSON";
49
- return false;
50
- }
51
-
52
- DUPX.showProgressBar = function ()
53
- {
54
- DUPX.animateProgressBar('progress-bar');
55
- $('#ajaxerr-area').hide();
56
- $('#progress-area').show();
57
- }
58
-
59
- DUPX.hideProgressBar = function ()
60
- {
61
- $('#progress-area').hide(100);
62
- $('#ajaxerr-area').fadeIn(400);
63
- }
64
-
65
- DUPX.animateProgressBar = function(id) {
66
- //Create Progress Bar
67
- var $mainbar = $("#" + id);
68
- $mainbar.progressbar({ value: 100 });
69
- $mainbar.height(25);
70
- runAnimation($mainbar);
71
-
72
- function runAnimation($pb) {
73
- $pb.css({ "padding-left": "0%", "padding-right": "90%" });
74
- $pb.progressbar("option", "value", 100);
75
- $pb.animate({ paddingLeft: "90%", paddingRight: "0%" }, 3500, "linear", function () { runAnimation($pb); });
76
- }
77
- }
78
-
79
- DUPX.initToggle = function() {
80
- $("body").on('click', "*[data-type~='toggle']", DUPX.toggleClick);
81
-
82
- var hasFailedReq = false;
83
- $("*[data-type~='auto'][data-status='fail']").each(function(){
84
- hasFailedReq = true;
85
- $(this).trigger('click');
86
- });
87
-
88
- $("*[data-type~='auto'][data-status='warn']").each(function(){
89
- if (hasFailedReq) {
90
- return ;
91
- }
92
-
93
- $(this).trigger('click');
94
- });
95
- }
96
-
97
- DUPX.toggleAllReqs = function(id) {
98
- $(id + " *[data-type='toggle auto']").each(function() {
99
- $(this).trigger('click');
100
- });
101
- }
102
-
103
- DUPX.toggleAllNotices = function(id) {
104
- $(id + " *[data-type='toggle']").each(function() {
105
- $(this).trigger('click');
106
- });
107
- }
108
-
109
- DUPX.toggleClick = function()
110
- {
111
- var src = 0;
112
- var id = $(this).attr('data-target');
113
- var text = $(this).text().replace(/\+|\-/, "");
114
- var icon = $(this).find('i.fa');
115
- var target = $(id);
116
- var list = new Array();
117
-
118
- var style = [
119
- { open: "fa-minus-square",
120
- close: "fa-plus-square"
121
- },
122
- { open: "fa-caret-down",
123
- close: "fa-caret-right"
124
- }];
125
-
126
- //Create src
127
- for (i = 0; i < style.length; i++) {
128
- if ($(icon).hasClass(style[i].open) || $(icon).hasClass(style[i].close)) {
129
- src = i;
130
- break;
131
- }
132
- }
133
-
134
- //Build remove list
135
- for (i = 0; i < style.length; i++) {
136
- list.push(style[i].open);
137
- list.push(style[i].close);
138
- }
139
-
140
- $(icon).removeClass(list.join(" "));
141
- if (target.is(':hidden') ) {
142
- (icon.length)
143
- ? $(icon).addClass(style[src].open )
144
- : $(this).html("- " + text );
145
- target.show().removeClass('no-display');
146
- } else {
147
- (icon.length)
148
- ? $(icon).addClass(style[src].close)
149
- : $(this).html("+ " + text );
150
- target.hide();
151
- }
152
- }
153
-
154
- DUPX.Util.formatBytes = function (bytes,decimals)
155
- {
156
- if(bytes == 0) return '0 Byte';
157
- var k = 1000;
158
- var dm = decimals + 1 || 3;
159
- var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
160
- var i = Math.floor(Math.log(bytes) / Math.log(k));
161
- return (bytes / Math.pow(k, i)).toPrecision(dm) + ' ' + sizes[i];
162
- }
163
-
164
- $(document).ready(function()
165
- {
166
- $('body').on( "click", ".copy-to-clipboard-block button", function(e) {
167
- e.preventDefault();
168
- var button = $(this);
169
- var buttonText = button.html();
170
- var textarea = button.parent().find("textarea")[0];
171
-
172
- textarea.select();
173
-
174
- try {
175
- message = document.execCommand('copy') ? "Copied to Clipboard" : 'Unable to copy';
176
- } catch (err) {
177
- console.log(err);
178
- }
179
-
180
- button.html(message);
181
-
182
- setTimeout(function () {
183
- button.text(buttonText);
184
- }, 2000);
185
- });
186
-
187
- <?php if (DUPX_Log::isLevel(DUPX_Log::LV_DEBUG)) : ?>
188
- $("div.dupx-debug input[type=hidden], div.dupx-debug textarea").each(function() {
189
- var label = '<label>' + $(this).attr('name') + ':</label>';
190
- $(this).before(label);
191
- $(this).after('<br/>');
192
- });
193
- $("div.dupx-debug input[type=hidden]").each(function() {
194
- $(this).attr('type', 'text');
195
- });
196
-
197
- $("div.dupx-debug").prepend('<div class="dupx-debug-hdr">Debug View</div>');
198
- <?php endif; ?>
199
-
200
- DUPX.loadQtip = function()
201
- {
202
- //Look for tooltip data
203
- $('i[data-tooltip!=""]').qtip({
204
- content: {
205
- attr: 'data-tooltip',
206
- title: {
207
- text: function() { return $(this).attr('data-tooltip-title'); }
208
- }
209
- },
210
- style: {
211
- classes: 'qtip-light qtip-rounded qtip-shadow',
212
- width: 500
213
- },
214
- position: {
215
- my: 'top left',
216
- at: 'bottom center'
217
- }
218
- });
219
- }
220
-
221
- DUPX.loadQtip();
222
-
223
- });
224
-
225
- </script>
226
- <?php
227
  DUPX_U_Html::js();
1
+ <?php defined('ABSPATH') || defined('DUPXABSPATH') || exit; ?>
2
+ <script>
3
+ //Unique namespace
4
+ DUPX = new Object();
5
+ DUPX.Util = new Object();
6
+ DUPX.Const = new Object();
7
+ DUPX.GLB_DEBUG = <?php echo ($_GET['debug'] || $GLOBALS['DEBUG_JS']) ? 'true' : 'false'; ?>;
8
+
9
+ DUPX.parseJSON = function(mixData) {
10
+ try {
11
+ var parsed = JSON.parse(mixData);
12
+ return parsed;
13
+ } catch (e) {
14
+ console.log("JSON parse failed - 1");
15
+ console.log(mixData);
16
+ }
17
+
18
+ if (mixData.indexOf('[') > -1 && mixData.indexOf('{') > -1) {
19
+ if (mixData.indexOf('{') < mixData.indexOf('[')) {
20
+ var startBracket = '{';
21
+ var endBracket = '}';
22
+ } else {
23
+ var startBracket = '[';
24
+ var endBracket = ']';
25
+ }
26
+ } else if (mixData.indexOf('[') > -1 && mixData.indexOf('{') === -1) {
27
+ var startBracket = '[';
28
+ var endBracket = ']';
29
+ } else {
30
+ var startBracket = '{';
31
+ var endBracket = '}';
32
+ }
33
+
34
+ var jsonStartPos = mixData.indexOf(startBracket);
35
+ var jsonLastPos = mixData.lastIndexOf(endBracket);
36
+ if (jsonStartPos > -1 && jsonLastPos > -1) {
37
+ var expectedJsonStr = mixData.slice(jsonStartPos, jsonLastPos + 1);
38
+ try {
39
+ var parsed = JSON.parse(expectedJsonStr);
40
+ return parsed;
41
+ } catch (e) {
42
+ console.log("JSON parse failed - 2");
43
+ console.log(mixData);
44
+ throw e;
45
+ return false;
46
+ }
47
+ }
48
+ throw "could not parse the JSON";
49
+ return false;
50
+ }
51
+
52
+ DUPX.showProgressBar = function ()
53
+ {
54
+ DUPX.animateProgressBar('progress-bar');
55
+ $('#ajaxerr-area').hide();
56
+ $('#progress-area').show();
57
+ }
58
+
59
+ DUPX.hideProgressBar = function ()
60
+ {
61
+ $('#progress-area').hide(100);
62
+ $('#ajaxerr-area').fadeIn(400);
63
+ }
64
+
65
+ DUPX.animateProgressBar = function(id) {
66
+ //Create Progress Bar
67
+ var $mainbar = $("#" + id);
68
+ $mainbar.progressbar({ value: 100 });
69
+ $mainbar.height(25);
70
+ runAnimation($mainbar);
71
+
72
+ function runAnimation($pb) {
73
+ $pb.css({ "padding-left": "0%", "padding-right": "90%" });
74
+ $pb.progressbar("option", "value", 100);
75
+ $pb.animate({ paddingLeft: "90%", paddingRight: "0%" }, 3500, "linear", function () { runAnimation($pb); });
76
+ }
77
+ }
78
+
79
+ DUPX.initToggle = function() {
80
+ $("body").on('click', "*[data-type~='toggle']", DUPX.toggleClick);
81
+
82
+ var hasFailedReq = false;
83
+ $("*[data-type~='auto'][data-status='fail']").each(function(){
84
+ hasFailedReq = true;
85
+ $(this).trigger('click');
86
+ });
87
+
88
+ $("*[data-type~='auto'][data-status='warn']").each(function(){
89
+ if (hasFailedReq) {
90
+ return ;
91
+ }
92
+
93
+ $(this).trigger('click');
94
+ });
95
+ }
96
+
97
+ DUPX.toggleAllReqs = function(id) {
98
+ $(id + " *[data-type='toggle auto']").each(function() {
99
+ $(this).trigger('click');
100
+ });
101
+ }
102
+
103
+ DUPX.toggleAllNotices = function(id) {
104
+ $(id + " *[data-type='toggle']").each(function() {
105
+ $(this).trigger('click');
106
+ });
107
+ }
108
+
109
+ DUPX.toggleClick = function()
110
+ {
111
+ var src = 0;
112
+ var id = $(this).attr('data-target');
113
+ var text = $(this).text().replace(/\+|\-/, "");
114
+ var icon = $(this).find('i.fa');
115
+ var target = $(id);
116
+ var list = new Array();
117
+
118
+ var style = [
119
+ { open: "fa-minus-square",
120
+ close: "fa-plus-square"
121
+ },
122
+ { open: "fa-caret-down",
123
+ close: "fa-caret-right"
124
+ }];
125
+
126
+ //Create src
127
+ for (i = 0; i < style.length; i++) {
128
+ if ($(icon).hasClass(style[i].open) || $(icon).hasClass(style[i].close)) {
129
+ src = i;
130
+ break;
131
+ }
132
+ }
133
+
134
+ //Build remove list
135
+ for (i = 0; i < style.length; i++) {
136
+ list.push(style[i].open);
137
+ list.push(style[i].close);
138
+ }
139
+
140
+ $(icon).removeClass(list.join(" "));
141
+ if (target.is(':hidden') ) {
142
+ (icon.length)
143
+ ? $(icon).addClass(style[src].open )
144
+ : $(this).html("- " + text );
145
+ target.show().removeClass('no-display');
146
+ } else {
147
+ (icon.length)
148
+ ? $(icon).addClass(style[src].close)
149
+ : $(this).html("+ " + text );
150
+ target.hide();
151
+ }
152
+ }
153
+
154
+ DUPX.Util.formatBytes = function (bytes,decimals)
155
+ {
156
+ if(bytes == 0) return '0 Byte';
157
+ var k = 1000;
158
+ var dm = decimals + 1 || 3;
159
+ var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
160
+ var i = Math.floor(Math.log(bytes) / Math.log(k));
161
+ return (bytes / Math.pow(k, i)).toPrecision(dm) + ' ' + sizes[i];
162
+ }
163
+
164
+ $(document).ready(function()
165
+ {
166
+ $('body').on( "click", ".copy-to-clipboard-block button", function(e) {
167
+ e.preventDefault();
168
+ var button = $(this);
169
+ var buttonText = button.html();
170
+ var textarea = button.parent().find("textarea")[0];
171
+
172
+ textarea.select();
173
+
174
+ try {
175
+ message = document.execCommand('copy') ? "Copied to Clipboard" : 'Unable to copy';
176
+ } catch (err) {
177
+ console.log(err);
178
+ }
179
+
180
+ button.html(message);
181
+
182
+ setTimeout(function () {
183
+ button.text(buttonText);
184
+ }, 2000);
185
+ });
186
+
187
+ <?php if (DUPX_Log::isLevel(DUPX_Log::LV_DEBUG)) : ?>
188
+ $("div.dupx-debug input[type=hidden], div.dupx-debug textarea").each(function() {
189
+ var label = '<label>' + $(this).attr('name') + ':</label>';
190
+ $(this).before(label);
191
+ $(this).after('<br/>');
192
+ });
193
+ $("div.dupx-debug input[type=hidden]").each(function() {
194
+ $(this).attr('type', 'text');
195
+ });
196
+
197
+ $("div.dupx-debug").prepend('<div class="dupx-debug-hdr">Debug View</div>');
198
+ <?php endif; ?>
199
+
200
+ DUPX.loadQtip = function()
201
+ {
202
+ //Look for tooltip data
203
+ $('i[data-tooltip!=""]').qtip({
204
+ content: {
205
+ attr: 'data-tooltip',
206
+ title: {
207
+ text: function() { return $(this).attr('data-tooltip-title'); }
208
+ }
209
+ },
210
+ style: {
211
+ classes: 'qtip-light qtip-rounded qtip-shadow',
212
+ width: 500
213
+ },
214
+ position: {
215
+ my: 'top left',
216
+ at: 'bottom center'
217
+ }
218
+ });
219
+ }
220
+
221
+ DUPX.loadQtip();
222
+
223
+ });
224
+
225
+ </script>
226
+ <?php
227
  DUPX_U_Html::js();
installer/dup-installer/classes/class.csrf.php CHANGED
@@ -31,8 +31,8 @@ class DUPX_CSRF
31
  /**
32
  * Set new CSRF
33
  *
34
- * @param string $key CSRF Key
35
- * @param string $val CSRF Val
36
  *
37
  * @return Void
38
  */
@@ -110,7 +110,7 @@ class DUPX_CSRF
110
  */
111
  protected static function token()
112
  {
113
- mt_srand((double) microtime() * 10000);
114
  $charid = strtoupper(md5(uniqid(rand(), true)));
115
  return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);
116
  }
31
  /**
32
  * Set new CSRF
33
  *
34
+ * @param string $key CSRF key
35
+ * @param string $val CSRF val
36
  *
37
  * @return Void
38
  */
110
  */
111
  protected static function token()
112
  {
113
+ mt_srand((int)((double) microtime() * 10000));
114
  $charid = strtoupper(md5(uniqid(rand(), true)));
115
  return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);
116
  }
installer/dup-installer/classes/class.s3.func.php CHANGED
@@ -211,7 +211,7 @@ final class DUPX_S3_Funcs
211
  // OTHER
212
  $this->post['exe_safe_mode'] = filter_input(INPUT_POST, 'exe_safe_mode', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
213
  $this->post['config_mode'] = DUPX_U::isset_sanitize($_POST, 'config_mode', array('default' => 'NEW'));
214
- $this->post['plugins'] = filter_input(INPUT_POST, 'plugins', FILTER_SANITIZE_STRING,
215
  array(
216
  'options' => array(
217
  'default' => array()
@@ -984,7 +984,7 @@ LONGMSG;
984
  mysqli_query($this->dbh,
985
  "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $this->post['siteurl'])."' WHERE option_name = 'siteurl' ");
986
  mysqli_query($this->dbh,
987
- "INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` (option_value, option_name) VALUES('".mysqli_real_escape_string($this->dbh,
988
  $this->post['exe_safe_mode'])."','duplicator_exe_safe_mode')");
989
  //Reset the postguid data
990
  if ($this->post['postguid']) {
211
  // OTHER
212
  $this->post['exe_safe_mode'] = filter_input(INPUT_POST, 'exe_safe_mode', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
213
  $this->post['config_mode'] = DUPX_U::isset_sanitize($_POST, 'config_mode', array('default' => 'NEW'));
214
+ $this->post['plugins'] = filter_input(INPUT_POST, 'plugins', FILTER_UNSAFE_RAW,
215
  array(
216
  'options' => array(
217
  'default' => array()
984
  mysqli_query($this->dbh,
985
  "UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $this->post['siteurl'])."' WHERE option_name = 'siteurl' ");
986
  mysqli_query($this->dbh,
987
+ "REPLACE INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` (option_value, option_name) VALUES('".mysqli_real_escape_string($this->dbh,
988
  $this->post['exe_safe_mode'])."','duplicator_exe_safe_mode')");
989
  //Reset the postguid data
990
  if ($this->post['postguid']) {
installer/dup-installer/classes/utilities/class.u.html.php CHANGED
@@ -320,7 +320,7 @@ class DUPX_U_Html
320
  */
321
  public static function getMoreContent($htmlContent, $classes = array(), $step = 200, $id = '', $echo = true)
322
  {
323
- $inputCls = filter_var($classes, FILTER_SANITIZE_STRING, FILTER_FORCE_ARRAY);
324
  $mainClasses = array_merge(array('more-content'), $inputCls);
325
  $atStep = max(100, $step);
326
  $idAttr = empty($id) ? '' : 'id="'.$id.'" ';
320
  */
321
  public static function getMoreContent($htmlContent, $classes = array(), $step = 200, $id = '', $echo = true)
322
  {
323
+ $inputCls = filter_var($classes, FILTER_UNSAFE_RAW, FILTER_FORCE_ARRAY);
324
  $mainClasses = array_merge(array('more-content'), $inputCls);
325
  $atStep = max(100, $step);
326
  $idAttr = empty($id) ? '' : 'id="'.$id.'" ';
installer/dup-installer/classes/utilities/class.u.notices.manager.php CHANGED
@@ -1,1251 +1,1251 @@
1
- <?php
2
- /**
3
- * Notice manager
4
- *
5
- * Standard: PSR-2
6
- * @link http://www.php-fig.org/psr/psr-2 Full Documentation
7
- *
8
- * @package SC\DUPX\U
9
- *
10
- */
11
- defined('ABSPATH') || defined('DUPXABSPATH') || exit;
12
-
13
- /**
14
- * Notice manager
15
- * singleton class
16
- */
17
- final class DUPX_NOTICE_MANAGER
18
- {
19
- const ADD_NORMAL = 0; // add notice in list
20
- const ADD_UNIQUE = 1; // add if unique id don't exists
21
- const ADD_UNIQUE_UPDATE = 2; // add or update notice unique id
22
- const ADD_UNIQUE_APPEND = 3; // append long msg
23
- const ADD_UNIQUE_APPEND_IF_EXISTS = 4; // append long msg if already exists item
24
- const ADD_UNIQUE_PREPEND = 5; // append long msg
25
- const ADD_UNIQUE_PREPEND_IF_EXISTS = 6; // prepend long msg if already exists item
26
- const DEFAULT_UNIQUE_ID_PREFIX = '__auto_unique_id__';
27
-
28
- private static $uniqueCountId = 0;
29
-
30
- /**
31
- *
32
- * @var DUPX_NOTICE_ITEM[]
33
- */
34
- private $nextStepNotices = array();
35
-
36
- /**
37
- *
38
- * @var DUPX_NOTICE_ITEM[]
39
- */
40
- private $finalReporNotices = array();
41
-
42
- /**
43
- *
44
- * @var DUPX_NOTICE_MANAGER
45
- */
46
- private static $instance = null;
47
-
48
- /**
49
- *
50
- * @var string
51
- */
52
- private $persistanceFile = null;
53
-
54
- /**
55
- *
56
- * @return DUPX_S_R_MANAGER
57
- */
58
- public static function getInstance()
59
- {
60
- if (is_null(self::$instance)) {
61
- self::$instance = new self();
62
- }
63
-
64
- return self::$instance;
65
- }
66
-
67
- private function __construct()
68
- {
69
- $this->persistanceFile = $GLOBALS["NOTICES_FILE_PATH"];
70
- $this->loadNotices();
71
- }
72
-
73
- /**
74
- * save notices from json file
75
- */
76
- public function saveNotices()
77
- {
78
- $notices = array(
79
- 'globalData' => array(
80
- 'uniqueCountId' => self::$uniqueCountId
81
- ),
82
- 'nextStep' => array(),
83
- 'finalReport' => array()
84
- );
85
-
86
- foreach ($this->nextStepNotices as $uniqueId => $notice) {
87
- $notices['nextStep'][$uniqueId] = $notice->toArray();
88
- }
89
-
90
- foreach ($this->finalReporNotices as $uniqueId => $notice) {
91
- $notices['finalReport'][$uniqueId] = $notice->toArray();
92
- }
93
-
94
- file_put_contents($this->persistanceFile, DupLiteSnapJsonU::wp_json_encode_pprint($notices));
95
- }
96
-
97
- /**
98
- * load notice from json file
99
- */
100
- private function loadNotices()
101
- {
102
- if (file_exists($this->persistanceFile)) {
103
- $json = file_get_contents($this->persistanceFile);
104
- $notices = json_decode($json, true);
105
-
106
- $this->nextStepNotices = array();
107
- $this->finalReporNotices = array();
108
-
109
- if (!empty($notices['nextStep'])) {
110
- foreach ($notices['nextStep'] as $uniqueId => $notice) {
111
- $this->nextStepNotices[$uniqueId] = DUPX_NOTICE_ITEM::getItemFromArray($notice);
112
- }
113
- }
114
-
115
- if (!empty($notices['finalReport'])) {
116
- foreach ($notices['finalReport'] as $uniqueId => $notice) {
117
- $this->finalReporNotices[$uniqueId] = DUPX_NOTICE_ITEM::getItemFromArray($notice);
118
- }
119
- }
120
-
121
- self::$uniqueCountId = $notices['globalData']['uniqueCountId'];
122
- } else {
123
- $this->resetNotices();
124
- }
125
- }
126
-
127
- /**
128
- * remove all notices and save reset file
129
- */
130
- public function resetNotices()
131
- {
132
- $this->nextStepNotices = array();
133
- $this->finalReporNotices = array();
134
- self::$uniqueCountId = 0;
135
- $this->saveNotices();
136
- }
137
-
138
- /**
139
- * return next step notice by id
140
- *
141
- * @param string $id
142
- * @return DUPX_NOTICE_ITEM
143
- */
144
- public function getNextStepNoticeById($id)
145
- {
146
- if (isset($this->nextStepNotices[$id])) {
147
- return $this->nextStepNotices[$id];
148
- } else {
149
- return null;
150
- }
151
- }
152
-
153
- /**
154
- * return last report notice by id
155
- *
156
- * @param string $id
157
- * @return DUPX_NOTICE_ITEM
158
- */
159
- public function getFinalReporNoticeById($id)
160
- {
161
- if (isset($this->finalReporNotices[$id])) {
162
- return $this->finalReporNotices[$id];
163
- } else {
164
- return null;
165
- }
166
- }
167
-
168
- /**
169
- *
170
- * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
171
- * // if array must be [
172
- * 'shortMsg' => text,
173
- * 'level' => level,
174
- * 'longMsg' => html text,
175
- * 'sections' => sections list,
176
- * 'faqLink' => [
177
- * 'url' => external link
178
- * 'label' => link text if empty get external url link
179
- * ]
180
- * ]
181
- * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
182
- * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
183
- *
184
- * @return string // notice insert id
185
- *
186
- * @throws Exception
187
- */
188
- public function addBothNextAndFinalReportNotice($item, $mode = self::ADD_NORMAL, $uniqueId = null)
189
- {
190
- $this->addNextStepNotice($item, $mode, $uniqueId);
191
- $this->addFinalReportNotice($item, $mode, $uniqueId);
192
- }
193
-
194
- /**
195
- *
196
- * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
197
- * // if array must be [
198
- * 'shortMsg' => text,
199
- * 'level' => level,
200
- * 'longMsg' => html text,
201
- * 'sections' => sections list,
202
- * 'faqLink' => [
203
- * 'url' => external link
204
- * 'label' => link text if empty get external url link
205
- * ]
206
- * ]
207
- * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
208
- * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
209
- *
210
- * @return string // notice insert id
211
- *
212
- * @throws Exception
213
- */
214
- public function addNextStepNotice($item, $mode = self::ADD_NORMAL, $uniqueId = null)
215
- {
216
- if (!is_array($item) && !($item instanceof DUPX_NOTICE_ITEM)) {
217
- throw new Exception('Invalid item param');
218
- }
219
- return self::addReportNoticeToList($this->nextStepNotices, $item, $mode, $uniqueId);
220
- }
221
-
222
- /**
223
- * addNextStepNotice wrapper to add simple message with error level
224
- *
225
- * @param string $message
226
- * @param int $level // warning level
227
- * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
228
- * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
229
- *
230
- * @return string // notice insert id
231
- *
232
- * @throws Exception
233
- */
234
- public function addNextStepNoticeMessage($message, $level = DUPX_NOTICE_ITEM::INFO, $mode = self::ADD_NORMAL, $uniqueId = null)
235
- {
236
- return $this->addNextStepNotice(array(
237
- 'shortMsg' => $message,
238
- 'level' => $level,
239
- ), $mode, $uniqueId);
240
- }
241
-
242
- /**
243
- *
244
- * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
245
- * // if array must be [
246
- * 'shortMsg' => text,
247
- * 'level' => level,
248
- * 'longMsg' => html text,
249
- * 'sections' => sections list,
250
- * 'faqLink' => [
251
- * 'url' => external link
252
- * 'label' => link text if empty get external url link
253
- * ]
254
- * ]
255
- * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
256
- * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
257
- *
258
- * @return string // notice insert id
259
- *
260
- * @throws Exception
261
- */
262
- public function addFinalReportNotice($item, $mode = self::ADD_NORMAL, $uniqueId = null)
263
- {
264
- if (!is_array($item) && !($item instanceof DUPX_NOTICE_ITEM)) {
265
- throw new Exception('Invalid item param');
266
- }
267
- return self::addReportNoticeToList($this->finalReporNotices, $item, $mode, $uniqueId);
268
- }
269
-
270
- /**
271
- * addFinalReportNotice wrapper to add simple message with error level
272
- *
273
- * @param string $message
274
- * @param string|string[] $sections // message sections on final report
275
- * @param int $level // warning level
276
- * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
277
- * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
278
- *
279
- * @return string // notice insert id
280
- *
281
- * @throws Exception
282
- */
283
- public function addFinalReportNoticeMessage($message, $sections, $level = DUPX_NOTICE_ITEM::INFO, $mode = self::ADD_NORMAL, $uniqueId = null)
284
- {
285
- return $this->addFinalReportNotice(array(
286
- 'shortMsg' => $message,
287
- 'level' => $level,
288
- 'sections' => $sections,
289
- ), $mode, $uniqueId);
290
- }
291
-
292
- /**
293
- *
294
- * @param array $list
295
- * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
296
- * // if array must be [
297
- * 'shortMsg' => text,
298
- * 'level' => level,
299
- * 'longMsg' => html text,
300
- * 'sections' => sections list,
301
- * 'faqLink' => [
302
- * 'url' => external link
303
- * 'label' => link text if empty get external url link
304
- * ]
305
- * ]
306
- * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
307
- * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
308
- *
309
- * @return string // notice insert id
310
- *
311
- * @throws Exception
312
- */
313
- private static function addReportNoticeToList(&$list, $item, $mode = self::ADD_NORMAL, $uniqueId = null)
314
- {
315
- switch ($mode) {
316
- case self::ADD_UNIQUE:
317
- if (empty($uniqueId)) {
318
- throw new Exception('uniqueId can\'t be empty');
319
- }
320
- if (isset($list[$uniqueId])) {
321
- return $uniqueId;
322
- }
323
- // no break -> continue on unique update
324
- case self::ADD_UNIQUE_UPDATE:
325
- if (empty($uniqueId)) {
326
- throw new Exception('uniqueId can\'t be empty');
327
- }
328
- $insertId = $uniqueId;
329
- break;
330
- case self::ADD_UNIQUE_APPEND_IF_EXISTS:
331
- if (empty($uniqueId)) {
332
- throw new Exception('uniqueId can\'t be empty');
333
- }
334
- if (!isset($list[$uniqueId])) {
335
- return false;
336
- }
337
- // no break
338
- case self::ADD_UNIQUE_APPEND:
339
- if (empty($uniqueId)) {
340
- throw new Exception('uniqueId can\'t be empty');
341
- }
342
- $insertId = $uniqueId;
343
- // if item id exist append long msg
344
- if (isset($list[$uniqueId])) {
345
- $tempObj = self::getObjFromParams($item);
346
- $list[$uniqueId]->longMsg .= $tempObj->longMsg;
347
- $item = $list[$uniqueId];
348
- }
349
- break;
350
- case self::ADD_UNIQUE_PREPEND_IF_EXISTS:
351
- if (empty($uniqueId)) {
352
- throw new Exception('uniqueId can\'t be empty');
353
- }
354
- if (!isset($list[$uniqueId])) {
355
- return false;
356
- }
357
- // no break
358
- case self::ADD_UNIQUE_PREPEND:
359
- if (empty($uniqueId)) {
360
- throw new Exception('uniqueId can\'t be empty');
361
- }
362
- $insertId = $uniqueId;
363
- // if item id exist append long msg
364
- if (isset($list[$uniqueId])) {
365
- $tempObj = self::getObjFromParams($item);
366
- $list[$uniqueId]->longMsg = $tempObj->longMsg.$list[$uniqueId]->longMsg;
367
- $item = $list[$uniqueId];
368
- }
369
- break;
370
- case self::ADD_NORMAL:
371
- default:
372
- if (empty($uniqueId)) {
373
- $insertId = self::getNewAutoUniqueId();
374
- } else {
375
- $insertId = $uniqueId;
376
- }
377
- }
378
-
379
- $list[$insertId] = self::getObjFromParams($item);
380
- return $insertId;
381
- }
382
-
383
- /**
384
- *
385
- * @param string|array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
386
- * // if array must be [
387
- * 'shortMsg' => text,
388
- * 'level' => level,
389
- * 'longMsg' => html text,
390
- * 'sections' => sections list,
391
- * 'faqLink' => [
392
- * 'url' => external link
393
- * 'label' => link text if empty get external url link
394
- * ]
395
- * ]
396
- * @param int $level message level considered only in the case where $item is a string.
397
- * @return \DUPX_NOTICE_ITEM
398
- *
399
- * @throws Exception
400
- */
401
- private static function getObjFromParams($item, $level = DUPX_NOTICE_ITEM::INFO)
402
- {
403
- if ($item instanceof DUPX_NOTICE_ITEM) {
404
- $newObj = $item;
405
- } else if (is_array($item)) {
406
- $newObj = DUPX_NOTICE_ITEM::getItemFromArray($item);
407
- } else if (is_string($item)) {
408
- $newObj = new DUPX_NOTICE_ITEM($item, $level);
409
- } else {
410
- throw new Exception('Notice input not valid');
411
- }
412
-
413
- return $newObj;
414
- }
415
-
416
- /**
417
- *
418
- * @param null|string $section if null is count global
419
- * @param int $level error level
420
- * @param string $operator > < >= <= = !=
421
- *
422
- * @return int
423
- */
424
- public function countFinalReportNotices($section = null, $level = DUPX_NOTICE_ITEM::INFO, $operator = '>=')
425
- {
426
- $result = 0;
427
- foreach ($this->finalReporNotices as $notice) {
428
- if (is_null($section) || in_array($section, $notice->sections)) {
429
- switch ($operator) {
430
- case '>=':
431
- $result += (int) ($notice->level >= $level);
432
- break;
433
- case '>':
434
- $result += (int) ($notice->level > $level);
435
- break;
436
- case '=':
437
- $result += (int) ($notice->level = $level);
438
- break;
439
- case '<=':
440
- $result += (int) ($notice->level <= $level);
441
- break;
442
- case '<':
443
- $result += (int) ($notice->level < $level);
444
- break;
445
- case '!=':
446
- $result += (int) ($notice->level != $level);
447
- break;
448
- }
449
- }
450
- }
451
- return $result;
452
- }
453
-
454
- /**
455
- * sort final report notice from priority and notice level
456
- */
457
- public function sortFinalReport()
458
- {
459
- uasort($this->finalReporNotices, 'DUPX_NOTICE_ITEM::sortNoticeForPriorityAndLevel');
460
- }
461
-
462
- /**
463
- * display final final report notice section
464
- *
465
- * @param string $section
466
- */
467
- public function displayFinalReport($section)
468
- {
469
- foreach ($this->finalReporNotices as $id => $notice) {
470
- if (in_array($section, $notice->sections)) {
471
- self::finalReportNotice($id, $notice);
472
- }
473
- }
474
- }
475
-
476
- /**
477
- *
478
- * @param string $section
479
- * @param string $title
480
- */
481
- public function displayFinalRepostSectionHtml($section, $title)
482
- {
483
- if ($this->haveSection($section)) {
484
- ?>
485
- <div id="report-section-<?php echo $section; ?>" class="section" >
486
- <div class="section-title" ><?php echo $title; ?></div>
487
- <div class="section-content">
488
- <?php
489
- $this->displayFinalReport($section);
490
- ?>
491
- </div>
492
- </div>
493
- <?php
494
- }
495
- }
496
-
497
- /**
498
- *
499
- * @param string $section
500
- * @return boolean
501
- */
502
- public function haveSection($section)
503
- {
504
- foreach ($this->finalReporNotices as $notice) {
505
- if (in_array($section, $notice->sections)) {
506
- return true;
507
- }
508
- }
509
- return false;
510
- }
511
-
512
- /**
513
- *
514
- * @param null|string $section if null is a global result
515
- *
516
- * @return int // returns the worst level found
517
- *
518
- */
519
- public function getSectionErrLevel($section = null)
520
- {
521
- $result = DUPX_NOTICE_ITEM::INFO;
522
-
523
- foreach ($this->finalReporNotices as $notice) {
524
- if (is_null($section) || in_array($section, $notice->sections)) {
525
- $result = max($result, $notice->level);
526
- }
527
- }
528
- return $result;
529
- }
530
-
531
- /**
532
- *
533
- * @param string $section
534
- * @param bool $echo
535
- * @return void|string
536
- */
537
- public function getSectionErrLevelHtml($section = null, $echo = true)
538
- {
539
- return self::getErrorLevelHtml($this->getSectionErrLevel($section), $echo);
540
- }
541
-
542
- /**
543
- * Displa next step notice message
544
- *
545
- * @param bool $deleteListAfterDisaply
546
- * @return void
547
- */
548
- public function displayStepMessages($deleteListAfterDisaply = true)
549
- {
550
- if (empty($this->nextStepNotices)) {
551
- return;
552
- }
553
- ?>
554
- <div id="step-messages">
555
- <?php
556
- foreach ($this->nextStepNotices as $notice) {
557
- self::stepMsg($notice);
558
- }
559
- ?>
560
- </div>
561
- <?php
562
- if ($deleteListAfterDisaply) {
563
- $this->nextStepNotices = array();
564
- $this->saveNotices();
565
- }
566
- }
567
-
568
- /**
569
- *
570
- * @param DUPX_NOTICE_ITEM $notice
571
- */
572
- private static function stepMsg($notice)
573
- {
574
- $classes = array(
575
- 'notice',
576
- 'next-step',
577
- self::getClassFromLevel($notice->level)
578
- );
579
- $haveContent = !empty($notice->faqLink) || !empty($notice->longMsg);
580
- ?>
581
- <div class="<?php echo implode(' ', $classes); ?>">
582
- <div class="title">
583
- <?php echo self::getNextStepLevelPrefixMessage($notice->level).': <b>'.htmlentities($notice->shortMsg).'</b>'; ?>
584
- </div>
585
- <?php if ($haveContent) { ?>
586
- <div class="title-separator" ></div>
587
- <?php
588
- ob_start();
589
- if (!empty($notice->faqLink)) {
590
- ?>
591
- See FAQ: <a href="<?php echo $notice->faqLink['url']; ?>" >
592
- <b><?php echo htmlentities(empty($notice->faqLink['label']) ? $notice->faqLink['url'] : $notice->faqLink['label']); ?></b>
593
- </a>
594
- <?php
595
- }
596
- if (!empty($notice->faqLink) && !empty($notice->longMsg)) {
597
- echo '<br><br>';
598
- }
599
- if (!empty($notice->longMsg)) {
600
- switch ($notice->longMsgMode) {
601
- case DUPX_NOTICE_ITEM::MSG_MODE_PRE:
602
- echo '<pre>'.htmlentities($notice->longMsg).'</pre>';
603
- break;
604
- case DUPX_NOTICE_ITEM::MSG_MODE_HTML:
605
- echo $notice->longMsg;
606
- break;
607
- case DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT:
608
- default:
609
- echo htmlentities($notice->longMsg);
610
- }
611
- }
612
- $longContent = ob_get_clean();
613
- DUPX_U_Html::getMoreContent($longContent, 'info', 200);
614
- }
615
- ?>
616
- </div>
617
- <?php
618
- }
619
-
620
- /**
621
- *
622
- * @param string $id
623
- * @param DUPX_NOTICE_ITEM $notice
624
- */
625
- private static function finalReportNotice($id, $notice)
626
- {
627
- $classes = array(
628
- 'notice-report',
629
- 'notice',
630
- self::getClassFromLevel($notice->level)
631
- );
632
- $haveContent = !empty($notice->faqLink) || !empty($notice->longMsg);
633
- $contentId = 'notice-content-'.$id;
634
- $iconClasses = $haveContent ? 'fa fa-caret-right' : 'fa fa-toggle-empty';
635
- $toggleLinkData = $haveContent ? 'data-type="toggle" data-target="#'.$contentId.'"' : '';
636
- ?>
637
- <div class="<?php echo implode(' ', $classes); ?>">
638
- <div class="title" <?php echo $toggleLinkData; ?>>
639
- <i class="<?php echo $iconClasses; ?>"></i> <?php echo htmlentities($notice->shortMsg); ?>
640
- </div>
641
- <?php
642
- if ($haveContent) {
643
- $infoClasses = array('info');
644
- if (!$notice->open) {
645
- $infoClasses[] = 'no-display';
646
- }
647
- ?>
648
- <div id="<?php echo $contentId; ?>" class="<?php echo implode(' ', $infoClasses); ?>" >
649
- <?php
650
- if (!empty($notice->faqLink)) {
651
- ?>
652
- <b>See FAQ</b>: <a href="<?php echo $notice->faqLink['url']; ?>" >
653
- <?php echo htmlentities(empty($notice->faqLink['label']) ? $notice->faqLink['url'] : $notice->faqLink['label']); ?>
654
- </a>
655
- <?php
656
- }
657
- if (!empty($notice->faqLink) && !empty($notice->longMsg)) {
658
- echo '<br><br>';
659
- }
660
- if (!empty($notice->longMsg)) {
661
- switch ($notice->longMsgMode) {
662
- case DUPX_NOTICE_ITEM::MSG_MODE_PRE:
663
- echo '<pre>'.htmlentities($notice->longMsg).'</pre>';
664
- break;
665
- case DUPX_NOTICE_ITEM::MSG_MODE_HTML:
666
- echo $notice->longMsg;
667
- break;
668
- case DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT:
669
- default:
670
- echo htmlentities($notice->longMsg);
671
- }
672
- }
673
- ?>
674
- </div>
675
- <?php
676
- }
677
- ?>
678
- </div>
679
- <?php
680
- }
681
-
682
- /**
683
- *
684
- * @param DUPX_NOTICE_ITEM $notice
685
- */
686
- private static function noticeToText($notice)
687
- {
688
- $result = '-----------------------'."\n".
689
- '['.self::getNextStepLevelPrefixMessage($notice->level, false).'] '.$notice->shortMsg;
690
-
691
- if (!empty($notice->sections)) {
692
- $result .= "\n\t".'SECTIONS: '.implode(',', $notice->sections);
693
- }
694
- if (!empty($notice->longMsg)) {
695
- $result .= "\n\t".'LONG MSG: '.$notice->longMsg;
696
- }
697
- return $result."\n";
698
- }
699
-
700
- public function nextStepLog()
701
- {
702
- if (!empty($this->nextStepNotices)) {
703
- DUPX_Log::info(
704
- '===================================='."\n".
705
- 'NEXT STEP NOTICES'."\n".
706
- '====================================');
707
- foreach ($this->nextStepNotices as $notice) {
708
- DUPX_Log::info(self::noticeToText($notice));
709
- }
710
- DUPX_Log::info(
711
- '====================================');
712
- }
713
- }
714
-
715
- public function finalReportLog($sections = array())
716
- {
717
- if (!empty($this->finalReporNotices)) {
718
- DUPX_Log::info(
719
- '===================================='."\n".
720
- 'FINAL REPORT NOTICES LIST'."\n".
721
- '====================================');
722
- foreach ($this->finalReporNotices as $notice) {
723
- if (count(array_intersect($notice->sections, $sections)) > 0) {
724
- DUPX_Log::info(self::noticeToText($notice));
725
- }
726
- }
727
- DUPX_Log::info(
728
- '====================================');
729
- }
730
- }
731
-
732
- /**
733
- * get html class from level
734
- *
735
- * @param int $level
736
- * @return string
737
- */
738
- private static function getClassFromLevel($level)
739
- {
740
- switch ($level) {
741
- case DUPX_NOTICE_ITEM::INFO:
742
- return 'l-info';
743
- case DUPX_NOTICE_ITEM::NOTICE:
744
- return 'l-notice';
745
- case DUPX_NOTICE_ITEM::SOFT_WARNING:
746
- return 'l-swarning';
747
- case DUPX_NOTICE_ITEM::HARD_WARNING:
748
- return 'l-hwarning';
749
- case DUPX_NOTICE_ITEM::CRITICAL:
750
- return 'l-critical';
751
- case DUPX_NOTICE_ITEM::FATAL:
752
- return 'l-fatal';
753
- }
754
- }
755
-
756
- /**
757
- * get level label from level
758
- *
759
- * @param int $level
760
- * @param bool $echo
761
- * @return type
762
- */
763
- public static function getErrorLevelHtml($level, $echo = true)
764
- {
765
- switch ($level) {
766
- case DUPX_NOTICE_ITEM::INFO:
767
- $label = 'good';
768
- break;
769
- case DUPX_NOTICE_ITEM::NOTICE:
770
- $label = 'good';
771
- break;
772
- case DUPX_NOTICE_ITEM::SOFT_WARNING:
773
- $label = 'warning';
774
- break;
775
- case DUPX_NOTICE_ITEM::HARD_WARNING:
776
- $label = 'warning';
777
- break;
778
- case DUPX_NOTICE_ITEM::CRITICAL:
779
- $label = 'critical error';
780
- break;
781
- case DUPX_NOTICE_ITEM::FATAL:
782
- $label = 'fatal error';
783
- break;
784
- default:
785
- return;
786
- }
787
- $classes = self::getClassFromLevel($level);
788
- ob_start();
789
- ?>
790
- <span class="notice-level-status <?php echo $classes; ?>"><?php echo $label; ?></span>
791
- <?php
792
- if ($echo) {
793
- ob_end_flush();
794
- } else {
795
- return ob_get_clean();
796
- }
797
- }
798
-
799
- /**
800
- * get next step message prefix
801
- *
802
- * @param int $level
803
- * @param bool $echo
804
- * @return string
805
- */
806
- public static function getNextStepLevelPrefixMessage($level, $echo = true)
807
- {
808
- switch ($level) {
809
- case DUPX_NOTICE_ITEM::INFO:
810
- $label = 'INFO';
811
- break;
812
- case DUPX_NOTICE_ITEM::NOTICE:
813
- $label = 'NOTICE';
814
- break;
815
- case DUPX_NOTICE_ITEM::SOFT_WARNING:
816
- $label = 'WARNING';
817
- break;
818
- case DUPX_NOTICE_ITEM::HARD_WARNING:
819
- $label = 'WARNING';
820
- break;
821
- case DUPX_NOTICE_ITEM::CRITICAL:
822
- $label = 'CRITICAL ERROR';
823
- break;
824
- case DUPX_NOTICE_ITEM::FATAL:
825
- $label = 'FATAL ERROR';
826
- break;
827
- default:
828
- return;
829
- }
830
-
831
- if ($echo) {
832
- echo $label;
833
- } else {
834
- return $label;
835
- }
836
- }
837
-
838
- /**
839
- * get unique id
840
- *
841
- * @return string
842
- */
843
- private static function getNewAutoUniqueId()
844
- {
845
- self::$uniqueCountId ++;
846
- return self::DEFAULT_UNIQUE_ID_PREFIX.self::$uniqueCountId;
847
- }
848
-
849
- /**
850
- * function for internal test
851
- *
852
- * display all messages levels
853
- */
854
- public static function testNextStepMessaesLevels()
855
- {
856
- $manager = self::getInstance();
857
- $manager->addNextStepNoticeMessage('Level info ('.DUPX_NOTICE_ITEM::INFO.')', DUPX_NOTICE_ITEM::INFO);
858
- $manager->addNextStepNoticeMessage('Level notice ('.DUPX_NOTICE_ITEM::NOTICE.')', DUPX_NOTICE_ITEM::NOTICE);
859
- $manager->addNextStepNoticeMessage('Level soft warning ('.DUPX_NOTICE_ITEM::SOFT_WARNING.')', DUPX_NOTICE_ITEM::SOFT_WARNING);
860
- $manager->addNextStepNoticeMessage('Level hard warning ('.DUPX_NOTICE_ITEM::HARD_WARNING.')', DUPX_NOTICE_ITEM::HARD_WARNING);
861
- $manager->addNextStepNoticeMessage('Level critical error ('.DUPX_NOTICE_ITEM::CRITICAL.')', DUPX_NOTICE_ITEM::CRITICAL);
862
- $manager->addNextStepNoticeMessage('Level fatal error ('.DUPX_NOTICE_ITEM::FATAL.')', DUPX_NOTICE_ITEM::FATAL);
863
- $manager->saveNotices();
864
- }
865
-
866
- /**
867
- * test function
868
- */
869
- public static function testNextStepFullMessageData()
870
- {
871
- $manager = self::getInstance();
872
- $longMsg = <<<LONGMSG
873
- <b>Formattend long text</b><br>
874
- <ul>
875
- <li>Proin dapibus mi eu erat pulvinar, id congue nisl egestas.</li>
876
- <li>Nunc venenatis eros et sapien ornare consequat.</li>
877
- <li>Mauris tincidunt est sit amet turpis placerat, a tristique dui porttitor.</li>
878
- <li>Etiam volutpat lectus quis risus molestie faucibus.</li>
879
- <li>Integer gravida eros sit amet sem viverra, a volutpat neque rutrum.</li>
880
- <li>Aenean varius ipsum vitae lorem tempus rhoncus.</li>
881
- </ul>
882
- LONGMSG;
883
- $manager->addNextStepNotice(array(
884
- 'shortMsg' => 'Full elements next step message MODE HTML',
885
- 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
886
- 'longMsg' => $longMsg,
887
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
888
- 'faqLink' => array(
889
- 'url' => 'http://www.google.it',
890
- 'label' => 'google link'
891
- )
892
- ));
893
-
894
- $longMsg = <<<LONGMSG
895
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc a auctor erat, et lobortis libero.
896
- Suspendisse aliquet neque in massa posuere mollis. Donec venenatis finibus sapien in bibendum. Donec et ex massa.
897
-
898
- Aliquam venenatis dapibus tellus nec ullamcorper. Mauris ante velit, tincidunt sit amet egestas et, mattis non lorem. In semper ex ut velit suscipit,
899
- at luctus nunc dapibus. Etiam blandit maximus dapibus. Nullam eu porttitor augue. Suspendisse pulvinar, massa eget condimentum aliquet, dolor massa tempus dui, vel rhoncus tellus ligula non odio.
900
- Ut ac faucibus tellus, in lobortis odio.
901
- LONGMSG;
902
- $manager->addNextStepNotice(array(
903
- 'shortMsg' => 'Full elements next step message MODE PRE',
904
- 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
905
- 'longMsg' => $longMsg,
906
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE,
907
- 'faqLink' => array(
908
- 'url' => 'http://www.google.it',
909
- 'label' => 'google link'
910
- )
911
- ));
912
-
913
- $longMsg = <<<LONGMSG
914
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc a auctor erat, et lobortis libero.
915
- Suspendisse aliquet neque in massa posuere mollis. Donec venenatis finibus sapien in bibendum. Donec et ex massa.
916
-
917
- Aliquam venenatis dapibus tellus nec ullamcorper. Mauris ante velit, tincidunt sit amet egestas et, mattis non lorem. In semper ex ut velit suscipit,
918
- at luctus nunc dapibus. Etiam blandit maximus dapibus. Nullam eu porttitor augue. Suspendisse pulvinar, massa eget condimentum aliquet, dolor massa tempus dui, vel rhoncus tellus ligula non odio.
919
- Ut ac faucibus tellus, in lobortis odio.
920
- LONGMSG;
921
- $manager->addNextStepNotice(array(
922
- 'shortMsg' => 'Full elements next step message MODE DEFAULT',
923
- 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
924
- 'longMsg' => $longMsg,
925
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT,
926
- 'faqLink' => array(
927
- 'url' => 'http://www.google.it',
928
- 'label' => 'google link'
929
- )
930
- ));
931
-
932
-
933
- $longMsg = <<<LONGMSG
934
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam cursus porttitor consectetur. Nunc faucibus elementum nisl nec ornare. Phasellus sit amet urna in diam ultricies ornare nec sit amet nibh. Nulla a aliquet leo. Quisque aliquet posuere lectus sit amet commodo. Nullam tempus enim eget urna rutrum egestas. Aliquam eget lorem nisl. Nulla tincidunt massa erat. Phasellus lectus tellus, mollis sit amet aliquam in, dapibus quis metus. Nunc venenatis nulla vitae convallis accumsan.
935
-
936
- Mauris eu ullamcorper metus. Aenean ultricies et turpis eget mollis. Aliquam auctor, elit scelerisque placerat pellentesque, quam augue fermentum lectus, vel pretium nisi justo sit amet ante. Donec blandit porttitor tempus. Duis vulputate nulla ut orci rutrum, et consectetur urna mollis. Sed at iaculis velit. Pellentesque id quam turpis. Curabitur eu ligula velit. Cras gravida, ipsum sed iaculis eleifend, mauris nunc posuere quam, vel blandit nisi justo congue ligula. Phasellus aliquam eu odio ac porttitor. Fusce dictum mollis turpis sit amet fringilla.
937
-
938
- Nulla eu ligula mauris. Fusce lobortis ligula elit, a interdum nibh pulvinar eu. Pellentesque rhoncus nec turpis id blandit. Morbi fringilla, justo non varius consequat, arcu ante efficitur ante, sit amet cursus lorem elit vel odio. Phasellus neque ligula, vehicula vel ipsum sed, volutpat dignissim eros. Curabitur at lacus id felis elementum auctor. Nullam ac tempus nisi. Phasellus nibh purus, aliquam nec purus ut, sodales lobortis nulla. Cras viverra dictum magna, ac malesuada nibh dictum ac. Mauris euismod, magna sit amet pretium posuere, ligula nibh ultrices tellus, sit amet pretium odio urna egestas justo. Suspendisse purus erat, eleifend sed magna in, efficitur interdum nibh.
939
-
940
- Vivamus nibh nunc, fermentum non tortor volutpat, consectetur vulputate velit. Phasellus lobortis, purus et faucibus mollis, metus eros viverra ante, sit amet euismod nibh est eu orci. Duis sodales cursus lacinia. Praesent laoreet ut ipsum ut interdum. Praesent venenatis massa vitae ligula consequat aliquet. Fusce in purus in odio molestie laoreet at ac augue. Fusce consectetur elit a magna mollis aliquet.
941
-
942
- Nulla eros nisi, dapibus eget diam vitae, tincidunt blandit odio. Fusce interdum tellus nec varius condimentum. Fusce non magna a purus sodales imperdiet sit amet vitae ligula. Quisque viverra leo sit amet mi egestas, et posuere nunc tincidunt. Suspendisse feugiat malesuada urna sed tincidunt. Morbi a urna sed magna volutpat pellentesque sit amet ac mauris. Nulla sed ultrices dui. Etiam massa arcu, tempor ut erat at, cursus malesuada ipsum. Duis sit amet felis dolor.
943
-
944
- Morbi gravida nisl nunc, vulputate iaculis risus vehicula non. Proin cursus, velit et laoreet consectetur, lacus libero sagittis lacus, quis accumsan odio lectus non erat. Aenean dolor lectus, euismod sit amet justo eget, dictum gravida nisl. Phasellus sed nunc non odio ullamcorper rhoncus non ut ipsum. Duis ante ligula, pellentesque sit amet imperdiet eget, congue vel dui. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla facilisi. Suspendisse luctus leo eget justo mollis, convallis convallis ex suscipit. Integer et justo eget odio lobortis sollicitudin. Pellentesque accumsan rhoncus augue, luctus suscipit ex accumsan nec. Maecenas lacinia consectetur risus at bibendum. Etiam venenatis purus lorem, sit amet elementum turpis tristique eu. Proin vulputate faucibus feugiat. Nunc vehicula congue odio consequat vulputate. Quisque bibendum augue id iaculis faucibus. Donec blandit cursus sem, eget accumsan orci commodo sed.
945
-
946
- Suspendisse iaculis est quam, sed scelerisque purus tincidunt non. Cras hendrerit ante turpis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse purus ipsum, rutrum id sem in, venenatis laoreet metus. Aliquam ac bibendum mauris. Cras egestas rhoncus est, sed lacinia nibh vestibulum id. Proin diam quam, sagittis congue molestie ac, rhoncus et mauris. Phasellus massa neque, ornare vel erat a, rutrum pharetra arcu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi et nulla eget massa auctor fermentum. Quisque maximus tellus sed cursus cursus. Ut vehicula erat at purus aliquet, quis imperdiet dui sagittis. Nullam eget quam leo.
947
-
948
- Nulla magna ipsum, congue nec dui ut, lacinia malesuada felis. Cras mattis metus non maximus venenatis. Aliquam euismod est vitae erat sollicitudin, at pellentesque augue sollicitudin. Curabitur euismod maximus cursus. In tortor dui, convallis sed sapien ac, varius congue metus. Nunc ullamcorper ac orci sit amet finibus. Vivamus molestie nibh vitae quam rhoncus, eu ultrices est molestie. Maecenas consectetur eu quam sit amet placerat.
949
-
950
- Curabitur ut fermentum mauris. Donec et congue nibh. Sed cursus elit sit amet convallis varius. Donec malesuada porta odio condimentum varius. Pellentesque ornare tempor ante, ut volutpat nulla lobortis sed. Nunc congue aliquet erat ac elementum. Quisque a ex sit amet turpis placerat sagittis eget ac ligula. Etiam in augue malesuada, aliquam est non, lacinia justo. Vivamus tincidunt dolor orci, id dignissim lorem maximus at. Vivamus ligula mauris, venenatis vel nibh id, lacinia ultrices ipsum. Mauris cursus, urna ac rutrum aliquet, risus ipsum tincidunt purus, sit amet blandit nunc sem sit amet nibh.
951
-
952
- Nam eleifend risus lacus, eu pharetra risus egestas eu. Maecenas hendrerit nisl in semper placerat. Vestibulum massa tellus, laoreet non euismod quis, sollicitudin id sapien. Morbi vel cursus metus. Aenean tincidunt nisi est, ut elementum est auctor id. Duis auctor elit leo, ac scelerisque risus suscipit et. Pellentesque lectus nisi, ultricies in elit sed, pulvinar iaculis massa. Morbi viverra eros mi, pretium facilisis neque egestas id. Curabitur non massa accumsan, porttitor sem vitae, ultricies lacus. Curabitur blandit nisl velit. Mauris sollicitudin ultricies purus sit amet placerat. Fusce ac neque sed leo venenatis laoreet ut non ex. Integer elementum rhoncus orci, eu maximus neque tempus eu. Curabitur euismod dignissim tellus, vitae lacinia metus. Mauris imperdiet metus vitae vulputate accumsan. Duis eget luctus nibh, sit amet finibus libero.
953
-
954
- LONGMSG;
955
- $manager->addNextStepNotice(array(
956
- 'shortMsg' => 'Full elements LONG LONG',
957
- 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
958
- 'longMsg' => $longMsg,
959
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT,
960
- 'faqLink' => array(
961
- 'url' => 'http://www.google.it',
962
- 'label' => 'google link'
963
- )
964
- ));
965
-
966
-
967
-
968
-
969
- $manager->saveNotices();
970
- }
971
-
972
- /**
973
- * test function
974
- */
975
- public static function testFinalReporMessaesLevels()
976
- {
977
- $section = 'general';
978
-
979
- $manager = self::getInstance();
980
- $manager->addFinalReportNoticeMessage('Level info ('.DUPX_NOTICE_ITEM::INFO.')', $section, DUPX_NOTICE_ITEM::INFO, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_0');
981
- $manager->addFinalReportNoticeMessage('Level notice ('.DUPX_NOTICE_ITEM::NOTICE.')', $section, DUPX_NOTICE_ITEM::NOTICE, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_1');
982
- $manager->addFinalReportNoticeMessage('Level soft warning ('.DUPX_NOTICE_ITEM::SOFT_WARNING.')', $section, DUPX_NOTICE_ITEM::SOFT_WARNING, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_2');
983
- $manager->addFinalReportNoticeMessage('Level hard warning ('.DUPX_NOTICE_ITEM::HARD_WARNING.')', $section, DUPX_NOTICE_ITEM::HARD_WARNING, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_3');
984
- $manager->addFinalReportNoticeMessage('Level critical error ('.DUPX_NOTICE_ITEM::CRITICAL.')', $section, DUPX_NOTICE_ITEM::CRITICAL, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_4');
985
- $manager->addFinalReportNoticeMessage('Level fatal error ('.DUPX_NOTICE_ITEM::FATAL.')', $section, DUPX_NOTICE_ITEM::FATAL, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_5');
986
- $manager->saveNotices();
987
- }
988
-
989
- /**
990
- * test function
991
- */
992
- public static function testFinalReportFullMessages()
993
- {
994
- $section = 'general';
995
- $manager = self::getInstance();
996
-
997
- $longMsg = <<<LONGMSG
998
- <b>Formattend long text</b><br>
999
- <ul>
1000
- <li>Proin dapibus mi eu erat pulvinar, id congue nisl egestas.</li>
1001
- <li>Nunc venenatis eros et sapien ornare consequat.</li>
1002
- <li>Mauris tincidunt est sit amet turpis placerat, a tristique dui porttitor.</li>
1003
- <li>Etiam volutpat lectus quis risus molestie faucibus.</li>
1004
- <li>Integer gravida eros sit amet sem viverra, a volutpat neque rutrum.</li>
1005
- <li>Aenean varius ipsum vitae lorem tempus rhoncus.</li>
1006
- </ul>
1007
- LONGMSG;
1008
-
1009
- $manager->addFinalReportNotice(array(
1010
- 'shortMsg' => 'Full elements final report message',
1011
- 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
1012
- 'longMsg' => $longMsg,
1013
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
1014
- 'sections' => $section,
1015
- 'faqLink' => array(
1016
- 'url' => 'http://www.google.it',
1017
- 'label' => 'google link'
1018
- )
1019
- ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_full_1');
1020
-
1021
- $manager->addFinalReportNotice(array(
1022
- 'shortMsg' => 'Full elements final report message info high priority',
1023
- 'level' => DUPX_NOTICE_ITEM::INFO,
1024
- 'longMsg' => $longMsg,
1025
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
1026
- 'sections' => $section,
1027
- 'faqLink' => array(
1028
- 'url' => 'http://www.google.it',
1029
- 'label' => 'google link'
1030
- ),
1031
- 'priority' => 5
1032
- ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_full_2');
1033
- $manager->saveNotices();
1034
- }
1035
-
1036
- //PHP 8 Requires method to be public
1037
- public function __wakeup()
1038
- {
1039
- }
1040
-
1041
- private function __clone()
1042
- {
1043
-
1044
- }
1045
- }
1046
-
1047
- class DUPX_NOTICE_ITEM
1048
- {
1049
- const INFO = 0;
1050
- const NOTICE = 1;
1051
- const SOFT_WARNING = 2;
1052
- const HARD_WARNING = 3;
1053
- const CRITICAL = 4;
1054
- const FATAL = 5;
1055
- const MSG_MODE_DEFAULT = 'def';
1056
- const MSG_MODE_HTML = 'html';
1057
- const MSG_MODE_PRE = 'pre';
1058
-
1059
- /**
1060
- *
1061
- * @var string text
1062
- */
1063
- public $shortMsg = '';
1064
-
1065
- /**
1066
- *
1067
- * @var string html text
1068
- */
1069
- public $longMsg = '';
1070
-
1071
- /**
1072
- *
1073
- * @var bool if true long msg can be html
1074
- */
1075
- public $longMsgMode = self::MSG_MODE_DEFAULT;
1076
-
1077
- /**
1078
- *
1079
- * @var null|array // null = no faq link
1080
- * array( 'label' => link text , 'url' => faq url)
1081
- */
1082
- public $faqLink = array(
1083
- 'label' => '',
1084
- 'url' => ''
1085
- );
1086
-
1087
- /**
1088
- *
1089
- * @var string[] notice sections for final report only
1090
- */
1091
- public $sections = array();
1092
-
1093
- /**
1094
- *
1095
- * @var int
1096
- */
1097
- public $level = self::NOTICE;
1098
-
1099
- /**
1100
- *
1101
- * @var int
1102
- */
1103
- public $priority = 10;
1104
-
1105
- /**
1106
- *
1107
- * @var bool if true notice start open. For final report only
1108
- */
1109
- public $open = false;
1110
-
1111
- /**
1112
- *
1113
- * @param string $shortMsg text
1114
- * @param int $level
1115
- * @param string $longMsg html text
1116
- * @param string|string[] $sections
1117
- * @param null|array $faqLink [
1118
- * 'url' => external link
1119
- * 'label' => link text if empty get external url link
1120
- * ]
1121
- * @param int priority
1122
- * @param bool open
1123
- * @param string longMsgMode MSG_MODE_DEFAULT | MSG_MODE_HTML | MSG_MODE_PRE
1124
- */
1125
- public function __construct($shortMsg, $level = self::INFO, $longMsg = '', $sections = array(), $faqLink = null, $priority = 10, $open = false, $longMsgMode = self::MSG_MODE_DEFAULT)
1126
- {
1127
- $this->shortMsg = (string) $shortMsg;
1128
- $this->level = (int) $level;
1129
- $this->longMsg = (string) $longMsg;
1130
- $this->sections = is_array($sections) ? $sections : array($sections);
1131
- $this->faqLink = $faqLink;
1132
- $this->priority = $priority;
1133
- $this->open = $open;
1134
- $this->longMsgMode = $longMsgMode;
1135
- }
1136
-
1137
- /**
1138
- *
1139
- * @return array [
1140
- * 'shortMsg' => text,
1141
- * 'level' => level,
1142
- * 'longMsg' => html text,
1143
- * 'sections' => string|string[],
1144
- * 'faqLink' => [
1145
- * 'url' => external link
1146
- * 'label' => link text if empty get external url link
1147
- * ]
1148
- * 'priority' => int low first
1149
- * 'open' => if true the tab is opene on final report
1150
- * 'longMsgMode'=> MSG_MODE_DEFAULT | MSG_MODE_HTML | MSG_MODE_PRE
1151
- * ]
1152
- */
1153
- public function toArray()
1154
- {
1155
- return array(
1156
- 'shortMsg' => $this->shortMsg,
1157
- 'level' => $this->level,
1158
- 'longMsg' => $this->longMsg,
1159
- 'sections' => $this->sections,
1160
- 'faqLink' => $this->faqLink,
1161
- 'priority' => $this->priority,
1162
- 'open' => $this->open,
1163
- 'longMsgMode' => $this->longMsgMode
1164
- );
1165
- }
1166
-
1167
- /**
1168
- *
1169
- * @return array [
1170
- * 'shortMsg' => text,
1171
- * 'level' => level,
1172
- * 'longMsg' => html text,
1173
- * 'sections' => string|string[],
1174
- * 'faqLink' => [
1175
- * 'url' => external link
1176
- * 'label' => link text if empty get external url link
1177
- * ],
1178
- * priority
1179
- * open
1180
- * longMsgMode
1181
- * ]
1182
- * @return DUPX_NOTICE_ITEM
1183
- */
1184
- public static function getItemFromArray($array)
1185
- {
1186
- if (isset($array['sections']) && !is_array($array['sections'])) {
1187
- if (empty($array['sections'])) {
1188
- $array['sections'] = array();
1189
- } else {
1190
- $array['sections'] = array($array['sections']);
1191
- }
1192
- }
1193
- $params = array_merge(self::getDefaultArrayParams(), $array);
1194
- $result = new self($params['shortMsg'], $params['level'], $params['longMsg'], $params['sections'], $params['faqLink'], $params['priority'], $params['open'], $params['longMsgMode']);
1195
- return $result;
1196
- }
1197
-
1198
- /**
1199
- *
1200
- * @return array [
1201
- * 'shortMsg' => text,
1202
- * 'level' => level,
1203
- * 'longMsg' => html text,
1204
- * 'sections' => string|string[],
1205
- * 'faqLink' => [
1206
- * 'url' => external link
1207
- * 'label' => link text if empty get external url link
1208
- * ],
1209
- * priority
1210
- * open
1211
- * longMsgMode
1212
- * ]
1213
- */
1214
- public static function getDefaultArrayParams()
1215
- {
1216
- return array(
1217
- 'shortMsg' => '',
1218
- 'level' => self::INFO,
1219
- 'longMsg' => '',
1220
- 'sections' => array(),
1221
- 'faqLink' => null,
1222
- 'priority' => 10,
1223
- 'open' => false,
1224
- 'longMsgMode' => self::MSG_MODE_DEFAULT
1225
- );
1226
- }
1227
-
1228
- /**
1229
- * before lower priority
1230
- * before highest level
1231
- *
1232
- * @param DUPX_NOTICE_ITEM $a
1233
- * @param DUPX_NOTICE_ITEM $b
1234
- */
1235
- public static function sortNoticeForPriorityAndLevel($a, $b)
1236
- {
1237
- if ($a->priority == $b->priority) {
1238
- if ($a->level == $b->level) {
1239
- return 0;
1240
- } else if ($a->level < $b->level) {
1241
- return 1;
1242
- } else {
1243
- return -1;
1244
- }
1245
- } else if ($a->priority < $b->priority) {
1246
- return -1;
1247
- } else {
1248
- return 1;
1249
- }
1250
- }
1251
  }
1
+ <?php
2
+ /**
3
+ * Notice manager
4
+ *
5
+ * Standard: PSR-2
6
+ * @link http://www.php-fig.org/psr/psr-2 Full Documentation
7
+ *
8
+ * @package SC\DUPX\U
9
+ *
10
+ */
11
+ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
12
+
13
+ /**
14
+ * Notice manager
15
+ * singleton class
16
+ */
17
+ final class DUPX_NOTICE_MANAGER
18
+ {
19
+ const ADD_NORMAL = 0; // add notice in list
20
+ const ADD_UNIQUE = 1; // add if unique id don't exists
21
+ const ADD_UNIQUE_UPDATE = 2; // add or update notice unique id
22
+ const ADD_UNIQUE_APPEND = 3; // append long msg
23
+ const ADD_UNIQUE_APPEND_IF_EXISTS = 4; // append long msg if already exists item
24
+ const ADD_UNIQUE_PREPEND = 5; // append long msg
25
+ const ADD_UNIQUE_PREPEND_IF_EXISTS = 6; // prepend long msg if already exists item
26
+ const DEFAULT_UNIQUE_ID_PREFIX = '__auto_unique_id__';
27
+
28
+ private static $uniqueCountId = 0;
29
+
30
+ /**
31
+ *
32
+ * @var DUPX_NOTICE_ITEM[]
33
+ */
34
+ private $nextStepNotices = array();
35
+
36
+ /**
37
+ *
38
+ * @var DUPX_NOTICE_ITEM[]
39
+ */
40
+ private $finalReporNotices = array();
41
+
42
+ /**
43
+ *
44
+ * @var DUPX_NOTICE_MANAGER
45
+ */
46
+ private static $instance = null;
47
+
48
+ /**
49
+ *
50
+ * @var string
51
+ */
52
+ private $persistanceFile = null;
53
+
54
+ /**
55
+ *
56
+ * @return DUPX_S_R_MANAGER
57
+ */
58
+ public static function getInstance()
59
+ {
60
+ if (is_null(self::$instance)) {
61
+ self::$instance = new self();
62
+ }
63
+
64
+ return self::$instance;
65
+ }
66
+
67
+ private function __construct()
68
+ {
69
+ $this->persistanceFile = $GLOBALS["NOTICES_FILE_PATH"];
70
+ $this->loadNotices();
71
+ }
72
+
73
+ /**
74
+ * save notices from json file
75
+ */
76
+ public function saveNotices()
77
+ {
78
+ $notices = array(
79
+ 'globalData' => array(
80
+ 'uniqueCountId' => self::$uniqueCountId
81
+ ),
82
+ 'nextStep' => array(),
83
+ 'finalReport' => array()
84
+ );
85
+
86
+ foreach ($this->nextStepNotices as $uniqueId => $notice) {
87
+ $notices['nextStep'][$uniqueId] = $notice->toArray();
88
+ }
89
+
90
+ foreach ($this->finalReporNotices as $uniqueId => $notice) {
91
+ $notices['finalReport'][$uniqueId] = $notice->toArray();
92
+ }
93
+
94
+ file_put_contents($this->persistanceFile, DupLiteSnapJsonU::wp_json_encode_pprint($notices));
95
+ }
96
+
97
+ /**
98
+ * load notice from json file
99
+ */
100
+ private function loadNotices()
101
+ {
102
+ if (file_exists($this->persistanceFile)) {
103
+ $json = file_get_contents($this->persistanceFile);
104
+ $notices = json_decode($json, true);
105
+
106
+ $this->nextStepNotices = array();
107
+ $this->finalReporNotices = array();
108
+
109
+ if (!empty($notices['nextStep'])) {
110
+ foreach ($notices['nextStep'] as $uniqueId => $notice) {
111
+ $this->nextStepNotices[$uniqueId] = DUPX_NOTICE_ITEM::getItemFromArray($notice);
112
+ }
113
+ }
114
+
115
+ if (!empty($notices['finalReport'])) {
116
+ foreach ($notices['finalReport'] as $uniqueId => $notice) {
117
+ $this->finalReporNotices[$uniqueId] = DUPX_NOTICE_ITEM::getItemFromArray($notice);
118
+ }
119
+ }
120
+
121
+ self::$uniqueCountId = $notices['globalData']['uniqueCountId'];
122
+ } else {
123
+ $this->resetNotices();
124
+ }
125
+ }
126
+
127
+ /**
128
+ * remove all notices and save reset file
129
+ */
130
+ public function resetNotices()
131
+ {
132
+ $this->nextStepNotices = array();
133
+ $this->finalReporNotices = array();
134
+ self::$uniqueCountId = 0;
135
+ $this->saveNotices();
136
+ }
137
+
138
+ /**
139
+ * return next step notice by id
140
+ *
141
+ * @param string $id
142
+ * @return DUPX_NOTICE_ITEM
143
+ */
144
+ public function getNextStepNoticeById($id)
145
+ {
146
+ if (isset($this->nextStepNotices[$id])) {
147
+ return $this->nextStepNotices[$id];
148
+ } else {
149
+ return null;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * return last report notice by id
155
+ *
156
+ * @param string $id
157
+ * @return DUPX_NOTICE_ITEM
158
+ */
159
+ public function getFinalReporNoticeById($id)
160
+ {
161
+ if (isset($this->finalReporNotices[$id])) {
162
+ return $this->finalReporNotices[$id];
163
+ } else {
164
+ return null;
165
+ }
166
+ }
167
+
168
+ /**
169
+ *
170
+ * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
171
+ * // if array must be [
172
+ * 'shortMsg' => text,
173
+ * 'level' => level,
174
+ * 'longMsg' => html text,
175
+ * 'sections' => sections list,
176
+ * 'faqLink' => [
177
+ * 'url' => external link
178
+ * 'label' => link text if empty get external url link
179
+ * ]
180
+ * ]
181
+ * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
182
+ * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
183
+ *
184
+ * @return string // notice insert id
185
+ *
186
+ * @throws Exception
187
+ */
188
+ public function addBothNextAndFinalReportNotice($item, $mode = self::ADD_NORMAL, $uniqueId = null)
189
+ {
190
+ $this->addNextStepNotice($item, $mode, $uniqueId);
191
+ $this->addFinalReportNotice($item, $mode, $uniqueId);
192
+ }
193
+
194
+ /**
195
+ *
196
+ * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
197
+ * // if array must be [
198
+ * 'shortMsg' => text,
199
+ * 'level' => level,
200
+ * 'longMsg' => html text,
201
+ * 'sections' => sections list,
202
+ * 'faqLink' => [
203
+ * 'url' => external link
204
+ * 'label' => link text if empty get external url link
205
+ * ]
206
+ * ]
207
+ * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
208
+ * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
209
+ *
210
+ * @return string // notice insert id
211
+ *
212
+ * @throws Exception
213
+ */
214
+ public function addNextStepNotice($item, $mode = self::ADD_NORMAL, $uniqueId = null)
215
+ {
216
+ if (!is_array($item) && !($item instanceof DUPX_NOTICE_ITEM)) {
217
+ throw new Exception('Invalid item param');
218
+ }
219
+ return self::addReportNoticeToList($this->nextStepNotices, $item, $mode, $uniqueId);
220
+ }
221
+
222
+ /**
223
+ * addNextStepNotice wrapper to add simple message with error level
224
+ *
225
+ * @param string $message
226
+ * @param int $level // warning level
227
+ * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
228
+ * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
229
+ *
230
+ * @return string // notice insert id
231
+ *
232
+ * @throws Exception
233
+ */
234
+ public function addNextStepNoticeMessage($message, $level = DUPX_NOTICE_ITEM::INFO, $mode = self::ADD_NORMAL, $uniqueId = null)
235
+ {
236
+ return $this->addNextStepNotice(array(
237
+ 'shortMsg' => $message,
238
+ 'level' => $level,
239
+ ), $mode, $uniqueId);
240
+ }
241
+
242
+ /**
243
+ *
244
+ * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
245
+ * // if array must be [
246
+ * 'shortMsg' => text,
247
+ * 'level' => level,
248
+ * 'longMsg' => html text,
249
+ * 'sections' => sections list,
250
+ * 'faqLink' => [
251
+ * 'url' => external link
252
+ * 'label' => link text if empty get external url link
253
+ * ]
254
+ * ]
255
+ * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
256
+ * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
257
+ *
258
+ * @return string // notice insert id
259
+ *
260
+ * @throws Exception
261
+ */
262
+ public function addFinalReportNotice($item, $mode = self::ADD_NORMAL, $uniqueId = null)
263
+ {
264
+ if (!is_array($item) && !($item instanceof DUPX_NOTICE_ITEM)) {
265
+ throw new Exception('Invalid item param');
266
+ }
267
+ return self::addReportNoticeToList($this->finalReporNotices, $item, $mode, $uniqueId);
268
+ }
269
+
270
+ /**
271
+ * addFinalReportNotice wrapper to add simple message with error level
272
+ *
273
+ * @param string $message
274
+ * @param string|string[] $sections // message sections on final report
275
+ * @param int $level // warning level
276
+ * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
277
+ * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
278
+ *
279
+ * @return string // notice insert id
280
+ *
281
+ * @throws Exception
282
+ */
283
+ public function addFinalReportNoticeMessage($message, $sections, $level = DUPX_NOTICE_ITEM::INFO, $mode = self::ADD_NORMAL, $uniqueId = null)
284
+ {
285
+ return $this->addFinalReportNotice(array(
286
+ 'shortMsg' => $message,
287
+ 'level' => $level,
288
+ 'sections' => $sections,
289
+ ), $mode, $uniqueId);
290
+ }
291
+
292
+ /**
293
+ *
294
+ * @param array $list
295
+ * @param array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
296
+ * // if array must be [
297
+ * 'shortMsg' => text,
298
+ * 'level' => level,
299
+ * 'longMsg' => html text,
300
+ * 'sections' => sections list,
301
+ * 'faqLink' => [
302
+ * 'url' => external link
303
+ * 'label' => link text if empty get external url link
304
+ * ]
305
+ * ]
306
+ * @param int $mode // ADD_NORMAL | ADD_UNIQUE | ADD_UNIQUE_UPDATE | ADD_UNIQUE_APPEND
307
+ * @param string $uniqueId // used for ADD_UNIQUE or ADD_UNIQUE_UPDATE or ADD_UNIQUE_APPEND
308
+ *
309
+ * @return string // notice insert id
310
+ *
311
+ * @throws Exception
312
+ */
313
+ private static function addReportNoticeToList(&$list, $item, $mode = self::ADD_NORMAL, $uniqueId = null)
314
+ {
315
+ switch ($mode) {
316
+ case self::ADD_UNIQUE:
317
+ if (empty($uniqueId)) {
318
+ throw new Exception('uniqueId can\'t be empty');
319
+ }
320
+ if (isset($list[$uniqueId])) {
321
+ return $uniqueId;
322
+ }
323
+ // no break -> continue on unique update
324
+ case self::ADD_UNIQUE_UPDATE:
325
+ if (empty($uniqueId)) {
326
+ throw new Exception('uniqueId can\'t be empty');
327
+ }
328
+ $insertId = $uniqueId;
329
+ break;
330
+ case self::ADD_UNIQUE_APPEND_IF_EXISTS:
331
+ if (empty($uniqueId)) {
332
+ throw new Exception('uniqueId can\'t be empty');
333
+ }
334
+ if (!isset($list[$uniqueId])) {
335
+ return false;
336
+ }
337
+ // no break
338
+ case self::ADD_UNIQUE_APPEND:
339
+ if (empty($uniqueId)) {
340
+ throw new Exception('uniqueId can\'t be empty');
341
+ }
342
+ $insertId = $uniqueId;
343
+ // if item id exist append long msg
344
+ if (isset($list[$uniqueId])) {
345
+ $tempObj = self::getObjFromParams($item);
346
+ $list[$uniqueId]->longMsg .= $tempObj->longMsg;
347
+ $item = $list[$uniqueId];
348
+ }
349
+ break;
350
+ case self::ADD_UNIQUE_PREPEND_IF_EXISTS:
351
+ if (empty($uniqueId)) {
352
+ throw new Exception('uniqueId can\'t be empty');
353
+ }
354
+ if (!isset($list[$uniqueId])) {
355
+ return false;
356
+ }
357
+ // no break
358
+ case self::ADD_UNIQUE_PREPEND:
359
+ if (empty($uniqueId)) {
360
+ throw new Exception('uniqueId can\'t be empty');
361
+ }
362
+ $insertId = $uniqueId;
363
+ // if item id exist append long msg
364
+ if (isset($list[$uniqueId])) {
365
+ $tempObj = self::getObjFromParams($item);
366
+ $list[$uniqueId]->longMsg = $tempObj->longMsg.$list[$uniqueId]->longMsg;
367
+ $item = $list[$uniqueId];
368
+ }
369
+ break;
370
+ case self::ADD_NORMAL:
371
+ default:
372
+ if (empty($uniqueId)) {
373
+ $insertId = self::getNewAutoUniqueId();
374
+ } else {
375
+ $insertId = $uniqueId;
376
+ }
377
+ }
378
+
379
+ $list[$insertId] = self::getObjFromParams($item);
380
+ return $insertId;
381
+ }
382
+
383
+ /**
384
+ *
385
+ * @param string|array|DUPX_NOTICE_ITEM $item // if string add new notice obj with item message and level param
386
+ * // if array must be [
387
+ * 'shortMsg' => text,
388
+ * 'level' => level,
389
+ * 'longMsg' => html text,
390
+ * 'sections' => sections list,
391
+ * 'faqLink' => [
392
+ * 'url' => external link
393
+ * 'label' => link text if empty get external url link
394
+ * ]
395
+ * ]
396
+ * @param int $level message level considered only in the case where $item is a string.
397
+ * @return \DUPX_NOTICE_ITEM
398
+ *
399
+ * @throws Exception
400
+ */
401
+ private static function getObjFromParams($item, $level = DUPX_NOTICE_ITEM::INFO)
402
+ {
403
+ if ($item instanceof DUPX_NOTICE_ITEM) {
404
+ $newObj = $item;
405
+ } else if (is_array($item)) {
406
+ $newObj = DUPX_NOTICE_ITEM::getItemFromArray($item);
407
+ } else if (is_string($item)) {
408
+ $newObj = new DUPX_NOTICE_ITEM($item, $level);
409
+ } else {
410
+ throw new Exception('Notice input not valid');
411
+ }
412
+
413
+ return $newObj;
414
+ }
415
+
416
+ /**
417
+ *
418
+ * @param null|string $section if null is count global
419
+ * @param int $level error level
420
+ * @param string $operator > < >= <= = !=
421
+ *
422
+ * @return int
423
+ */
424
+ public function countFinalReportNotices($section = null, $level = DUPX_NOTICE_ITEM::INFO, $operator = '>=')
425
+ {
426
+ $result = 0;
427
+ foreach ($this->finalReporNotices as $notice) {
428
+ if (is_null($section) || in_array($section, $notice->sections)) {
429
+ switch ($operator) {
430
+ case '>=':
431
+ $result += (int) ($notice->level >= $level);
432
+ break;
433
+ case '>':
434
+ $result += (int) ($notice->level > $level);
435
+ break;
436
+ case '=':
437
+ $result += (int) ($notice->level = $level);
438
+ break;
439
+ case '<=':
440
+ $result += (int) ($notice->level <= $level);
441
+ break;
442
+ case '<':
443
+ $result += (int) ($notice->level < $level);
444
+ break;
445
+ case '!=':
446
+ $result += (int) ($notice->level != $level);
447
+ break;
448
+ }
449
+ }
450
+ }
451
+ return $result;
452
+ }
453
+
454
+ /**
455
+ * sort final report notice from priority and notice level
456
+ */
457
+ public function sortFinalReport()
458
+ {
459
+ uasort($this->finalReporNotices, 'DUPX_NOTICE_ITEM::sortNoticeForPriorityAndLevel');
460
+ }
461
+
462
+ /**
463
+ * display final final report notice section
464
+ *
465
+ * @param string $section
466
+ */
467
+ public function displayFinalReport($section)
468
+ {
469
+ foreach ($this->finalReporNotices as $id => $notice) {
470
+ if (in_array($section, $notice->sections)) {
471
+ self::finalReportNotice($id, $notice);
472
+ }
473
+ }
474
+ }
475
+
476
+ /**
477
+ *
478
+ * @param string $section
479
+ * @param string $title
480
+ */
481
+ public function displayFinalRepostSectionHtml($section, $title)
482
+ {
483
+ if ($this->haveSection($section)) {
484
+ ?>
485
+ <div id="report-section-<?php echo $section; ?>" class="section" >
486
+ <div class="section-title" ><?php echo $title; ?></div>
487
+ <div class="section-content">
488
+ <?php
489
+ $this->displayFinalReport($section);
490
+ ?>
491
+ </div>
492
+ </div>
493
+ <?php
494
+ }
495
+ }
496
+
497
+ /**
498
+ *
499
+ * @param string $section
500
+ * @return boolean
501
+ */
502
+ public function haveSection($section)
503
+ {
504
+ foreach ($this->finalReporNotices as $notice) {
505
+ if (in_array($section, $notice->sections)) {
506
+ return true;
507
+ }
508
+ }
509
+ return false;
510
+ }
511
+
512
+ /**
513
+ *
514
+ * @param null|string $section if null is a global result
515
+ *
516
+ * @return int // returns the worst level found
517
+ *
518
+ */
519
+ public function getSectionErrLevel($section = null)
520
+ {
521
+ $result = DUPX_NOTICE_ITEM::INFO;
522
+
523
+ foreach ($this->finalReporNotices as $notice) {
524
+ if (is_null($section) || in_array($section, $notice->sections)) {
525
+ $result = max($result, $notice->level);
526
+ }
527
+ }
528
+ return $result;
529
+ }
530
+
531
+ /**
532
+ *
533
+ * @param string $section
534
+ * @param bool $echo
535
+ * @return void|string
536
+ */
537
+ public function getSectionErrLevelHtml($section = null, $echo = true)
538
+ {
539
+ return self::getErrorLevelHtml($this->getSectionErrLevel($section), $echo);
540
+ }
541
+
542
+ /**
543
+ * Displa next step notice message
544
+ *
545
+ * @param bool $deleteListAfterDisaply
546
+ * @return void
547
+ */
548
+ public function displayStepMessages($deleteListAfterDisaply = true)
549
+ {
550
+ if (empty($this->nextStepNotices)) {
551
+ return;
552
+ }
553
+ ?>
554
+ <div id="step-messages">
555
+ <?php
556
+ foreach ($this->nextStepNotices as $notice) {
557
+ self::stepMsg($notice);
558
+ }
559
+ ?>
560
+ </div>
561
+ <?php
562
+ if ($deleteListAfterDisaply) {
563
+ $this->nextStepNotices = array();
564
+ $this->saveNotices();
565
+ }
566
+ }
567
+
568
+ /**
569
+ *
570
+ * @param DUPX_NOTICE_ITEM $notice
571
+ */
572
+ private static function stepMsg($notice)
573
+ {
574
+ $classes = array(
575
+ 'notice',
576
+ 'next-step',
577
+ self::getClassFromLevel($notice->level)
578
+ );
579
+ $haveContent = !empty($notice->faqLink) || !empty($notice->longMsg);
580
+ ?>
581
+ <div class="<?php echo implode(' ', $classes); ?>">
582
+ <div class="title">
583
+ <?php echo self::getNextStepLevelPrefixMessage($notice->level).': <b>'.htmlentities($notice->shortMsg).'</b>'; ?>
584
+ </div>
585
+ <?php if ($haveContent) { ?>
586
+ <div class="title-separator" ></div>
587
+ <?php
588
+ ob_start();
589
+ if (!empty($notice->faqLink)) {
590
+ ?>
591
+ See FAQ: <a href="<?php echo $notice->faqLink['url']; ?>" >
592
+ <b><?php echo htmlentities(empty($notice->faqLink['label']) ? $notice->faqLink['url'] : $notice->faqLink['label']); ?></b>
593
+ </a>
594
+ <?php
595
+ }
596
+ if (!empty($notice->faqLink) && !empty($notice->longMsg)) {
597
+ echo '<br><br>';
598
+ }
599
+ if (!empty($notice->longMsg)) {
600
+ switch ($notice->longMsgMode) {
601
+ case DUPX_NOTICE_ITEM::MSG_MODE_PRE:
602
+ echo '<pre>'.htmlentities($notice->longMsg).'</pre>';
603
+ break;
604
+ case DUPX_NOTICE_ITEM::MSG_MODE_HTML:
605
+ echo $notice->longMsg;
606
+ break;
607
+ case DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT:
608
+ default:
609
+ echo htmlentities($notice->longMsg);
610
+ }
611
+ }
612
+ $longContent = ob_get_clean();
613
+ DUPX_U_Html::getMoreContent($longContent, 'info', 200);
614
+ }
615
+ ?>
616
+ </div>
617
+ <?php
618
+ }
619
+
620
+ /**
621
+ *
622
+ * @param string $id
623
+ * @param DUPX_NOTICE_ITEM $notice
624
+ */
625
+ private static function finalReportNotice($id, $notice)
626
+ {
627
+ $classes = array(
628
+ 'notice-report',
629
+ 'notice',
630
+ self::getClassFromLevel($notice->level)
631
+ );
632
+ $haveContent = !empty($notice->faqLink) || !empty($notice->longMsg);
633
+ $contentId = 'notice-content-'.$id;
634
+ $iconClasses = $haveContent ? 'fa fa-caret-right' : 'fa fa-toggle-empty';
635
+ $toggleLinkData = $haveContent ? 'data-type="toggle" data-target="#'.$contentId.'"' : '';
636
+ ?>
637
+ <div class="<?php echo implode(' ', $classes); ?>">
638
+ <div class="title" <?php echo $toggleLinkData; ?>>
639
+ <i class="<?php echo $iconClasses; ?>"></i> <?php echo htmlentities($notice->shortMsg); ?>
640
+ </div>
641
+ <?php
642
+ if ($haveContent) {
643
+ $infoClasses = array('info');
644
+ if (!$notice->open) {
645
+ $infoClasses[] = 'no-display';
646
+ }
647
+ ?>
648
+ <div id="<?php echo $contentId; ?>" class="<?php echo implode(' ', $infoClasses); ?>" >
649
+ <?php
650
+ if (!empty($notice->faqLink)) {
651
+ ?>
652
+ <b>See FAQ</b>: <a href="<?php echo $notice->faqLink['url']; ?>" >
653
+ <?php echo htmlentities(empty($notice->faqLink['label']) ? $notice->faqLink['url'] : $notice->faqLink['label']); ?>
654
+ </a>
655
+ <?php
656
+ }
657
+ if (!empty($notice->faqLink) && !empty($notice->longMsg)) {
658
+ echo '<br><br>';
659
+ }
660
+ if (!empty($notice->longMsg)) {
661
+ switch ($notice->longMsgMode) {
662
+ case DUPX_NOTICE_ITEM::MSG_MODE_PRE:
663
+ echo '<pre>'.htmlentities($notice->longMsg).'</pre>';
664
+ break;
665
+ case DUPX_NOTICE_ITEM::MSG_MODE_HTML:
666
+ echo $notice->longMsg;
667
+ break;
668
+ case DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT:
669
+ default:
670
+ echo htmlentities($notice->longMsg);
671
+ }
672
+ }
673
+ ?>
674
+ </div>
675
+ <?php
676
+ }
677
+ ?>
678
+ </div>
679
+ <?php
680
+ }
681
+
682
+ /**
683
+ *
684
+ * @param DUPX_NOTICE_ITEM $notice
685
+ */
686
+ private static function noticeToText($notice)
687
+ {
688
+ $result = '-----------------------'."\n".
689
+ '['.self::getNextStepLevelPrefixMessage($notice->level, false).'] '.$notice->shortMsg;
690
+
691
+ if (!empty($notice->sections)) {
692
+ $result .= "\n\t".'SECTIONS: '.implode(',', $notice->sections);
693
+ }
694
+ if (!empty($notice->longMsg)) {
695
+ $result .= "\n\t".'LONG MSG: '.$notice->longMsg;
696
+ }
697
+ return $result."\n";
698
+ }
699
+
700
+ public function nextStepLog()
701
+ {
702
+ if (!empty($this->nextStepNotices)) {
703
+ DUPX_Log::info(
704
+ '===================================='."\n".
705
+ 'NEXT STEP NOTICES'."\n".
706
+ '====================================');
707
+ foreach ($this->nextStepNotices as $notice) {
708
+ DUPX_Log::info(self::noticeToText($notice));
709
+ }
710
+ DUPX_Log::info(
711
+ '====================================');
712
+ }
713
+ }
714
+
715
+ public function finalReportLog($sections = array())
716
+ {
717
+ if (!empty($this->finalReporNotices)) {
718
+ DUPX_Log::info(
719
+ '===================================='."\n".
720
+ 'FINAL REPORT NOTICES LIST'."\n".
721
+ '====================================');
722
+ foreach ($this->finalReporNotices as $notice) {
723
+ if (count(array_intersect($notice->sections, $sections)) > 0) {
724
+ DUPX_Log::info(self::noticeToText($notice));
725
+ }
726
+ }
727
+ DUPX_Log::info(
728
+ '====================================');
729
+ }
730
+ }
731
+
732
+ /**
733
+ * get html class from level
734
+ *
735
+ * @param int $level
736
+ * @return string
737
+ */
738
+ private static function getClassFromLevel($level)
739
+ {
740
+ switch ($level) {
741
+ case DUPX_NOTICE_ITEM::INFO:
742
+ return 'l-info';
743
+ case DUPX_NOTICE_ITEM::NOTICE:
744
+ return 'l-notice';
745
+ case DUPX_NOTICE_ITEM::SOFT_WARNING:
746
+ return 'l-swarning';
747
+ case DUPX_NOTICE_ITEM::HARD_WARNING:
748
+ return 'l-hwarning';
749
+ case DUPX_NOTICE_ITEM::CRITICAL:
750
+ return 'l-critical';
751
+ case DUPX_NOTICE_ITEM::FATAL:
752
+ return 'l-fatal';
753
+ }
754
+ }
755
+
756
+ /**
757
+ * get level label from level
758
+ *
759
+ * @param int $level
760
+ * @param bool $echo
761
+ * @return type
762
+ */
763
+ public static function getErrorLevelHtml($level, $echo = true)
764
+ {
765
+ switch ($level) {
766
+ case DUPX_NOTICE_ITEM::INFO:
767
+ $label = 'good';
768
+ break;
769
+ case DUPX_NOTICE_ITEM::NOTICE:
770
+ $label = 'good';
771
+ break;
772
+ case DUPX_NOTICE_ITEM::SOFT_WARNING:
773
+ $label = 'warning';
774
+ break;
775
+ case DUPX_NOTICE_ITEM::HARD_WARNING:
776
+ $label = 'warning';
777
+ break;
778
+ case DUPX_NOTICE_ITEM::CRITICAL:
779
+ $label = 'critical error';
780
+ break;
781
+ case DUPX_NOTICE_ITEM::FATAL:
782
+ $label = 'fatal error';
783
+ break;
784
+ default:
785
+ return;
786
+ }
787
+ $classes = self::getClassFromLevel($level);
788
+ ob_start();
789
+ ?>
790
+ <span class="notice-level-status <?php echo $classes; ?>"><?php echo $label; ?></span>
791
+ <?php
792
+ if ($echo) {
793
+ ob_end_flush();
794
+ } else {
795
+ return ob_get_clean();
796
+ }
797
+ }
798
+
799
+ /**
800
+ * get next step message prefix
801
+ *
802
+ * @param int $level
803
+ * @param bool $echo
804
+ * @return string
805
+ */
806
+ public static function getNextStepLevelPrefixMessage($level, $echo = true)
807
+ {
808
+ switch ($level) {
809
+ case DUPX_NOTICE_ITEM::INFO:
810
+ $label = 'INFO';
811
+ break;
812
+ case DUPX_NOTICE_ITEM::NOTICE:
813
+ $label = 'NOTICE';
814
+ break;
815
+ case DUPX_NOTICE_ITEM::SOFT_WARNING:
816
+ $label = 'WARNING';
817
+ break;
818
+ case DUPX_NOTICE_ITEM::HARD_WARNING:
819
+ $label = 'WARNING';
820
+ break;
821
+ case DUPX_NOTICE_ITEM::CRITICAL:
822
+ $label = 'CRITICAL ERROR';
823
+ break;
824
+ case DUPX_NOTICE_ITEM::FATAL:
825
+ $label = 'FATAL ERROR';
826
+ break;
827
+ default:
828
+ return;
829
+ }
830
+
831
+ if ($echo) {
832
+ echo $label;
833
+ } else {
834
+ return $label;
835
+ }
836
+ }
837
+
838
+ /**
839
+ * get unique id
840
+ *
841
+ * @return string
842
+ */
843
+ private static function getNewAutoUniqueId()
844
+ {
845
+ self::$uniqueCountId ++;
846
+ return self::DEFAULT_UNIQUE_ID_PREFIX.self::$uniqueCountId;
847
+ }
848
+
849
+ /**
850
+ * function for internal test
851
+ *
852
+ * display all messages levels
853
+ */
854
+ public static function testNextStepMessaesLevels()
855
+ {
856
+ $manager = self::getInstance();
857
+ $manager->addNextStepNoticeMessage('Level info ('.DUPX_NOTICE_ITEM::INFO.')', DUPX_NOTICE_ITEM::INFO);
858
+ $manager->addNextStepNoticeMessage('Level notice ('.DUPX_NOTICE_ITEM::NOTICE.')', DUPX_NOTICE_ITEM::NOTICE);
859
+ $manager->addNextStepNoticeMessage('Level soft warning ('.DUPX_NOTICE_ITEM::SOFT_WARNING.')', DUPX_NOTICE_ITEM::SOFT_WARNING);
860
+ $manager->addNextStepNoticeMessage('Level hard warning ('.DUPX_NOTICE_ITEM::HARD_WARNING.')', DUPX_NOTICE_ITEM::HARD_WARNING);
861
+ $manager->addNextStepNoticeMessage('Level critical error ('.DUPX_NOTICE_ITEM::CRITICAL.')', DUPX_NOTICE_ITEM::CRITICAL);
862
+ $manager->addNextStepNoticeMessage('Level fatal error ('.DUPX_NOTICE_ITEM::FATAL.')', DUPX_NOTICE_ITEM::FATAL);
863
+ $manager->saveNotices();
864
+ }
865
+
866
+ /**
867
+ * test function
868
+ */
869
+ public static function testNextStepFullMessageData()
870
+ {
871
+ $manager = self::getInstance();
872
+ $longMsg = <<<LONGMSG
873
+ <b>Formattend long text</b><br>
874
+ <ul>
875
+ <li>Proin dapibus mi eu erat pulvinar, id congue nisl egestas.</li>
876
+ <li>Nunc venenatis eros et sapien ornare consequat.</li>
877
+ <li>Mauris tincidunt est sit amet turpis placerat, a tristique dui porttitor.</li>
878
+ <li>Etiam volutpat lectus quis risus molestie faucibus.</li>
879
+ <li>Integer gravida eros sit amet sem viverra, a volutpat neque rutrum.</li>
880
+ <li>Aenean varius ipsum vitae lorem tempus rhoncus.</li>
881
+ </ul>
882
+ LONGMSG;
883
+ $manager->addNextStepNotice(array(
884
+ 'shortMsg' => 'Full elements next step message MODE HTML',
885
+ 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
886
+ 'longMsg' => $longMsg,
887
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
888
+ 'faqLink' => array(
889
+ 'url' => 'http://www.google.it',
890
+ 'label' => 'google link'
891
+ )
892
+ ));
893
+
894
+ $longMsg = <<<LONGMSG
895
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc a auctor erat, et lobortis libero.
896
+ Suspendisse aliquet neque in massa posuere mollis. Donec venenatis finibus sapien in bibendum. Donec et ex massa.
897
+
898
+ Aliquam venenatis dapibus tellus nec ullamcorper. Mauris ante velit, tincidunt sit amet egestas et, mattis non lorem. In semper ex ut velit suscipit,
899
+ at luctus nunc dapibus. Etiam blandit maximus dapibus. Nullam eu porttitor augue. Suspendisse pulvinar, massa eget condimentum aliquet, dolor massa tempus dui, vel rhoncus tellus ligula non odio.
900
+ Ut ac faucibus tellus, in lobortis odio.
901
+ LONGMSG;
902
+ $manager->addNextStepNotice(array(
903
+ 'shortMsg' => 'Full elements next step message MODE PRE',
904
+ 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
905
+ 'longMsg' => $longMsg,
906
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE,
907
+ 'faqLink' => array(
908
+ 'url' => 'http://www.google.it',
909
+ 'label' => 'google link'
910
+ )
911
+ ));
912
+
913
+ $longMsg = <<<LONGMSG
914
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc a auctor erat, et lobortis libero.
915
+ Suspendisse aliquet neque in massa posuere mollis. Donec venenatis finibus sapien in bibendum. Donec et ex massa.
916
+
917
+ Aliquam venenatis dapibus tellus nec ullamcorper. Mauris ante velit, tincidunt sit amet egestas et, mattis non lorem. In semper ex ut velit suscipit,
918
+ at luctus nunc dapibus. Etiam blandit maximus dapibus. Nullam eu porttitor augue. Suspendisse pulvinar, massa eget condimentum aliquet, dolor massa tempus dui, vel rhoncus tellus ligula non odio.
919
+ Ut ac faucibus tellus, in lobortis odio.
920
+ LONGMSG;
921
+ $manager->addNextStepNotice(array(
922
+ 'shortMsg' => 'Full elements next step message MODE DEFAULT',
923
+ 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
924
+ 'longMsg' => $longMsg,
925
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT,
926
+ 'faqLink' => array(
927
+ 'url' => 'http://www.google.it',
928
+ 'label' => 'google link'
929
+ )
930
+ ));
931
+
932
+
933
+ $longMsg = <<<LONGMSG
934
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam cursus porttitor consectetur. Nunc faucibus elementum nisl nec ornare. Phasellus sit amet urna in diam ultricies ornare nec sit amet nibh. Nulla a aliquet leo. Quisque aliquet posuere lectus sit amet commodo. Nullam tempus enim eget urna rutrum egestas. Aliquam eget lorem nisl. Nulla tincidunt massa erat. Phasellus lectus tellus, mollis sit amet aliquam in, dapibus quis metus. Nunc venenatis nulla vitae convallis accumsan.
935
+
936
+ Mauris eu ullamcorper metus. Aenean ultricies et turpis eget mollis. Aliquam auctor, elit scelerisque placerat pellentesque, quam augue fermentum lectus, vel pretium nisi justo sit amet ante. Donec blandit porttitor tempus. Duis vulputate nulla ut orci rutrum, et consectetur urna mollis. Sed at iaculis velit. Pellentesque id quam turpis. Curabitur eu ligula velit. Cras gravida, ipsum sed iaculis eleifend, mauris nunc posuere quam, vel blandit nisi justo congue ligula. Phasellus aliquam eu odio ac porttitor. Fusce dictum mollis turpis sit amet fringilla.
937
+
938
+ Nulla eu ligula mauris. Fusce lobortis ligula elit, a interdum nibh pulvinar eu. Pellentesque rhoncus nec turpis id blandit. Morbi fringilla, justo non varius consequat, arcu ante efficitur ante, sit amet cursus lorem elit vel odio. Phasellus neque ligula, vehicula vel ipsum sed, volutpat dignissim eros. Curabitur at lacus id felis elementum auctor. Nullam ac tempus nisi. Phasellus nibh purus, aliquam nec purus ut, sodales lobortis nulla. Cras viverra dictum magna, ac malesuada nibh dictum ac. Mauris euismod, magna sit amet pretium posuere, ligula nibh ultrices tellus, sit amet pretium odio urna egestas justo. Suspendisse purus erat, eleifend sed magna in, efficitur interdum nibh.
939
+
940
+ Vivamus nibh nunc, fermentum non tortor volutpat, consectetur vulputate velit. Phasellus lobortis, purus et faucibus mollis, metus eros viverra ante, sit amet euismod nibh est eu orci. Duis sodales cursus lacinia. Praesent laoreet ut ipsum ut interdum. Praesent venenatis massa vitae ligula consequat aliquet. Fusce in purus in odio molestie laoreet at ac augue. Fusce consectetur elit a magna mollis aliquet.
941
+
942
+ Nulla eros nisi, dapibus eget diam vitae, tincidunt blandit odio. Fusce interdum tellus nec varius condimentum. Fusce non magna a purus sodales imperdiet sit amet vitae ligula. Quisque viverra leo sit amet mi egestas, et posuere nunc tincidunt. Suspendisse feugiat malesuada urna sed tincidunt. Morbi a urna sed magna volutpat pellentesque sit amet ac mauris. Nulla sed ultrices dui. Etiam massa arcu, tempor ut erat at, cursus malesuada ipsum. Duis sit amet felis dolor.
943
+
944
+ Morbi gravida nisl nunc, vulputate iaculis risus vehicula non. Proin cursus, velit et laoreet consectetur, lacus libero sagittis lacus, quis accumsan odio lectus non erat. Aenean dolor lectus, euismod sit amet justo eget, dictum gravida nisl. Phasellus sed nunc non odio ullamcorper rhoncus non ut ipsum. Duis ante ligula, pellentesque sit amet imperdiet eget, congue vel dui. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla facilisi. Suspendisse luctus leo eget justo mollis, convallis convallis ex suscipit. Integer et justo eget odio lobortis sollicitudin. Pellentesque accumsan rhoncus augue, luctus suscipit ex accumsan nec. Maecenas lacinia consectetur risus at bibendum. Etiam venenatis purus lorem, sit amet elementum turpis tristique eu. Proin vulputate faucibus feugiat. Nunc vehicula congue odio consequat vulputate. Quisque bibendum augue id iaculis faucibus. Donec blandit cursus sem, eget accumsan orci commodo sed.
945
+
946
+ Suspendisse iaculis est quam, sed scelerisque purus tincidunt non. Cras hendrerit ante turpis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse purus ipsum, rutrum id sem in, venenatis laoreet metus. Aliquam ac bibendum mauris. Cras egestas rhoncus est, sed lacinia nibh vestibulum id. Proin diam quam, sagittis congue molestie ac, rhoncus et mauris. Phasellus massa neque, ornare vel erat a, rutrum pharetra arcu. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi et nulla eget massa auctor fermentum. Quisque maximus tellus sed cursus cursus. Ut vehicula erat at purus aliquet, quis imperdiet dui sagittis. Nullam eget quam leo.
947
+
948
+ Nulla magna ipsum, congue nec dui ut, lacinia malesuada felis. Cras mattis metus non maximus venenatis. Aliquam euismod est vitae erat sollicitudin, at pellentesque augue sollicitudin. Curabitur euismod maximus cursus. In tortor dui, convallis sed sapien ac, varius congue metus. Nunc ullamcorper ac orci sit amet finibus. Vivamus molestie nibh vitae quam rhoncus, eu ultrices est molestie. Maecenas consectetur eu quam sit amet placerat.
949
+
950
+ Curabitur ut fermentum mauris. Donec et congue nibh. Sed cursus elit sit amet convallis varius. Donec malesuada porta odio condimentum varius. Pellentesque ornare tempor ante, ut volutpat nulla lobortis sed. Nunc congue aliquet erat ac elementum. Quisque a ex sit amet turpis placerat sagittis eget ac ligula. Etiam in augue malesuada, aliquam est non, lacinia justo. Vivamus tincidunt dolor orci, id dignissim lorem maximus at. Vivamus ligula mauris, venenatis vel nibh id, lacinia ultrices ipsum. Mauris cursus, urna ac rutrum aliquet, risus ipsum tincidunt purus, sit amet blandit nunc sem sit amet nibh.
951
+
952
+ Nam eleifend risus lacus, eu pharetra risus egestas eu. Maecenas hendrerit nisl in semper placerat. Vestibulum massa tellus, laoreet non euismod quis, sollicitudin id sapien. Morbi vel cursus metus. Aenean tincidunt nisi est, ut elementum est auctor id. Duis auctor elit leo, ac scelerisque risus suscipit et. Pellentesque lectus nisi, ultricies in elit sed, pulvinar iaculis massa. Morbi viverra eros mi, pretium facilisis neque egestas id. Curabitur non massa accumsan, porttitor sem vitae, ultricies lacus. Curabitur blandit nisl velit. Mauris sollicitudin ultricies purus sit amet placerat. Fusce ac neque sed leo venenatis laoreet ut non ex. Integer elementum rhoncus orci, eu maximus neque tempus eu. Curabitur euismod dignissim tellus, vitae lacinia metus. Mauris imperdiet metus vitae vulputate accumsan. Duis eget luctus nibh, sit amet finibus libero.
953
+
954
+ LONGMSG;
955
+ $manager->addNextStepNotice(array(
956
+ 'shortMsg' => 'Full elements LONG LONG',
957
+ 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
958
+ 'longMsg' => $longMsg,
959
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_DEFAULT,
960
+ 'faqLink' => array(
961
+ 'url' => 'http://www.google.it',
962
+ 'label' => 'google link'
963
+ )
964
+ ));
965
+
966
+
967
+
968
+
969
+ $manager->saveNotices();
970
+ }
971
+
972
+ /**
973
+ * test function
974
+ */
975
+ public static function testFinalReporMessaesLevels()
976
+ {
977
+ $section = 'general';
978
+
979
+ $manager = self::getInstance();
980
+ $manager->addFinalReportNoticeMessage('Level info ('.DUPX_NOTICE_ITEM::INFO.')', $section, DUPX_NOTICE_ITEM::INFO, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_0');
981
+ $manager->addFinalReportNoticeMessage('Level notice ('.DUPX_NOTICE_ITEM::NOTICE.')', $section, DUPX_NOTICE_ITEM::NOTICE, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_1');
982
+ $manager->addFinalReportNoticeMessage('Level soft warning ('.DUPX_NOTICE_ITEM::SOFT_WARNING.')', $section, DUPX_NOTICE_ITEM::SOFT_WARNING, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_2');
983
+ $manager->addFinalReportNoticeMessage('Level hard warning ('.DUPX_NOTICE_ITEM::HARD_WARNING.')', $section, DUPX_NOTICE_ITEM::HARD_WARNING, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_3');
984
+ $manager->addFinalReportNoticeMessage('Level critical error ('.DUPX_NOTICE_ITEM::CRITICAL.')', $section, DUPX_NOTICE_ITEM::CRITICAL, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_4');
985
+ $manager->addFinalReportNoticeMessage('Level fatal error ('.DUPX_NOTICE_ITEM::FATAL.')', $section, DUPX_NOTICE_ITEM::FATAL, DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_5');
986
+ $manager->saveNotices();
987
+ }
988
+
989
+ /**
990
+ * test function
991
+ */
992
+ public static function testFinalReportFullMessages()
993
+ {
994
+ $section = 'general';
995
+ $manager = self::getInstance();
996
+
997
+ $longMsg = <<<LONGMSG
998
+ <b>Formattend long text</b><br>
999
+ <ul>
1000
+ <li>Proin dapibus mi eu erat pulvinar, id congue nisl egestas.</li>
1001
+ <li>Nunc venenatis eros et sapien ornare consequat.</li>
1002
+ <li>Mauris tincidunt est sit amet turpis placerat, a tristique dui porttitor.</li>
1003
+ <li>Etiam volutpat lectus quis risus molestie faucibus.</li>
1004
+ <li>Integer gravida eros sit amet sem viverra, a volutpat neque rutrum.</li>
1005
+ <li>Aenean varius ipsum vitae lorem tempus rhoncus.</li>
1006
+ </ul>
1007
+ LONGMSG;
1008
+
1009
+ $manager->addFinalReportNotice(array(
1010
+ 'shortMsg' => 'Full elements final report message',
1011
+ 'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
1012
+ 'longMsg' => $longMsg,
1013
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
1014
+ 'sections' => $section,
1015
+ 'faqLink' => array(
1016
+ 'url' => 'http://www.google.it',
1017
+ 'label' => 'google link'
1018
+ )
1019
+ ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_full_1');
1020
+
1021
+ $manager->addFinalReportNotice(array(
1022
+ 'shortMsg' => 'Full elements final report message info high priority',
1023
+ 'level' => DUPX_NOTICE_ITEM::INFO,
1024
+ 'longMsg' => $longMsg,
1025
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
1026
+ 'sections' => $section,
1027
+ 'faqLink' => array(
1028
+ 'url' => 'http://www.google.it',
1029
+ 'label' => 'google link'
1030
+ ),
1031
+ 'priority' => 5
1032
+ ), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'test_fr_full_2');
1033
+ $manager->saveNotices();
1034
+ }
1035
+
1036
+ //PHP 8 Requires method to be public
1037
+ public function __wakeup()
1038
+ {
1039
+ }
1040
+
1041
+ private function __clone()
1042
+ {
1043
+
1044
+ }
1045
+ }
1046
+
1047
+ class DUPX_NOTICE_ITEM
1048
+ {
1049
+ const INFO = 0;
1050
+ const NOTICE = 1;
1051
+ const SOFT_WARNING = 2;
1052
+ const HARD_WARNING = 3;
1053
+ const CRITICAL = 4;
1054
+ const FATAL = 5;
1055
+ const MSG_MODE_DEFAULT = 'def';
1056
+ const MSG_MODE_HTML = 'html';
1057
+ const MSG_MODE_PRE = 'pre';
1058
+
1059
+ /**
1060
+ *
1061
+ * @var string text
1062
+ */
1063
+ public $shortMsg = '';
1064
+
1065
+ /**
1066
+ *
1067
+ * @var string html text
1068
+ */
1069
+ public $longMsg = '';
1070
+
1071
+ /**
1072
+ *
1073
+ * @var bool if true long msg can be html
1074
+ */
1075
+ public $longMsgMode = self::MSG_MODE_DEFAULT;
1076
+
1077
+ /**
1078
+ *
1079
+ * @var null|array // null = no faq link
1080
+ * array( 'label' => link text , 'url' => faq url)
1081
+ */
1082
+ public $faqLink = array(
1083
+ 'label' => '',
1084
+ 'url' => ''
1085
+ );
1086
+
1087
+ /**
1088
+ *
1089
+ * @var string[] notice sections for final report only
1090
+ */
1091
+ public $sections = array();
1092
+
1093
+ /**
1094
+ *
1095
+ * @var int
1096
+ */
1097
+ public $level = self::NOTICE;
1098
+
1099
+ /**
1100
+ *
1101
+ * @var int
1102
+ */
1103
+ public $priority = 10;
1104
+
1105
+ /**
1106
+ *
1107
+ * @var bool if true notice start open. For final report only
1108
+ */
1109
+ public $open = false;
1110
+
1111
+ /**
1112
+ *
1113
+ * @param string $shortMsg text
1114
+ * @param int $level
1115
+ * @param string $longMsg html text
1116
+ * @param string|string[] $sections
1117
+ * @param null|array $faqLink [
1118
+ * 'url' => external link
1119
+ * 'label' => link text if empty get external url link
1120
+ * ]
1121
+ * @param int priority
1122
+ * @param bool open
1123
+ * @param string longMsgMode MSG_MODE_DEFAULT | MSG_MODE_HTML | MSG_MODE_PRE
1124
+ */
1125
+ public function __construct($shortMsg, $level = self::INFO, $longMsg = '', $sections = array(), $faqLink = null, $priority = 10, $open = false, $longMsgMode = self::MSG_MODE_DEFAULT)
1126
+ {
1127
+ $this->shortMsg = (string) $shortMsg;
1128
+ $this->level = (int) $level;
1129
+ $this->longMsg = (string) $longMsg;
1130
+ $this->sections = is_array($sections) ? $sections : array($sections);
1131
+ $this->faqLink = $faqLink;
1132
+ $this->priority = $priority;
1133
+ $this->open = $open;
1134
+ $this->longMsgMode = $longMsgMode;
1135
+ }
1136
+
1137
+ /**
1138
+ *
1139
+ * @return array [
1140
+ * 'shortMsg' => text,
1141
+ * 'level' => level,
1142
+ * 'longMsg' => html text,
1143
+ * 'sections' => string|string[],
1144
+ * 'faqLink' => [
1145
+ * 'url' => external link
1146
+ * 'label' => link text if empty get external url link
1147
+ * ]
1148
+ * 'priority' => int low first
1149
+ * 'open' => if true the tab is opene on final report
1150
+ * 'longMsgMode'=> MSG_MODE_DEFAULT | MSG_MODE_HTML | MSG_MODE_PRE
1151
+ * ]
1152
+ */
1153
+ public function toArray()
1154
+ {
1155
+ return array(
1156
+ 'shortMsg' => $this->shortMsg,
1157
+ 'level' => $this->level,
1158
+ 'longMsg' => $this->longMsg,
1159
+ 'sections' => $this->sections,
1160
+ 'faqLink' => $this->faqLink,
1161
+ 'priority' => $this->priority,
1162
+ 'open' => $this->open,
1163
+ 'longMsgMode' => $this->longMsgMode
1164
+ );
1165
+ }
1166
+
1167
+ /**
1168
+ *
1169
+ * @return array [
1170
+ * 'shortMsg' => text,
1171
+ * 'level' => level,
1172
+ * 'longMsg' => html text,
1173
+ * 'sections' => string|string[],
1174
+ * 'faqLink' => [
1175
+ * 'url' => external link
1176
+ * 'label' => link text if empty get external url link
1177
+ * ],
1178
+ * priority
1179
+ * open
1180
+ * longMsgMode
1181
+ * ]
1182
+ * @return DUPX_NOTICE_ITEM
1183
+ */
1184
+ public static function getItemFromArray($array)
1185
+ {
1186
+ if (isset($array['sections']) && !is_array($array['sections'])) {
1187
+ if (empty($array['sections'])) {
1188
+ $array['sections'] = array();
1189
+ } else {
1190
+ $array['sections'] = array($array['sections']);
1191
+ }
1192
+ }
1193
+ $params = array_merge(self::getDefaultArrayParams(), $array);
1194
+ $result = new self($params['shortMsg'], $params['level'], $params['longMsg'], $params['sections'], $params['faqLink'], $params['priority'], $params['open'], $params['longMsgMode']);
1195
+ return $result;
1196
+ }
1197
+
1198
+ /**
1199
+ *
1200
+ * @return array [
1201
+ * 'shortMsg' => text,
1202
+ * 'level' => level,
1203
+ * 'longMsg' => html text,
1204
+ * 'sections' => string|string[],
1205
+ * 'faqLink' => [
1206
+ * 'url' => external link
1207
+ * 'label' => link text if empty get external url link
1208
+ * ],
1209
+ * priority
1210
+ * open
1211
+ * longMsgMode
1212
+ * ]
1213
+ */
1214
+ public static function getDefaultArrayParams()
1215
+ {
1216
+ return array(
1217
+ 'shortMsg' => '',
1218
+ 'level' => self::INFO,
1219
+ 'longMsg' => '',
1220
+ 'sections' => array(),
1221
+ 'faqLink' => null,
1222
+ 'priority' => 10,
1223
+ 'open' => false,
1224
+ 'longMsgMode' => self::MSG_MODE_DEFAULT
1225
+ );
1226
+ }
1227
+
1228
+ /**
1229
+ * before lower priority
1230
+ * before highest level
1231
+ *
1232
+ * @param DUPX_NOTICE_ITEM $a
1233
+ * @param DUPX_NOTICE_ITEM $b
1234
+ */
1235
+ public static function sortNoticeForPriorityAndLevel($a, $b)
1236
+ {
1237
+ if ($a->priority == $b->priority) {
1238
+ if ($a->level == $b->level) {
1239
+ return 0;
1240
+ } else if ($a->level < $b->level) {
1241
+ return 1;
1242
+ } else {
1243
+ return -1;
1244
+ }
1245
+ } else if ($a->priority < $b->priority) {
1246
+ return -1;
1247
+ } else {
1248
+ return 1;
1249
+ }
1250
+ }
1251
  }
installer/dup-installer/ctrls/classes/class.ctrl.extraction.php CHANGED
@@ -1,604 +1,605 @@
1
- <?php
2
- defined("DUPXABSPATH") or die("");
3
-
4
- class DUP_LITE_Extraction
5
- {
6
-
7
- const ACTION_DO_NOTHING = 'donothing';
8
- const ACTION_REMOVE_ALL_FILES = 'removeall';
9
- const ACTION_REMOVE_WP_FILES = 'removewpfiles';
10
- const INPUT_NAME_ARCHIVE_ACTION = 'archive_action';
11
-
12
- public $archive_action = self::ACTION_DO_NOTHING;
13
-
14
- /**
15
- *
16
- * @var self
17
- */
18
- protected static $instance = null;
19
-
20
- /**
21
- *
22
- * @return self
23
- */
24
- public static function getInstance()
25
- {
26
- if (is_null(self::$instance)) {
27
- self::$instance = new self;
28
- }
29
- return self::$instance;
30
- }
31
-
32
- private function __construct()
33
- {
34
- $this->initData();
35
- }
36
-
37
- /**
38
- * initialize extraction data
39
- */
40
- public function initData()
41
- {
42
- if ($_POST['archive_engine'] == 'manual') {
43
- $GLOBALS['DUPX_STATE']->isManualExtraction = true;
44
- $GLOBALS['DUPX_STATE']->save();
45
- }
46
- }
47
-
48
- /**
49
- *
50
- * @param string[] $folders
51
- */
52
- protected function removeFiles($folders = array())
53
- {
54
- $archive_path = $GLOBALS['FW_PACKAGE_PATH'];
55
-
56
- $excludeFiles = array(
57
- '/^'.preg_quote($archive_path, '/').'$/',
58
- '/^'.preg_quote(DUPX_CSRF::getVal('bootLogFile'), '/').'$/',
59
- '/^'.preg_quote(DUPX_CSRF::getVal('installerOrigPath'), '/').'$/',
60
- '/^'.preg_quote($GLOBALS['DUPX_ROOT'].'/wp-config.php', '/').'$/'
61
- );
62
-
63
- $excludeFolders = array(
64
- '/.+\/backups-dup-(lite|pro)$/',
65
- '/^'.preg_quote($GLOBALS['DUPX_INIT'], '/').'$/'
66
- );
67
-
68
- foreach (DUPX_Server::getWpAddonsSiteLists() as $addonPath) {
69
- $excludeFolders[] = '/^'.preg_quote($addonPath, '/').'$/';
70
- }
71
-
72
- foreach ($folders as $folder) {
73
- DUPX_Log::info('REMOVE FOLDER '.DUPX_Log::varToString($folder));
74
- DupLiteSnapLibIOU::regexGlobCallback($folder, function ($path) {
75
-
76
- if (is_dir($path)) {
77
- rmdir($path);
78
- } else {
79
- unlink($path);
80
- }
81
- }, array(
82
- 'regexFile' => $excludeFiles,
83
- 'regexFolder' => $excludeFolders,
84
- 'checkFullPath' => true,
85
- 'recursive' => true,
86
- 'invert' => true,
87
- 'childFirst' => true
88
- ));
89
- }
90
- }
91
-
92
- protected function removeWpFiles()
93
- {
94
- try {
95
- DUPX_Log::info('REMOVE WP FILES');
96
- DUPX_Log::resetTime(DUPX_Log::LV_DEFAULT, false);
97
-
98
- $absDir = DupLiteSnapLibIOU::trailingslashit($GLOBALS['DUPX_ROOT']);
99
- if (!is_dir($absDir) || !is_readable($absDir)) {
100
- return false;
101
- }
102
-
103
- $removeFolders = array();
104
-
105
- if (($dh = opendir($absDir))) {
106
- while (($elem = readdir($dh)) !== false) {
107
- if ($elem === '.' || $elem === '..') {
108
- continue;
109
- }
110
-
111
- if (DupLiteSnapLibUtilWp::isWpCore($elem, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
112
- $fullPath = $absDir.$elem;
113
- if (is_dir($fullPath)) {
114
- $removeFolders[] = $fullPath;
115
- } else {
116
- if (is_writable($fullPath)) {
117
- unlink($fullPath);
118
- }
119
- }
120
- }
121
- }
122
- closedir($dh);
123
- }
124
-
125
- $this->removeFiles(array_unique($removeFolders));
126
- DUPX_Log::logTime('FOLDERS REMOVED', DUPX_Log::LV_DEFAULT, false);
127
- }
128
- catch (Exception $e) {
129
- DUPX_Log::logException($e);
130
- }
131
- catch (Error $e) {
132
- DUPX_Log::logException($e);
133
- }
134
- }
135
-
136
- /**
137
- *
138
- */
139
- protected function removeAllFiles()
140
- {
141
- try {
142
- DUPX_Log::info('REMOVE ALL FILES');
143
- DUPX_Log::resetTime(DUPX_Log::LV_DEFAULT, false);
144
- $this->removeFiles(array($GLOBALS['DUPX_ROOT']));
145
- DUPX_Log::logTime('FOLDERS REMOVED', DUPX_Log::LV_DEFAULT, false);
146
- }
147
- catch (Exception $e) {
148
- DUPX_Log::logException($e);
149
- }
150
- catch (Error $e) {
151
- DUPX_Log::logException($e);
152
- }
153
- }
154
-
155
- /**
156
- * preliminary actions before the extraction.
157
- *
158
- * @return void
159
- */
160
- protected function beforeExtraction()
161
- {
162
- DUPX_Log::info('BEFORE EXTRACION ACTIONS');
163
-
164
- if (!$GLOBALS['DUPX_AC']->exportOnlyDB) {
165
- switch ($_POST[self::INPUT_NAME_ARCHIVE_ACTION]) {
166
- case self::ACTION_REMOVE_ALL_FILES:
167
- $this->removeAllFiles();
168
- break;
169
- case self::ACTION_REMOVE_WP_FILES:
170
- $this->removeWpFiles();
171
- break;
172
- case self::ACTION_DO_NOTHING:
173
- break;
174
- default:
175
- throw new Exception('Invalid engine action '.$_POST[self::INPUT_NAME_ARCHIVE_ACTION]);
176
- }
177
- }
178
- }
179
-
180
- /**
181
- *
182
- * @throws Exception
183
- */
184
- public function runExtraction()
185
- {
186
- //OPTIONS
187
- $_POST['set_file_perms'] = (isset($_POST['set_file_perms'])) ? 1 : 0;
188
- $_POST['set_dir_perms'] = (isset($_POST['set_dir_perms'])) ? 1 : 0;
189
- $_POST['file_perms_value'] = (isset($_POST['file_perms_value'])) ? DUPX_U::sanitize_text_field($_POST['file_perms_value']) : 0755;
190
- $_POST['dir_perms_value'] = (isset($_POST['dir_perms_value'])) ? DUPX_U::sanitize_text_field($_POST['dir_perms_value']) : 0644;
191
- $_POST['zip_filetime'] = (isset($_POST['zip_filetime'])) ? $_POST['zip_filetime'] : 'current';
192
- $_POST['config_mode'] = (isset($_POST['config_mode'])) ? $_POST['config_mode'] : 'NEW';
193
- $_POST[self::INPUT_NAME_ARCHIVE_ACTION] = (isset($_POST[self::INPUT_NAME_ARCHIVE_ACTION])) ? $_POST[self::INPUT_NAME_ARCHIVE_ACTION] : self::ACTION_DO_NOTHING;
194
- $_POST['archive_engine'] = (isset($_POST['archive_engine'])) ? $_POST['archive_engine'] : 'manual';
195
- $_POST['exe_safe_mode'] = (isset($_POST['exe_safe_mode'])) ? $_POST['exe_safe_mode'] : 0;
196
-
197
- //LOGGING
198
- $POST_LOG = $_POST;
199
- unset($POST_LOG['dbpass']);
200
- ksort($POST_LOG);
201
-
202
- //ACTION VARS
203
- $ajax1_start = DUPX_U::getMicrotime();
204
- $root_path = $GLOBALS['DUPX_ROOT'];
205
- $wpconfig_ark_path = ($GLOBALS['DUPX_AC']->installSiteOverwriteOn) ?
206
- "{$root_path}/dup-wp-config-arc__{$GLOBALS['DUPX_AC']->package_hash}.txt" : "{$root_path}/wp-config.php";
207
-
208
- $archive_path = $GLOBALS['FW_PACKAGE_PATH'];
209
- $dataResult = array();
210
- $dataResult['pass'] = 0;
211
-
212
- /** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
213
- cause errors in the JSON data Here we hide the status so warning level is reset at it at the end */
214
- $ajax1_error_level = error_reporting();
215
- error_reporting(E_ERROR);
216
-
217
- $nManager = DUPX_NOTICE_MANAGER::getInstance();
218
-
219
- //===============================
220
- //ARCHIVE ERROR MESSAGES
221
- //===============================
222
- ($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG);
223
-
224
- if (!$GLOBALS['DUPX_AC']->exportOnlyDB) {
225
-
226
- $post_archive_engine = DUPX_U::sanitize_text_field($_POST['archive_engine']);
227
-
228
- if ($post_archive_engine == 'manual') {
229
- if (!file_exists($wpconfig_ark_path) && !file_exists("database.sql")) {
230
- DUPX_Log::error(ERR_ZIPMANUAL);
231
- }
232
- } else {
233
- if (!is_readable("{$archive_path}")) {
234
- DUPX_Log::error("archive path:{$archive_path}<br/>".ERR_ZIPNOTFOUND);
235
- }
236
- }
237
-
238
- //ERR_ZIPMANUAL
239
- if (('ziparchive' == $post_archive_engine || 'shellexec_unzip' == $post_archive_engine) && !$GLOBALS['DUPX_AC']->installSiteOverwriteOn) {
240
- //ERR_CONFIG_FOUND
241
- $outer_root_path = dirname($root_path);
242
-
243
- if ((file_exists($wpconfig_ark_path) || (@file_exists("{$outer_root_path}/wp-config.php") && !@file_exists("{$outer_root_path}/wp-settings.php"))) && @file_exists("{$root_path}/wp-admin") && @file_exists("{$root_path}/wp-includes")) {
244
- DUPX_Log::error(ERR_CONFIG_FOUND);
245
- }
246
- }
247
- }
248
-
249
- DUPX_Log::info("********************************************************************************");
250
- DUPX_Log::info('* DUPLICATOR-LITE: Install-Log');
251
- DUPX_Log::info('* STEP-1 START @ '.@date('h:i:s'));
252
- DUPX_Log::info("* VERSION: {$GLOBALS['DUPX_AC']->version_dup}");
253
- DUPX_Log::info('* NOTICE: Do NOT post to public sites or forums!!');
254
- DUPX_Log::info("********************************************************************************");
255
-
256
- $colSize = 60;
257
- $labelPadSize = 20;
258
- $os = defined('PHP_OS') ? PHP_OS : 'unknown';
259
- $log = str_pad(str_pad('PACKAGE INFO', $labelPadSize, '_', STR_PAD_RIGHT).' '.'CURRENT SERVER', $colSize, ' ', STR_PAD_RIGHT).'|'.'ORIGINAL SERVER'."\n".
260
- str_pad(str_pad('PHP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_php, $colSize, ' ', STR_PAD_RIGHT).'|'.phpversion()."\n".
261
- str_pad(str_pad('OS', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_os, $colSize, ' ', STR_PAD_RIGHT).'|'.$os."\n".
262
- str_pad('CREATED', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->created."\n".
263
- str_pad('WP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_wp."\n".
264
- str_pad('DUP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_dup."\n".
265
- str_pad('DB', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_db."\n".
266
- str_pad('DB TABLES', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesFinalCount."\n".
267
- str_pad('DB ROWS', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesRowCount."\n".
268
- str_pad('DB FILE SIZE', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesSizeOnDisk."\n".
269
- "********************************************************************************";
270
- DUPX_Log::info($log);
271
- DUPX_Log::info("SERVER INFO");
272
- DUPX_Log::info(str_pad('PHP', $labelPadSize, '_', STR_PAD_RIGHT).': '.phpversion().' | SAPI: '.php_sapi_name());
273
- DUPX_Log::info(str_pad('PHP MEMORY', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['PHP_MEMORY_LIMIT'].' | SUHOSIN: '.$GLOBALS['PHP_SUHOSIN_ON']);
274
- DUPX_Log::info(str_pad('SERVER', $labelPadSize, '_', STR_PAD_RIGHT).': '.$_SERVER['SERVER_SOFTWARE']);
275
- DUPX_Log::info(str_pad('DOC ROOT', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($root_path));
276
- DUPX_Log::info(str_pad('DOC ROOT 755', $labelPadSize, '_', STR_PAD_RIGHT).': '.var_export($GLOBALS['CHOWN_ROOT_PATH'], true));
277
- DUPX_Log::info(str_pad('LOG FILE 644', $labelPadSize, '_', STR_PAD_RIGHT).': '.var_export($GLOBALS['CHOWN_LOG_PATH'], true));
278
- DUPX_Log::info(str_pad('REQUEST URL', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($GLOBALS['URL_PATH']));
279
-
280
- DUPX_Log::info("********************************************************************************");
281
- DUPX_Log::info("USER INPUTS");
282
- DUPX_Log::info(str_pad('ARCHIVE ACTION', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST[self::INPUT_NAME_ARCHIVE_ACTION]));
283
- DUPX_Log::info(str_pad('ARCHIVE ENGINE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['archive_engine']));
284
- DUPX_Log::info(str_pad('SET DIR PERMS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['set_dir_perms']));
285
- DUPX_Log::info(str_pad('DIR PERMS VALUE', $labelPadSize, '_', STR_PAD_RIGHT).': '.decoct($_POST['dir_perms_value']));
286
- DUPX_Log::info(str_pad('SET FILE PERMS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['set_file_perms']));
287
- DUPX_Log::info(str_pad('FILE PERMS VALUE', $labelPadSize, '_', STR_PAD_RIGHT).': '.decoct($_POST['file_perms_value']));
288
- DUPX_Log::info(str_pad('SAFE MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['exe_safe_mode']));
289
- DUPX_Log::info(str_pad('LOGGING', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['logging']));
290
- DUPX_Log::info(str_pad('CONFIG MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['config_mode']));
291
- DUPX_Log::info(str_pad('FILE TIME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['zip_filetime']));
292
- DUPX_Log::info("********************************************************************************\n");
293
-
294
- $log = "--------------------------------------\n";
295
- $log .= "POST DATA\n";
296
- $log .= "--------------------------------------\n";
297
- $log .= print_r($POST_LOG, true);
298
- DUPX_Log::info($log, DUPX_Log::LV_DEBUG);
299
-
300
- $log = "\n--------------------------------------\n";
301
- $log .= "ARCHIVE SETUP\n";
302
- $log .= "--------------------------------------\n";
303
- $log .= str_pad('NAME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($GLOBALS['FW_PACKAGE_PATH'])."\n";
304
- if (file_exists($GLOBALS['FW_PACKAGE_PATH'])) {
305
- $log .= str_pad('SIZE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_U::readableByteSize(@filesize($GLOBALS['FW_PACKAGE_PATH']));
306
- }
307
- DUPX_Log::info($log."\n", DUPX_Log::LV_DEFAULT, true);
308
-
309
- DUPX_Log::info('PRE-EXTRACT-CHECKS');
310
- DUPX_ServerConfig::beforeExtractionSetup();
311
-
312
- $this->beforeExtraction();
313
-
314
- $target = $root_path;
315
- DUPX_U::maintenanceMode(true);
316
-
317
- $post_archive_engine = DUPX_U::sanitize_text_field($_POST['archive_engine']);
318
- switch ($post_archive_engine) {
319
-
320
- //-----------------------
321
- //MANUAL EXTRACTION
322
- case 'manual':
323
- DUPX_Log::info("\n** PACKAGE EXTRACTION IS IN MANUAL MODE ** \n");
324
- break;
325
-
326
- //-----------------------
327
- //SHELL EXEC
328
- case 'shellexec_unzip':
329
- DUPX_Log::info("\n\nSTART ZIP FILE EXTRACTION SHELLEXEC >>> ");
330
- $shell_exec_path = DUPX_Server::get_unzip_filepath();
331
-
332
-
333
- $command = escapeshellcmd($shell_exec_path)." -o -qq ".escapeshellarg($archive_path)." -d ".escapeshellarg($target)." 2>&1";
334
- if ($_POST['zip_filetime'] == 'original') {
335
- DUPX_Log::info("\nShell Exec Current does not support orginal file timestamp please use ZipArchive");
336
- }
337
-
338
- DUPX_Log::info(">>> Starting Shell-Exec Unzip:\nCommand: {$command}", DUPX_Log::LV_DEBUG);
339
- $stderr = shell_exec($command);
340
- if ($stderr != '') {
341
- $zip_err_msg = ERR_SHELLEXEC_ZIPOPEN.": $stderr";
342
- $zip_err_msg .= "<br/><br/><b>To resolve error see <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q' target='_blank'>https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q</a></b>";
343
- DUPX_Log::error($zip_err_msg);
344
- }
345
- DUPX_Log::info("<<< Shell-Exec Unzip Complete.");
346
-
347
- break;
348
-
349
- //-----------------------
350
- //ZIP-ARCHIVE
351
- case 'ziparchive':
352
- DUPX_Log::info("\n\nSTART ZIP FILE EXTRACTION STANDARD >>> ");
353
-
354
- if (!class_exists('ZipArchive')) {
355
- DUPX_Log::info("ERROR: Stopping install process. Trying to extract without ZipArchive module installed. Please use the 'Manual Archive Extraction' mode to extract zip file.");
356
- DUPX_Log::error(ERR_ZIPARCHIVE);
357
- }
358
-
359
- if (($dupInstallerFolder = DUPX_U::findDupInstallerFolder($archive_path)) === false) {
360
- DUPX_Log::info("findDupInstallerFolder error; set no subfolder");
361
- // if not found set not subfolder
362
- $dupInstallerFolder = '';
363
- }
364
- if (!empty($dupInstallerFolder)) {
365
- DUPX_Log::info("ARCHIVE dup-installer SUBFOLDER:\"".$dupInstallerFolder."\"");
366
- } else {
367
- DUPX_Log::info("ARCHIVE dup-installer SUBFOLDER:\"".$dupInstallerFolder."\"", 2);
368
- }
369
-
370
- $dupInstallerZipPath = $dupInstallerFolder.'/dup-installer';
371
-
372
- $zip = new ZipArchive();
373
-
374
- if ($zip->open($archive_path) === TRUE) {
375
- $extract_filenames = array();
376
- DUPX_Handler::setMode(DUPX_Handler::MODE_VAR, false, false);
377
-
378
- for ($i = 0; $i < $zip->numFiles; $i++) {
379
- $extract_filename = $zip->getNameIndex($i);
380
-
381
- // skip dup-installer folder. Alrady extracted in bootstrap
382
- if (
383
- (strpos($extract_filename, $dupInstallerZipPath) === 0) ||
384
- (!empty($dupInstallerFolder) && strpos($extract_filename, $dupInstallerFolder) !== 0)
385
- ) {
386
- DUPX_Log::info("SKIPPING NOT IN ZIPATH:\"".DUPX_Log::varToString($extract_filename)."\"", DUPX_Log::LV_DETAILED);
387
- continue;
388
- }
389
-
390
- try {
391
- if (!$zip->extractTo($target, $extract_filename)) {
392
- if (DupLiteSnapLibUtilWp::isWpCore($extract_filename, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
393
- DUPX_Log::info("FILE CORE EXTRACION ERROR: ".$extract_filename);
394
- $shortMsg = 'Can\'t extract wp core files';
395
- $finalShortMsg = 'Wp core files not extracted';
396
- $errLevel = DUPX_NOTICE_ITEM::CRITICAL;
397
- $idManager = 'wp-extract-error-file-core';
398
- } else {
399
- DUPX_Log::info("FILE EXTRACION ERROR: ".$extract_filename);
400
- $shortMsg = 'Can\'t extract files';
401
- $finalShortMsg = 'Files not extracted';
402
- $errLevel = DUPX_NOTICE_ITEM::SOFT_WARNING;
403
- $idManager = 'wp-extract-error-file-no-core';
404
- }
405
- $longMsg = 'FILE: <b>'.htmlspecialchars($extract_filename).'</b><br>Message: '.htmlspecialchars(DUPX_Handler::getVarLogClean()).'<br><br>';
406
-
407
- $nManager->addNextStepNotice(array(
408
- 'shortMsg' => $shortMsg,
409
- 'longMsg' => $longMsg,
410
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
411
- 'level' => $errLevel
412
- ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
413
- $nManager->addFinalReportNotice(array(
414
- 'shortMsg' => $finalShortMsg,
415
- 'longMsg' => $longMsg,
416
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
417
- 'level' => $errLevel,
418
- 'sections' => array('files'),
419
- ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
420
- } else {
421
- DUPX_Log::info("FILE EXTRACTION DONE: ".DUPX_Log::varToString($extract_filename), DUPX_Log::LV_HARD_DEBUG);
422
- }
423
- }
424
- catch (Exception $ex) {
425
- if (DupLiteSnapLibUtilWp::isWpCore($extract_filename, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
426
- DUPX_Log::info("FILE CORE EXTRACION ERROR: {$extract_filename} | MSG:".$ex->getMessage());
427
- $shortMsg = 'Can\'t extract wp core files';
428
- $finalShortMsg = 'Wp core files not extracted';
429
- $errLevel = DUPX_NOTICE_ITEM::CRITICAL;
430
- $idManager = 'wp-extract-error-file-core';
431
- } else {
432
- DUPX_Log::info("FILE EXTRACION ERROR: {$extract_filename} | MSG:".$ex->getMessage());
433
- $shortMsg = 'Can\'t extract files';
434
- $finalShortMsg = 'Files not extracted';
435
- $errLevel = DUPX_NOTICE_ITEM::SOFT_WARNING;
436
- $idManager = 'wp-extract-error-file-no-core';
437
- }
438
- $longMsg = 'FILE: <b>'.htmlspecialchars($extract_filename).'</b><br>Message: '.htmlspecialchars($ex->getMessage()).'<br><br>';
439
-
440
- $nManager->addNextStepNotice(array(
441
- 'shortMsg' => $shortMsg,
442
- 'longMsg' => $longMsg,
443
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
444
- 'level' => $errLevel
445
- ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
446
- $nManager->addFinalReportNotice(array(
447
- 'shortMsg' => $finalShortMsg,
448
- 'longMsg' => $longMsg,
449
- 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
450
- 'level' => $errLevel,
451
- 'sections' => array('files'),
452
- ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
453
- }
454
- }
455
-
456
- if (!empty($dupInstallerFolder)) {
457
- DUPX_U::moveUpfromSubFolder($target.'/'.$dupInstallerFolder, true);
458
- }
459
-
460
- //Uncomment if needed
461
- //if (DUPX_Log::isLevel(DUPX_Log::LV_DEBUG)) {
462
- // $log = print_r($zip, true);
463
- //}
464
- //FILE-TIMESTAMP
465
- if ($_POST['zip_filetime'] == 'original') {
466
- $log .= "File timestamp set to Original\n";
467
- for ($idx = 0; $s = $zip->statIndex($idx); $idx++) {
468
- touch($target.DIRECTORY_SEPARATOR.$s['name'], $s['mtime']);
469
- }
470
- } else {
471
- $now = @date("Y-m-d H:i:s");
472
- $log .= "File timestamp set to Current: {$now}\n";
473
- }
474
-
475
- // set handler as default
476
- DUPX_Handler::setMode();
477
-
478
- $close_response = $zip->close();
479
- $log .= "<<< ZipArchive Unzip Complete: ".var_export($close_response, true);
480
- DUPX_Log::info($log);
481
- } else {
482
- $zip_err_msg = ERR_ZIPOPEN;
483
- $zip_err_msg .= "<br/><br/><b>To resolve error see <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q' target='_blank'>https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q</a></b>";
484
- DUPX_Log::error($zip_err_msg);
485
- }
486
-
487
- break;
488
-
489
- //-----------------------
490
- //DUP-ARCHIVE
491
- case 'duparchive':
492
- DUPX_Log::info(">>> DupArchive Extraction Complete");
493
-
494
- if (isset($_POST['extra_data'])) {
495
- $extraData = $_POST['extra_data'];
496
-
497
- $log = "\n--------------------------------------\n";
498
- $log .= "DUPARCHIVE EXTRACTION STATUS\n";
499
- $log .= "--------------------------------------\n";
500
-
501
- $dawsStatus = json_decode($extraData);
502
-
503
- if ($dawsStatus === null) {
504
- $log .= "Can't decode the dawsStatus!\n";
505
- $log .= print_r(extraData, true);
506
- } else {
507
- $criticalPresent = false;
508
-
509
- if (count($dawsStatus->failures) > 0) {
510
- $log .= "Archive extracted with errors.\n";
511
-
512
- foreach ($dawsStatus->failures as $failure) {
513
- if ($failure->isCritical) {
514
- $log .= '(C) ';
515
- $criticalPresent = true;
516
- }
517
- $log .= "{$failure->description}\n";
518
- }
519
- } else {
520
- $log .= "Archive extracted with no errors.\n";
521
- }
522
-
523
- if ($criticalPresent) {
524
- $log .= "\n\nCritical Errors present so stopping install.\n";
525
- exit();
526
- }
527
- }
528
-
529
- DUPX_Log::info($log);
530
- } else {
531
- DUPX_LOG::info("DAWS STATUS: UNKNOWN since extra_data wasn't in post!");
532
- }
533
-
534
- break;
535
- }
536
-
537
- $log = "--------------------------------------\n";
538
- $log .= "POST-EXTACT-CHECKS\n";
539
- $log .= "--------------------------------------";
540
- DUPX_Log::info($log);
541
-
542
- //===============================
543
- //FILE PERMISSIONS
544
- if ($_POST['set_file_perms'] || $_POST['set_dir_perms']) {
545
- $set_file_perms = $_POST['set_file_perms'];
546
- $set_dir_perms = $_POST['set_dir_perms'];
547
- $set_file_mtime = ($_POST['zip_filetime'] == 'current');
548
- $file_perms_value = $_POST['file_perms_value'] ? $_POST['file_perms_value'] : 0755;
549
- $dir_perms_value = $_POST['dir_perms_value'] ? $_POST['dir_perms_value'] : 0644;
550
-
551
- DUPX_Log::info("PERMISSION UPDATES:");
552
- DUPX_Log::info(" -DIRS: '{$dir_perms_value}'");
553
- DUPX_Log::info(" -FILES: '{$file_perms_value}'");
554
-
555
- $objects = new RecursiveIteratorIterator(new IgnorantRecursiveDirectoryIterator($root_path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
556
-
557
- foreach ($objects as $name => $object) {
558
- if ($set_file_perms && is_file($name)) {
559
- DUPX_Log::info("SET PERMISSION: ".DUPX_Log::varToString($name).'[MODE:'.$file_perms_value.']', DUPX_Log::LV_HARD_DEBUG);
560
- if (!DupLiteSnapLibIOU::chmod($name, $file_perms_value)) {
561
- DUPX_Log::info("Permissions setting on file '{$name}' failed");
562
- }
563
- } else if ($set_dir_perms && is_dir($name)) {
564
- DUPX_Log::info("SET PERMISSION: ".DUPX_Log::varToString($name).'[MODE:'.$dir_perms_value.']', DUPX_Log::LV_HARD_DEBUG);
565
- if (!DupLiteSnapLibIOU::chmod($name, $dir_perms_value)) {
566
- DUPX_Log::info("Permissions setting on directory '{$name}' failed");
567
- }
568
- }
569
- if ($set_file_mtime) {
570
- @touch($name);
571
- }
572
- }
573
- } else {
574
- DUPX_Log::info("\nPERMISSION UPDATES: None Applied");
575
- }
576
-
577
- DUPX_ServerConfig::afterExtractionSetup();
578
- $nManager->saveNotices();
579
-
580
- //FINAL RESULTS
581
- $ajax1_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $ajax1_start);
582
- DUPX_Log::info("\nSTEP-1 COMPLETE @ ".@date('h:i:s')." - RUNTIME: {$ajax1_sum}");
583
-
584
- $dataResult['pass'] = 1;
585
- error_reporting($ajax1_error_level);
586
- fclose($GLOBALS["LOG_FILE_HANDLE"]);
587
- return $dataResult;
588
- }
589
- }
590
-
591
- // Skips past paths it can't read
592
- class IgnorantRecursiveDirectoryIterator extends RecursiveDirectoryIterator
593
- {
594
-
595
- function getChildren()
596
- {
597
- try {
598
- return new IgnorantRecursiveDirectoryIterator($this->getPathname(), RecursiveDirectoryIterator::SKIP_DOTS);
599
- }
600
- catch (UnexpectedValueException $e) {
601
- return new RecursiveArrayIterator(array());
602
- }
603
- }
 
604
  }
1
+ <?php
2
+ defined("DUPXABSPATH") or die("");
3
+
4
+ class DUP_LITE_Extraction
5
+ {
6
+
7
+ const ACTION_DO_NOTHING = 'donothing';
8
+ const ACTION_REMOVE_ALL_FILES = 'removeall';
9
+ const ACTION_REMOVE_WP_FILES = 'removewpfiles';
10
+ const INPUT_NAME_ARCHIVE_ACTION = 'archive_action';
11
+
12
+ public $archive_action = self::ACTION_DO_NOTHING;
13
+
14
+ /**
15
+ *
16
+ * @var self
17
+ */
18
+ protected static $instance = null;
19
+
20
+ /**
21
+ *
22
+ * @return self
23
+ */
24
+ public static function getInstance()
25
+ {
26
+ if (is_null(self::$instance)) {
27
+ self::$instance = new self;
28
+ }
29
+ return self::$instance;
30
+ }
31
+
32
+ private function __construct()
33
+ {
34
+ $this->initData();
35
+ }
36
+
37
+ /**
38
+ * initialize extraction data
39
+ */
40
+ public function initData()
41
+ {
42
+ if ($_POST['archive_engine'] == 'manual') {
43
+ $GLOBALS['DUPX_STATE']->isManualExtraction = true;
44
+ $GLOBALS['DUPX_STATE']->save();
45
+ }
46
+ }
47
+
48
+ /**
49
+ *
50
+ * @param string[] $folders
51
+ */
52
+ protected function removeFiles($folders = array())
53
+ {
54
+ $archive_path = $GLOBALS['FW_PACKAGE_PATH'];
55
+
56
+ $excludeFiles = array(
57
+ '/^'.preg_quote($archive_path, '/').'$/',
58
+ '/^'.preg_quote(DUPX_CSRF::getVal('bootLogFile'), '/').'$/',
59
+ '/^'.preg_quote(DUPX_CSRF::getVal('installerOrigPath'), '/').'$/',
60
+ '/^'.preg_quote($GLOBALS['DUPX_ROOT'].'/wp-config.php', '/').'$/'
61
+ );
62
+
63
+ $excludeFolders = array(
64
+ '/.+\/backups-dup-(lite|pro)$/',
65
+ '/^'.preg_quote($GLOBALS['DUPX_INIT'], '/').'$/'
66
+ );
67
+
68
+ foreach (DUPX_Server::getWpAddonsSiteLists() as $addonPath) {
69
+ $excludeFolders[] = '/^'.preg_quote($addonPath, '/').'$/';
70
+ }
71
+
72
+ foreach ($folders as $folder) {
73
+ DUPX_Log::info('REMOVE FOLDER '.DUPX_Log::varToString($folder));
74
+ DupLiteSnapLibIOU::regexGlobCallback($folder, function ($path) {
75
+
76
+ if (is_dir($path)) {
77
+ rmdir($path);
78
+ } else {
79
+ unlink($path);
80
+ }
81
+ }, array(
82
+ 'regexFile' => $excludeFiles,
83
+ 'regexFolder' => $excludeFolders,
84
+ 'checkFullPath' => true,
85
+ 'recursive' => true,
86
+ 'invert' => true,
87
+ 'childFirst' => true
88
+ ));
89
+ }
90
+ }
91
+
92
+ protected function removeWpFiles()
93
+ {
94
+ try {
95
+ DUPX_Log::info('REMOVE WP FILES');
96
+ DUPX_Log::resetTime(DUPX_Log::LV_DEFAULT, false);
97
+
98
+ $absDir = DupLiteSnapLibIOU::trailingslashit($GLOBALS['DUPX_ROOT']);
99
+ if (!is_dir($absDir) || !is_readable($absDir)) {
100
+ return false;
101
+ }
102
+
103
+ $removeFolders = array();
104
+
105
+ if (($dh = opendir($absDir))) {
106
+ while (($elem = readdir($dh)) !== false) {
107
+ if ($elem === '.' || $elem === '..') {
108
+ continue;
109
+ }
110
+
111
+ if (DupLiteSnapLibUtilWp::isWpCore($elem, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
112
+ $fullPath = $absDir.$elem;
113
+ if (is_dir($fullPath)) {
114
+ $removeFolders[] = $fullPath;
115
+ } else {
116
+ if (is_writable($fullPath)) {
117
+ unlink($fullPath);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ closedir($dh);
123
+ }
124
+
125
+ $this->removeFiles(array_unique($removeFolders));
126
+ DUPX_Log::logTime('FOLDERS REMOVED', DUPX_Log::LV_DEFAULT, false);
127
+ }
128
+ catch (Exception $e) {
129
+ DUPX_Log::logException($e);
130
+ }
131
+ catch (Error $e) {
132
+ DUPX_Log::logException($e);
133
+ }
134
+ }
135
+
136
+ /**
137
+ *
138
+ */
139
+ protected function removeAllFiles()
140
+ {
141
+ try {
142
+ DUPX_Log::info('REMOVE ALL FILES');
143
+ DUPX_Log::resetTime(DUPX_Log::LV_DEFAULT, false);
144
+ $this->removeFiles(array($GLOBALS['DUPX_ROOT']));
145
+ DUPX_Log::logTime('FOLDERS REMOVED', DUPX_Log::LV_DEFAULT, false);
146
+ }
147
+ catch (Exception $e) {
148
+ DUPX_Log::logException($e);
149
+ }
150
+ catch (Error $e) {
151
+ DUPX_Log::logException($e);
152
+ }
153
+ }
154
+
155
+ /**
156
+ * preliminary actions before the extraction.
157
+ *
158
+ * @return void
159
+ */
160
+ protected function beforeExtraction()
161
+ {
162
+ DUPX_Log::info('BEFORE EXTRACION ACTIONS');
163
+
164
+ if (!$GLOBALS['DUPX_AC']->exportOnlyDB) {
165
+ switch ($_POST[self::INPUT_NAME_ARCHIVE_ACTION]) {
166
+ case self::ACTION_REMOVE_ALL_FILES:
167
+ $this->removeAllFiles();
168
+ break;
169
+ case self::ACTION_REMOVE_WP_FILES:
170
+ $this->removeWpFiles();
171
+ break;
172
+ case self::ACTION_DO_NOTHING:
173
+ break;
174
+ default:
175
+ throw new Exception('Invalid engine action '.$_POST[self::INPUT_NAME_ARCHIVE_ACTION]);
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ *
182
+ * @throws Exception
183
+ */
184
+ public function runExtraction()
185
+ {
186
+ //OPTIONS
187
+ $_POST['set_file_perms'] = (isset($_POST['set_file_perms'])) ? 1 : 0;
188
+ $_POST['set_dir_perms'] = (isset($_POST['set_dir_perms'])) ? 1 : 0;
189
+ $_POST['file_perms_value'] = (isset($_POST['file_perms_value'])) ? DUPX_U::sanitize_text_field($_POST['file_perms_value']) : 0755;
190
+ $_POST['dir_perms_value'] = (isset($_POST['dir_perms_value'])) ? DUPX_U::sanitize_text_field($_POST['dir_perms_value']) : 0644;
191
+ $_POST['zip_filetime'] = (isset($_POST['zip_filetime'])) ? $_POST['zip_filetime'] : 'current';
192
+ $_POST['config_mode'] = (isset($_POST['config_mode'])) ? $_POST['config_mode'] : 'NEW';
193
+ $_POST[self::INPUT_NAME_ARCHIVE_ACTION] = (isset($_POST[self::INPUT_NAME_ARCHIVE_ACTION])) ? $_POST[self::INPUT_NAME_ARCHIVE_ACTION] : self::ACTION_DO_NOTHING;
194
+ $_POST['archive_engine'] = (isset($_POST['archive_engine'])) ? $_POST['archive_engine'] : 'manual';
195
+ $_POST['exe_safe_mode'] = (isset($_POST['exe_safe_mode'])) ? $_POST['exe_safe_mode'] : 0;
196
+
197
+ //LOGGING
198
+ $POST_LOG = $_POST;
199
+ unset($POST_LOG['dbpass']);
200
+ ksort($POST_LOG);
201
+
202
+ //ACTION VARS
203
+ $ajax1_start = DUPX_U::getMicrotime();
204
+ $root_path = $GLOBALS['DUPX_ROOT'];
205
+ $wpconfig_ark_path = ($GLOBALS['DUPX_AC']->installSiteOverwriteOn) ?
206
+ "{$root_path}/dup-wp-config-arc__{$GLOBALS['DUPX_AC']->package_hash}.txt" : "{$root_path}/wp-config.php";
207
+
208
+ $archive_path = $GLOBALS['FW_PACKAGE_PATH'];
209
+ $dataResult = array();
210
+ $dataResult['pass'] = 0;
211
+
212
+ /** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
213
+ cause errors in the JSON data Here we hide the status so warning level is reset at it at the end */
214
+ $ajax1_error_level = error_reporting();
215
+ error_reporting(E_ERROR);
216
+
217
+ $nManager = DUPX_NOTICE_MANAGER::getInstance();
218
+
219
+ //===============================
220
+ //ARCHIVE ERROR MESSAGES
221
+ //===============================
222
+ ($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG);
223
+
224
+ if (!$GLOBALS['DUPX_AC']->exportOnlyDB) {
225
+
226
+ $post_archive_engine = DUPX_U::sanitize_text_field($_POST['archive_engine']);
227
+
228
+ if ($post_archive_engine == 'manual') {
229
+ if (!file_exists($wpconfig_ark_path) && !file_exists("database.sql")) {
230
+ DUPX_Log::error(ERR_ZIPMANUAL);
231
+ }
232
+ } else {
233
+ if (!is_readable("{$archive_path}")) {
234
+ DUPX_Log::error("archive path:{$archive_path}<br/>".ERR_ZIPNOTFOUND);
235
+ }
236
+ }
237
+
238
+ //ERR_ZIPMANUAL
239
+ if (('ziparchive' == $post_archive_engine || 'shellexec_unzip' == $post_archive_engine) && !$GLOBALS['DUPX_AC']->installSiteOverwriteOn) {
240
+ //ERR_CONFIG_FOUND
241
+ $outer_root_path = dirname($root_path);
242
+
243
+ if ((file_exists($wpconfig_ark_path) || (@file_exists("{$outer_root_path}/wp-config.php") && !@file_exists("{$outer_root_path}/wp-settings.php"))) && @file_exists("{$root_path}/wp-admin") && @file_exists("{$root_path}/wp-includes")) {
244
+ DUPX_Log::error(ERR_CONFIG_FOUND);
245
+ }
246
+ }
247
+ }
248
+
249
+ DUPX_Log::info("********************************************************************************");
250
+ DUPX_Log::info('* DUPLICATOR-LITE: Install-Log');
251
+ DUPX_Log::info('* STEP-1 START @ '.@date('h:i:s'));
252
+ DUPX_Log::info("* VERSION: {$GLOBALS['DUPX_AC']->version_dup}");
253
+ DUPX_Log::info('* NOTICE: Do NOT post to public sites or forums!!');
254
+ DUPX_Log::info("********************************************************************************");
255
+
256
+ $colSize = 60;
257
+ $labelPadSize = 20;
258
+ $os = defined('PHP_OS') ? PHP_OS : 'unknown';
259
+ $log = str_pad(str_pad('PACKAGE INFO', $labelPadSize, '_', STR_PAD_RIGHT).' '.'CURRENT SERVER', $colSize, ' ', STR_PAD_RIGHT).'|'.'ORIGINAL SERVER'."\n".
260
+ str_pad(str_pad('PHP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_php, $colSize, ' ', STR_PAD_RIGHT).'|'.phpversion()."\n".
261
+ str_pad(str_pad('OS', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_os, $colSize, ' ', STR_PAD_RIGHT).'|'.$os."\n".
262
+ str_pad('CREATED', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->created."\n".
263
+ str_pad('WP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_wp."\n".
264
+ str_pad('DUP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_dup."\n".
265
+ str_pad('DB', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_db."\n".
266
+ str_pad('DB TABLES', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesFinalCount."\n".
267
+ str_pad('DB ROWS', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesRowCount."\n".
268
+ str_pad('DB FILE SIZE', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesSizeOnDisk."\n".
269
+ "********************************************************************************";
270
+ DUPX_Log::info($log);
271
+ DUPX_Log::info("SERVER INFO");
272
+ DUPX_Log::info(str_pad('PHP', $labelPadSize, '_', STR_PAD_RIGHT).': '.phpversion().' | SAPI: '.php_sapi_name());
273
+ DUPX_Log::info(str_pad('PHP MEMORY', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['PHP_MEMORY_LIMIT'].' | SUHOSIN: '.$GLOBALS['PHP_SUHOSIN_ON']);
274
+ DUPX_Log::info(str_pad('SERVER', $labelPadSize, '_', STR_PAD_RIGHT).': '.$_SERVER['SERVER_SOFTWARE']);
275
+ DUPX_Log::info(str_pad('DOC ROOT', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($root_path));
276
+ DUPX_Log::info(str_pad('DOC ROOT 755', $labelPadSize, '_', STR_PAD_RIGHT).': '.var_export($GLOBALS['CHOWN_ROOT_PATH'], true));
277
+ DUPX_Log::info(str_pad('LOG FILE 644', $labelPadSize, '_', STR_PAD_RIGHT).': '.var_export($GLOBALS['CHOWN_LOG_PATH'], true));
278
+ DUPX_Log::info(str_pad('REQUEST URL', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($GLOBALS['URL_PATH']));
279
+
280
+ DUPX_Log::info("********************************************************************************");
281
+ DUPX_Log::info("USER INPUTS");
282
+ DUPX_Log::info(str_pad('ARCHIVE ACTION', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST[self::INPUT_NAME_ARCHIVE_ACTION]));
283
+ DUPX_Log::info(str_pad('ARCHIVE ENGINE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['archive_engine']));
284
+ DUPX_Log::info(str_pad('SET DIR PERMS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['set_dir_perms']));
285
+ DUPX_Log::info(str_pad('DIR PERMS VALUE', $labelPadSize, '_', STR_PAD_RIGHT).': '.decoct($_POST['dir_perms_value']));
286
+ DUPX_Log::info(str_pad('SET FILE PERMS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['set_file_perms']));
287
+ DUPX_Log::info(str_pad('FILE PERMS VALUE', $labelPadSize, '_', STR_PAD_RIGHT).': '.decoct($_POST['file_perms_value']));
288
+ DUPX_Log::info(str_pad('SAFE MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['exe_safe_mode']));
289
+ DUPX_Log::info(str_pad('LOGGING', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['logging']));
290
+ DUPX_Log::info(str_pad('CONFIG MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['config_mode']));
291
+ DUPX_Log::info(str_pad('FILE TIME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['zip_filetime']));
292
+ DUPX_Log::info("********************************************************************************\n");
293
+
294
+ $log = "--------------------------------------\n";
295
+ $log .= "POST DATA\n";
296
+ $log .= "--------------------------------------\n";
297
+ $log .= print_r($POST_LOG, true);
298
+ DUPX_Log::info($log, DUPX_Log::LV_DEBUG);
299
+
300
+ $log = "\n--------------------------------------\n";
301
+ $log .= "ARCHIVE SETUP\n";
302
+ $log .= "--------------------------------------\n";
303
+ $log .= str_pad('NAME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($GLOBALS['FW_PACKAGE_PATH'])."\n";
304
+ if (file_exists($GLOBALS['FW_PACKAGE_PATH'])) {
305
+ $log .= str_pad('SIZE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_U::readableByteSize(@filesize($GLOBALS['FW_PACKAGE_PATH']));
306
+ }
307
+ DUPX_Log::info($log."\n", DUPX_Log::LV_DEFAULT, true);
308
+
309
+ DUPX_Log::info('PRE-EXTRACT-CHECKS');
310
+ DUPX_ServerConfig::beforeExtractionSetup();
311
+
312
+ $this->beforeExtraction();
313
+
314
+ $target = $root_path;
315
+ DUPX_U::maintenanceMode(true);
316
+
317
+ $post_archive_engine = DUPX_U::sanitize_text_field($_POST['archive_engine']);
318
+ switch ($post_archive_engine) {
319
+
320
+ //-----------------------
321
+ //MANUAL EXTRACTION
322
+ case 'manual':
323
+ DUPX_Log::info("\n** PACKAGE EXTRACTION IS IN MANUAL MODE ** \n");
324
+ break;
325
+
326
+ //-----------------------
327
+ //SHELL EXEC
328
+ case 'shellexec_unzip':
329
+ DUPX_Log::info("\n\nSTART ZIP FILE EXTRACTION SHELLEXEC >>> ");
330
+ $shell_exec_path = DUPX_Server::get_unzip_filepath();
331
+
332
+
333
+ $command = escapeshellcmd($shell_exec_path)." -o -qq ".escapeshellarg($archive_path)." -d ".escapeshellarg($target)." 2>&1";
334
+ if ($_POST['zip_filetime'] == 'original') {
335
+ DUPX_Log::info("\nShell Exec Current does not support orginal file timestamp please use ZipArchive");
336
+ }
337
+
338
+ DUPX_Log::info(">>> Starting Shell-Exec Unzip:\nCommand: {$command}", DUPX_Log::LV_DEBUG);
339
+ $stderr = shell_exec($command);
340
+ if ($stderr != '') {
341
+ $zip_err_msg = ERR_SHELLEXEC_ZIPOPEN.": $stderr";
342
+ $zip_err_msg .= "<br/><br/><b>To resolve error see <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q' target='_blank'>https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q</a></b>";
343
+ DUPX_Log::error($zip_err_msg);
344
+ }
345
+ DUPX_Log::info("<<< Shell-Exec Unzip Complete.");
346
+
347
+ break;
348
+
349
+ //-----------------------
350
+ //ZIP-ARCHIVE
351
+ case 'ziparchive':
352
+ DUPX_Log::info("\n\nSTART ZIP FILE EXTRACTION STANDARD >>> ");
353
+
354
+ if (!class_exists('ZipArchive')) {
355
+ DUPX_Log::info("ERROR: Stopping install process. Trying to extract without ZipArchive module installed. Please use the 'Manual Archive Extraction' mode to extract zip file.");
356
+ DUPX_Log::error(ERR_ZIPARCHIVE);
357
+ }
358
+
359
+ if (($dupInstallerFolder = DUPX_U::findDupInstallerFolder($archive_path)) === false) {
360
+ DUPX_Log::info("findDupInstallerFolder error; set no subfolder");
361
+ // if not found set not subfolder
362
+ $dupInstallerFolder = '';
363
+ }
364
+ if (!empty($dupInstallerFolder)) {
365
+ DUPX_Log::info("ARCHIVE dup-installer SUBFOLDER:\"".$dupInstallerFolder."\"");
366
+ } else {
367
+ DUPX_Log::info("ARCHIVE dup-installer SUBFOLDER:\"".$dupInstallerFolder."\"", 2);
368
+ }
369
+
370
+ $dupInstallerZipPath = $dupInstallerFolder.'/dup-installer';
371
+
372
+ $zip = new ZipArchive();
373
+
374
+ if ($zip->open($archive_path) === TRUE) {
375
+ $extract_filenames = array();
376
+ DUPX_Handler::setMode(DUPX_Handler::MODE_VAR, false, false);
377
+
378
+ for ($i = 0; $i < $zip->numFiles; $i++) {
379
+ $extract_filename = $zip->getNameIndex($i);
380
+
381
+ // skip dup-installer folder. Alrady extracted in bootstrap
382
+ if (
383
+ (strpos($extract_filename, $dupInstallerZipPath) === 0) ||
384
+ (!empty($dupInstallerFolder) && strpos($extract_filename, $dupInstallerFolder) !== 0)
385
+ ) {
386
+ DUPX_Log::info("SKIPPING NOT IN ZIPATH:\"".DUPX_Log::varToString($extract_filename)."\"", DUPX_Log::LV_DETAILED);
387
+ continue;
388
+ }
389
+
390
+ try {
391
+ if (!$zip->extractTo($target, $extract_filename)) {
392
+ if (DupLiteSnapLibUtilWp::isWpCore($extract_filename, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
393
+ DUPX_Log::info("FILE CORE EXTRACION ERROR: ".$extract_filename);
394
+ $shortMsg = 'Can\'t extract wp core files';
395
+ $finalShortMsg = 'Wp core files not extracted';
396
+ $errLevel = DUPX_NOTICE_ITEM::CRITICAL;
397
+ $idManager = 'wp-extract-error-file-core';
398
+ } else {
399
+ DUPX_Log::info("FILE EXTRACION ERROR: ".$extract_filename);
400
+ $shortMsg = 'Can\'t extract files';
401
+ $finalShortMsg = 'Files not extracted';
402
+ $errLevel = DUPX_NOTICE_ITEM::SOFT_WARNING;
403
+ $idManager = 'wp-extract-error-file-no-core';
404
+ }
405
+ $longMsg = 'FILE: <b>'.htmlspecialchars($extract_filename).'</b><br>Message: '.htmlspecialchars(DUPX_Handler::getVarLogClean()).'<br><br>';
406
+
407
+ $nManager->addNextStepNotice(array(
408
+ 'shortMsg' => $shortMsg,
409
+ 'longMsg' => $longMsg,
410
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
411
+ 'level' => $errLevel
412
+ ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
413
+ $nManager->addFinalReportNotice(array(
414
+ 'shortMsg' => $finalShortMsg,
415
+ 'longMsg' => $longMsg,
416
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
417
+ 'level' => $errLevel,
418
+ 'sections' => array('files'),
419
+ ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
420
+ } else {
421
+ DUPX_Log::info("FILE EXTRACTION DONE: ".DUPX_Log::varToString($extract_filename), DUPX_Log::LV_HARD_DEBUG);
422
+ }
423
+ }
424
+ catch (Exception $ex) {
425
+ if (DupLiteSnapLibUtilWp::isWpCore($extract_filename, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
426
+ DUPX_Log::info("FILE CORE EXTRACION ERROR: {$extract_filename} | MSG:".$ex->getMessage());
427
+ $shortMsg = 'Can\'t extract wp core files';
428
+ $finalShortMsg = 'Wp core files not extracted';
429
+ $errLevel = DUPX_NOTICE_ITEM::CRITICAL;
430
+ $idManager = 'wp-extract-error-file-core';
431
+ } else {
432
+ DUPX_Log::info("FILE EXTRACION ERROR: {$extract_filename} | MSG:".$ex->getMessage());
433
+ $shortMsg = 'Can\'t extract files';
434
+ $finalShortMsg = 'Files not extracted';
435
+ $errLevel = DUPX_NOTICE_ITEM::SOFT_WARNING;
436
+ $idManager = 'wp-extract-error-file-no-core';
437
+ }
438
+ $longMsg = 'FILE: <b>'.htmlspecialchars($extract_filename).'</b><br>Message: '.htmlspecialchars($ex->getMessage()).'<br><br>';
439
+
440
+ $nManager->addNextStepNotice(array(
441
+ 'shortMsg' => $shortMsg,
442
+ 'longMsg' => $longMsg,
443
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
444
+ 'level' => $errLevel
445
+ ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
446
+ $nManager->addFinalReportNotice(array(
447
+ 'shortMsg' => $finalShortMsg,
448
+ 'longMsg' => $longMsg,
449
+ 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
450
+ 'level' => $errLevel,
451
+ 'sections' => array('files'),
452
+ ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
453
+ }
454
+ }
455
+
456
+ if (!empty($dupInstallerFolder)) {
457
+ DUPX_U::moveUpfromSubFolder($target.'/'.$dupInstallerFolder, true);
458
+ }
459
+
460
+ //Uncomment if needed
461
+ //if (DUPX_Log::isLevel(DUPX_Log::LV_DEBUG)) {
462
+ // $log = print_r($zip, true);
463
+ //}
464
+ //FILE-TIMESTAMP
465
+ if ($_POST['zip_filetime'] == 'original') {
466
+ $log .= "File timestamp set to Original\n";
467
+ for ($idx = 0; $s = $zip->statIndex($idx); $idx++) {
468
+ touch($target.DIRECTORY_SEPARATOR.$s['name'], $s['mtime']);
469
+ }
470
+ } else {
471
+ $now = @date("Y-m-d H:i:s");
472
+ $log .= "File timestamp set to Current: {$now}\n";
473
+ }
474
+
475
+ // set handler as default
476
+ DUPX_Handler::setMode();
477
+
478
+ $close_response = $zip->close();
479
+ $log .= "<<< ZipArchive Unzip Complete: ".var_export($close_response, true);
480
+ DUPX_Log::info($log);
481
+ } else {
482
+ $zip_err_msg = ERR_ZIPOPEN;
483
+ $zip_err_msg .= "<br/><br/><b>To resolve error see <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q' target='_blank'>https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-130-q</a></b>";
484
+ DUPX_Log::error($zip_err_msg);
485
+ }
486
+
487
+ break;
488
+
489
+ //-----------------------
490
+ //DUP-ARCHIVE
491
+ case 'duparchive':
492
+ DUPX_Log::info(">>> DupArchive Extraction Complete");
493
+
494
+ if (isset($_POST['extra_data'])) {
495
+ $extraData = $_POST['extra_data'];
496
+
497
+ $log = "\n--------------------------------------\n";
498
+ $log .= "DUPARCHIVE EXTRACTION STATUS\n";
499
+ $log .= "--------------------------------------\n";
500
+
501
+ $dawsStatus = json_decode($extraData);
502
+
503
+ if ($dawsStatus === null) {
504
+ $log .= "Can't decode the dawsStatus!\n";
505
+ $log .= print_r(extraData, true);
506
+ } else {
507
+ $criticalPresent = false;
508
+
509
+ if (count($dawsStatus->failures) > 0) {
510
+ $log .= "Archive extracted with errors.\n";
511
+
512
+ foreach ($dawsStatus->failures as $failure) {
513
+ if ($failure->isCritical) {
514
+ $log .= '(C) ';
515
+ $criticalPresent = true;
516
+ }
517
+ $log .= "{$failure->description}\n";
518
+ }
519
+ } else {
520
+ $log .= "Archive extracted with no errors.\n";
521
+ }
522
+
523
+ if ($criticalPresent) {
524
+ $log .= "\n\nCritical Errors present so stopping install.\n";
525
+ exit();
526
+ }
527
+ }
528
+
529
+ DUPX_Log::info($log);
530
+ } else {
531
+ DUPX_LOG::info("DAWS STATUS: UNKNOWN since extra_data wasn't in post!");
532
+ }
533
+
534
+ break;
535
+ }
536
+
537
+ $log = "--------------------------------------\n";
538
+ $log .= "POST-EXTRACT-CHECKS\n";
539
+ $log .= "--------------------------------------";
540
+ DUPX_Log::info($log);
541
+
542
+ //===============================
543
+ //FILE PERMISSIONS
544
+ if ($_POST['set_file_perms'] || $_POST['set_dir_perms']) {
545
+ $set_file_perms = $_POST['set_file_perms'];
546
+ $set_dir_perms = $_POST['set_dir_perms'];
547
+ $set_file_mtime = ($_POST['zip_filetime'] == 'current');
548
+ $file_perms_value = $_POST['file_perms_value'] ? $_POST['file_perms_value'] : 0755;
549
+ $dir_perms_value = $_POST['dir_perms_value'] ? $_POST['dir_perms_value'] : 0644;
550
+
551
+ DUPX_Log::info("PERMISSION UPDATES:");
552
+ DUPX_Log::info(" -DIRS: '{$dir_perms_value}'");
553
+ DUPX_Log::info(" -FILES: '{$file_perms_value}'");
554
+
555
+ $objects = new RecursiveIteratorIterator(
556
+ new IgnorantRecursiveDirectoryIterator($root_path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
557
+
558
+ foreach ($objects as $name => $object) {
559
+ if ($set_file_perms && is_file($name)) {
560
+ DUPX_Log::info("SET PERMISSION: ".DUPX_Log::varToString($name).'[MODE:'.$file_perms_value.']', DUPX_Log::LV_HARD_DEBUG);
561
+ if (!DupLiteSnapLibIOU::chmod($name, $file_perms_value)) {
562
+ DUPX_Log::info("Permissions setting on file '{$name}' failed");
563
+ }
564
+ } else if ($set_dir_perms && is_dir($name)) {
565
+ DUPX_Log::info("SET PERMISSION: ".DUPX_Log::varToString($name).'[MODE:'.$dir_perms_value.']', DUPX_Log::LV_HARD_DEBUG);
566
+ if (!DupLiteSnapLibIOU::chmod($name, $dir_perms_value)) {
567
+ DUPX_Log::info("Permissions setting on directory '{$name}' failed");
568
+ }
569
+ }
570
+ if ($set_file_mtime) {
571
+ @touch($name);
572
+ }
573
+ }
574
+ } else {
575
+ DUPX_Log::info("\nPERMISSION UPDATES: None Applied");
576
+ }
577
+
578
+ DUPX_ServerConfig::afterExtractionSetup();
579
+ $nManager->saveNotices();
580
+
581
+ //FINAL RESULTS
582
+ $ajax1_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $ajax1_start);
583
+ DUPX_Log::info("\nSTEP-1 COMPLETE @ ".@date('h:i:s')." - RUNTIME: {$ajax1_sum}");
584
+
585
+ $dataResult['pass'] = 1;
586
+ error_reporting($ajax1_error_level);
587
+ fclose($GLOBALS["LOG_FILE_HANDLE"]);
588
+ return $dataResult;
589
+ }
590
+ }
591
+
592
+ // Skips past paths it can't read
593
+ class IgnorantRecursiveDirectoryIterator extends RecursiveDirectoryIterator
594
+ {
595
+ #[\ReturnTypeWillChange]
596
+ public function getChildren()
597
+ {
598
+ try {
599
+ return new IgnorantRecursiveDirectoryIterator($this->getPathname(), RecursiveDirectoryIterator::SKIP_DOTS);
600
+ }
601
+ catch (UnexpectedValueException $e) {
602
+ return new RecursiveArrayIterator(array());
603
+ }
604
+ }
605
  }
installer/dup-installer/views/view.help.php CHANGED
@@ -4,7 +4,7 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
4
  //indicate if this help lives in lite or pro
5
  //$pro_version = true;
6
 
7
- $open_section = filter_input(INPUT_GET, 'open_section', FILTER_SANITIZE_STRING, array('options' => array('default' => '')));
8
 
9
  ?>
10
  <div class="hdr-main">
4
  //indicate if this help lives in lite or pro
5
  //$pro_version = true;
6
 
7
+ $open_section = filter_input(INPUT_GET, 'open_section', FILTER_UNSAFE_RAW, array('options' => array('default' => '')));
8
 
9
  ?>
10
  <div class="hdr-main">
installer/dup-installer/views/view.s3.php CHANGED
@@ -416,7 +416,10 @@ VIEW: STEP 3 - AJAX RESULT -->
416
  <div id="ajaxerr-area" style="display:none">
417
  <p>Please try again an issue has occurred.</p>
418
  <div style="padding: 0px 10px 10px 10px;">
419
- <div id="ajaxerr-data">An unknown issue has occurred with the update setup step. Please see the <?php DUPX_View_Funcs::installerLogLink(); ?> file for more details.</div>
 
 
 
420
  <div style="text-align:center; margin:10px auto 0px auto">
421
  <input type="button" onclick='DUPX.hideErrorResult2()' value="&laquo; Try Again" class="default-btn" /><br/><br/>
422
  <i style='font-size:11px'>See online help for more details at <a href='https://snapcreek.com' target='_blank'>snapcreek.com</a></i>
@@ -518,17 +521,28 @@ DUPX.runUpdate = function()
518
  DUPX.hideProgressBar();
519
  return false;
520
  }
521
- if (typeof(data) != 'undefined' && data.step3.pass == 1) {
522
- $("#ajax-url_new").val($("#url_new").val());
523
- $("#ajax-exe-safe-mode").val($("#exe-safe-mode").val());
524
- $("#ajax-json").val(escape(JSON.stringify(data)));
525
- <?php if (!DUPX_Log::isLevel(DUPX_Log::LV_DEBUG)) : ?>
526
- setTimeout(function(){$('#s3-result-form').submit();}, 1000);
527
- <?php endif; ?>
528
- //$('#progress-area').fadeOut(1500);
529
- } else {
530
- DUPX.hideProgressBar();
531
- }
 
 
 
 
 
 
 
 
 
 
 
532
  },
533
  error: function(xhr) {
534
  var status = "<b>Server Code:</b> " + xhr.status + "<br/>";
416
  <div id="ajaxerr-area" style="display:none">
417
  <p>Please try again an issue has occurred.</p>
418
  <div style="padding: 0px 10px 10px 10px;">
419
+ <div id="ajaxerr-data">
420
+ <b>Overview:</b><br/>
421
+ An issue has occurred in step 3. Please see the <?php DUPX_View_Funcs::installerLogLink(); ?> file for more details.
422
+ </div>
423
  <div style="text-align:center; margin:10px auto 0px auto">
424
  <input type="button" onclick='DUPX.hideErrorResult2()' value="&laquo; Try Again" class="default-btn" /><br/><br/>
425
  <i style='font-size:11px'>See online help for more details at <a href='https://snapcreek.com' target='_blank'>snapcreek.com</a></i>
521
  DUPX.hideProgressBar();
522
  return false;
523
  }
524
+
525
+ try {
526
+ if (typeof(data) != 'undefined' && data.step3.pass == 1) {
527
+ $("#ajax-url_new").val($("#url_new").val());
528
+ $("#ajax-exe-safe-mode").val($("#exe-safe-mode").val());
529
+ $("#ajax-json").val(escape(JSON.stringify(data)));
530
+ <?php if (!DUPX_Log::isLevel(DUPX_Log::LV_DEBUG)) : ?>
531
+ setTimeout(function(){$('#s3-result-form').submit();}, 1000);
532
+ <?php endif; ?>
533
+ } else {
534
+ if (typeof(data) != 'undefined' && data.step3.pass == -1) {
535
+ console.log(data);
536
+ let details = (data.step3.error_message.length > 0) ? data.step3.error_message : "No details found.";
537
+ $('#ajaxerr-data').append(`<br/><br/><b>Details:</b><br/> ${details}`);
538
+ }
539
+ DUPX.hideProgressBar();
540
+ }
541
+ } catch(err) {
542
+ console.log(err);
543
+ DUPX.hideProgressBar();
544
+ }
545
+
546
  },
547
  error: function(xhr) {
548
  var status = "<b>Server Code:</b> " + xhr.status + "<br/>";
installer/dup-installer/views/view.s4.php CHANGED
@@ -114,7 +114,7 @@ VIEW: STEP 4- INPUT -->
114
 
115
  <?php
116
  $nManager = DUPX_NOTICE_MANAGER::getInstance();
117
- if ($json_decode->step1->query_errs > 0) {
118
  $linkAttr = './'.DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);
119
  $longMsg = <<<LONGMSG
120
  Queries that error during the deploy step are logged to the <a href="{$linkAttr}" target="dup-installer">install-log.txt</a> file and
@@ -146,7 +146,7 @@ LONGMSG;
146
  ));
147
  }
148
 
149
- if ($json_decode->step3->errsql_sum > 0) {
150
  $longMsg = <<<LONGMSG
151
  Update errors that show here are queries that could not be performed because the database server being used has issues running it. Please validate the query, if
152
  it looks to be of concern please try to run the query manually. In many cases if your site performs well without any issues you can ignore the error.
@@ -162,7 +162,7 @@ LONGMSG;
162
  ));
163
  }
164
 
165
- if ($json_decode->step3->errkey_sum > 0) {
166
  $longMsg = <<<LONGMSG
167
  Notices should be ignored unless issues are found after you have tested an installed site. This notice indicates that a primary key is required to run the
168
  update engine. Below is a list of tables and the rows that were not updated. On some databases you can remove these notices by checking the box 'Enable Full Search'
@@ -186,7 +186,7 @@ LONGMSG;
186
  ));
187
  }
188
 
189
- if ($json_decode->step3->errser_sum > 0) {
190
  $longMsg = <<<LONGMSG
191
  Notices should be ignored unless issues are found after you have tested an installed site. The SQL below will show data that may have not been
192
  updated during the serialization process. Best practices for serialization notices is to just re-save the plugin/post/page in question.
@@ -326,9 +326,14 @@ LONGMSG;
326
  </li>
327
  <?php
328
  $wpconfigNotice = $nManager->getFinalReporNoticeById('wp-config-changes');
329
- $htaccessNorice = $nManager->getFinalReporNoticeById('htaccess-changes');
 
 
 
 
 
 
330
  ?>
331
- <li>Please validate <?php echo $wpconfigNotice->longMsg; ?> and <?php echo $htaccessNorice->longMsg; ?></li>
332
  <li>For additional help and questions visit the <a href='https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst4_step4_troubleshoot' target='_blank'>online FAQs</a></li>
333
  </ul>
334
  </div>
114
 
115
  <?php
116
  $nManager = DUPX_NOTICE_MANAGER::getInstance();
117
+ if ($json_decode && $json_decode->step1->query_errs > 0) {
118
  $linkAttr = './'.DUPX_U::esc_attr($GLOBALS["LOG_FILE_NAME"]);
119
  $longMsg = <<<LONGMSG
120
  Queries that error during the deploy step are logged to the <a href="{$linkAttr}" target="dup-installer">install-log.txt</a> file and
146
  ));
147
  }
148
 
149
+ if ($json_decode && $json_decode->step3->errsql_sum > 0) {
150
  $longMsg = <<<LONGMSG
151
  Update errors that show here are queries that could not be performed because the database server being used has issues running it. Please validate the query, if
152
  it looks to be of concern please try to run the query manually. In many cases if your site performs well without any issues you can ignore the error.
162
  ));
163
  }
164
 
165
+ if ($json_decode && $json_decode->step3->errkey_sum > 0) {
166
  $longMsg = <<<LONGMSG
167
  Notices should be ignored unless issues are found after you have tested an installed site. This notice indicates that a primary key is required to run the
168
  update engine. Below is a list of tables and the rows that were not updated. On some databases you can remove these notices by checking the box 'Enable Full Search'
186
  ));
187
  }
188
 
189
+ if ($json_decode && $json_decode->step3->errser_sum > 0) {
190
  $longMsg = <<<LONGMSG
191
  Notices should be ignored unless issues are found after you have tested an installed site. The SQL below will show data that may have not been
192
  updated during the serialization process. Best practices for serialization notices is to just re-save the plugin/post/page in question.
326
  </li>
327
  <?php
328
  $wpconfigNotice = $nManager->getFinalReporNoticeById('wp-config-changes');
329
+ $htaccessNotice = $nManager->getFinalReporNoticeById('htaccess-changes');
330
+ if ($wpconfigNotice) {
331
+ print("<li>Please validate ".$wpconfigNotice->longMsg."</li>");
332
+ }
333
+ if ($htaccessNotice) {
334
+ print("<li>Please validate ".$htaccessNotice->longMsg."</li>");
335
+ }
336
  ?>
 
337
  <li>For additional help and questions visit the <a href='https://snapcreek.com/duplicator/docs/faqs-tech/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_campaign=problem_resolution&utm_content=inst4_step4_troubleshoot' target='_blank'>online FAQs</a></li>
338
  </ul>
339
  </div>
lib/snaplib/class.snaplib.u.util.php CHANGED
@@ -175,7 +175,7 @@ if (!class_exists('DupLiteSnapLibUtil', false)) {
175
  */
176
  public static function sanitize($input)
177
  {
178
- return filter_var($input, FILTER_SANITIZE_STRING);
179
  }
180
 
181
  /**
175
  */
176
  public static function sanitize($input)
177
  {
178
+ return filter_var($input, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
179
  }
180
 
181
  /**
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: migration, backup, duplicate, move, migrate, restore, transfer, clone, aut
4
  Requires at least: 4.0
5
  Tested up to: 5.9
6
  Requires PHP: 5.3.8
7
- Stable tag: 1.4.4
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.
4
  Requires at least: 4.0
5
  Tested up to: 5.9
6
  Requires PHP: 5.3.8
7
+ Stable tag: 1.4.5
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.
views/packages/details/detail.php CHANGED
@@ -6,18 +6,13 @@ $ui_css_storage = (isset($view_state['dup-package-dtl-storage-panel']) && $view_
6
  $ui_css_archive = (isset($view_state['dup-package-dtl-archive-panel']) && $view_state['dup-package-dtl-archive-panel']) ? 'display:block' : 'display:none';
7
  $ui_css_install = (isset($view_state['dup-package-dtl-install-panel']) && $view_state['dup-package-dtl-install-panel']) ? 'display:block' : 'display:none';
8
 
9
- $sqlDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::SQL);
10
  $archiveDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::Archive);
11
  $logDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::Log);
12
- $scanDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::Scan);
13
  $installerDownloadInfo = $package->getInstallerDownloadInfo();
14
- $sqlDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($sqlDownloadInfo);
15
  $archiveDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($archiveDownloadInfo);
16
  $logDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($logDownloadInfo);
17
- $scanDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($scanDownloadInfo);
18
  $installerDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($installerDownloadInfo);
19
  $showLinksDialogJson = DupLiteSnapJsonU::json_encode_esc_attr(array(
20
- "sql" => $sqlDownloadInfo["url"],
21
  "archive" => $archiveDownloadInfo["url"],
22
  "log" => $logDownloadInfo["url"],
23
  ));
@@ -41,12 +36,10 @@ $dup_install_secure_pass = isset($package->Installer->OptsSecurePass) ? DUP_Util
41
  table.dup-dtl-data-tbl tr:first-child td {margin:0; padding-top:0 !important;}
42
  table.dup-dtl-data-tbl td {padding:0 5px 0 0; padding-top:10px !important;}
43
  table.dup-dtl-data-tbl td:first-child {font-weight: bold; width:130px}
44
- table.dup-sub-list td:first-child {white-space: nowrap; vertical-align: middle; width: 70px !important;}
45
- table.dup-sub-list td {white-space: nowrap; vertical-align:top; padding:0 !important; font-size:12px}
46
- div.dup-box-panel-hdr {font-size:14px; display:block; border-bottom: 1px dotted #efefef; margin:5px 0 5px 0; font-weight: bold; padding: 0 0 5px 0}
47
- tr.sub-item td:first-child {padding:0 0 0 40px}
48
- tr.sub-item td {font-size: 12px}
49
- tr.sub-item-disabled td {color:gray}
50
 
51
  /*STORAGE*/
52
  div.dup-store-pro {font-size:12px; font-style:italic;}
@@ -54,7 +47,10 @@ $dup_install_secure_pass = isset($package->Installer->OptsSecurePass) ? DUP_Util
54
  div.dup-store-pro a {text-decoration: underline}
55
 
56
  /*GENERAL*/
57
- div#dup-name-info, div#dup-version-info {display: none; font-size:11px; line-height:20px; margin:4px 0 0 0}
 
 
 
58
  div#dup-downloads-area {padding: 5px 0 5px 0; }
59
  div#dup-downloads-msg {margin-bottom:-5px; font-style: italic}
60
  div.sub-section {padding:7px 0 0 0}
@@ -90,9 +86,20 @@ GENERAL -->
90
  <td>
91
  <a href="javascript:void(0);" onclick="jQuery('#dup-name-info').toggle()"><?php echo esc_js($package->Name); ?></a>
92
  <div id="dup-name-info">
93
- <b><?php esc_html_e('ID', 'duplicator') ?>:</b> <?php echo absint($package->ID); ?><br/>
94
- <b><?php esc_html_e('Hash', 'duplicator') ?>:</b> <?php echo esc_html($package->Hash); ?><br/>
95
- <b><?php esc_html_e('Full Name', 'duplicator') ?>:</b> <?php echo esc_html($package->NameHash); ?><br/>
 
 
 
 
 
 
 
 
 
 
 
96
  </div>
97
  </td>
98
  </tr>
@@ -100,16 +107,32 @@ GENERAL -->
100
  <td><?php esc_html_e('Notes', 'duplicator') ?>:</td>
101
  <td><?php echo strlen($package->Notes) ? $package->Notes : esc_html__('- no notes -', 'duplicator') ?></td>
102
  </tr>
 
 
 
 
103
  <tr>
104
  <td><?php esc_html_e('Versions', 'duplicator') ?>:</td>
105
  <td>
106
  <a href="javascript:void(0);" onclick="jQuery('#dup-version-info').toggle()"><?php echo esc_html($package->Version); ?></a>
107
  <div id="dup-version-info">
108
- <b><?php esc_html_e('WordPress', 'duplicator') ?>:</b> <?php echo strlen($package->VersionWP) ? esc_html($package->VersionWP) : esc_html__('- unknown -', 'duplicator') ?><br/>
109
- <b><?php esc_html_e('PHP', 'duplicator') ?>:</b> <?php echo strlen($package->VersionPHP) ? esc_html($package->VersionPHP) : esc_html__('- unknown -', 'duplicator') ?><br/>
110
- <b><?php esc_html_e('Mysql', 'duplicator') ?>:</b>
111
- <?php echo strlen($package->VersionDB) ? esc_html($package->VersionDB) : esc_html__('- unknown -', 'duplicator') ?> |
112
- <?php echo strlen($package->Database->Comments) ? esc_html($package->Database->Comments) : esc_html__('- unknown -', 'duplicator') ?><br/>
 
 
 
 
 
 
 
 
 
 
 
 
113
  </div>
114
  </td>
115
  </tr>
@@ -130,14 +153,12 @@ GENERAL -->
130
  <td>
131
  <div id="dup-downloads-area">
132
  <?php if (!$err_found) :?>
133
-
134
- <button class="button" onclick="Duplicator.Pack.DownloadInstaller(<?php echo $installerDownloadInfoJson; ?>);return false;"><i class="fa fa-bolt fa-sm"></i> Installer</button>
135
- <button class="button" onclick="Duplicator.Pack.DownloadFile(<?php echo $archiveDownloadInfoJson; ?>);return false;"><i class="far fa-file-archive"></i> Archive - <?php echo esc_html($package->ZipSize); ?></button>
136
- <button class="button" onclick="Duplicator.Pack.DownloadFile(<?php echo $sqlDownloadInfoJson; ?>);return false;"><i class="fa fa-table fa-sm"></i> &nbsp; SQL - <?php echo esc_html(DUP_Util::byteSize($package->Database->Size)) ?></button>
137
- <button class="button" onclick="Duplicator.Pack.DownloadFile(<?php echo $logDownloadInfoJson; ?>);return false;"><i class="fa fa-table fa-sm"></i> &nbsp; <?php esc_html_e('Log', 'duplicator'); ?> </button>
138
- <button class="button" onclick="Duplicator.Pack.ShowLinksDialog(<?php echo $showLinksDialogJson;?>);" class="thickbox"><i class="fa fa-lock fa-xs"></i> &nbsp; <?php esc_html_e("Share", 'duplicator')?></button>
139
  <?php else: ?>
140
- <button class="button" onclick="Duplicator.Pack.DownloadFile(<?php echo $logDownloadInfoJson; ?>);return false;"><i class="fa fa-table fa-sm"></i> &nbsp; Log </button>
141
  <?php endif; ?>
142
  </div>
143
  <?php if (!$err_found) :?>
@@ -150,10 +171,15 @@ GENERAL -->
150
  <td><?php esc_html_e('Installer', 'duplicator') ?>: </td>
151
  <td><a href="#" onclick="Duplicator.Pack.DownloadInstaller(<?php echo $installerDownloadInfoJson; ?>);return false;" ><?php echo esc_html($package->Installer->File) ?></a></td>
152
  </tr>
153
- <tr>
154
- <td><?php esc_html_e('Database', 'duplicator') ?>: </td>
155
- <td><a href="<?php echo $sqlDownloadInfo["url"]; ?>" target="_blank"><?php echo esc_html($package->Database->File); ?></a></td>
156
- </tr>
 
 
 
 
 
157
  </table>
158
  <?php endif; ?>
159
  </td>
@@ -166,21 +192,21 @@ GENERAL -->
166
  DIALOG: QUICK PATH -->
167
  <?php add_thickbox(); ?>
168
  <div id="dup-dlg-quick-path" title="<?php esc_attr_e('Download Links', 'duplicator'); ?>" style="display:none">
169
- <p>
170
  <i class="fa fa-lock fa-xs"></i>
171
- <?php esc_html_e("The following links contain sensitive data. Please share with caution!", 'duplicator'); ?>
172
  </p>
173
 
174
- <div style="padding: 0px 15px 15px 15px;">
175
  <a href="javascript:void(0)" style="display:inline-block; text-align:right" onclick="Duplicator.Pack.GetLinksText()">[Select All]</a> <br/>
176
- <textarea id="dup-dlg-quick-path-data" style='border:1px solid silver; border-radius:3px; width:99%; height:180px; font-size:11px'></textarea><br/>
177
  <i style='font-size:11px'>
178
  <?php
179
  printf("%s <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-052-q' target='_blank'>%s</a>",
180
- esc_html__("An exact copy of the database SQL and installer file can both be found inside of the archive.zip/daf file. "
181
  . "Download and extract the archive file to get a copy of the installer which will be named 'installer-backup.php'. "
182
  . "For details on how to extract a archive.daf file please see: ", 'duplicator'),
183
- esc_html__("How do I work with DAF files and the DupArchive extraction tool?", 'duplicator'));
184
  ?>
185
  </i>
186
  </div>
@@ -190,7 +216,8 @@ DIALOG: QUICK PATH -->
190
  STORAGE -->
191
  <div class="dup-box">
192
  <div class="dup-box-title">
193
- <i class="fas fa-database fa-sm"></i> <?php esc_html_e('Storage', 'duplicator') ?>
 
194
  <div class="dup-box-arrow"></div>
195
  </div>
196
  <div class="dup-box-panel" id="dup-package-dtl-storage-panel" style="<?php echo esc_attr($ui_css_storage); ?>">
@@ -217,7 +244,10 @@ STORAGE -->
217
  ?>
218
  </i>
219
  </td>
220
- <td><i class="fas fa-server fa-fw"></i> <?php esc_html_e("Local", 'duplicator'); ?></td>
 
 
 
221
  <td><?php echo DUP_Settings::getSsdirPath(); ?></td>
222
  </tr>
223
  <tr>
@@ -249,9 +279,6 @@ STORAGE -->
249
 
250
  <!-- ===============================
251
  ARCHIVE -->
252
- <?php
253
- $css_db_filter_on = $package->Database->FilterOn == 1 ? '' : 'sub-item-disabled';
254
- ?>
255
  <div class="dup-box">
256
  <div class="dup-box-title">
257
  <i class="far fa-file-archive"></i> <?php esc_html_e('Archive', 'duplicator') ?>
@@ -260,6 +287,10 @@ ARCHIVE -->
260
  <div class="dup-box-panel" id="dup-package-dtl-archive-panel" style="<?php echo esc_attr($ui_css_archive); ?>">
261
 
262
  <!-- FILES -->
 
 
 
 
263
  <table class='dup-dtl-data-tbl'>
264
  <tr>
265
  <td><?php esc_html_e('Build Mode', 'duplicator') ?>: </td>
@@ -311,14 +342,21 @@ ARCHIVE -->
311
  </table><br/>
312
 
313
  <!-- DATABASE -->
314
- <div class="dup-box-panel-hdr"><i class="fa fa-table fa-sm"></i> <?php esc_html_e('DATABASE', 'duplicator'); ?></div>
 
 
 
315
  <table class='dup-dtl-data-tbl'>
 
 
 
 
316
  <tr>
317
  <td><?php esc_html_e('Type', 'duplicator') ?>: </td>
318
  <td><?php echo esc_html($package->Database->Type); ?></td>
319
  </tr>
320
  <tr>
321
- <td><?php esc_html_e('Build Mode', 'duplicator') ?>: </td>
322
  <td>
323
  <a href="?page=duplicator-settings&tab=package" target="_blank"><?php echo esc_html($dbbuild_mode); ?></a>
324
  <?php if ($mysqlcompat_on) : ?>
@@ -334,9 +372,10 @@ ARCHIVE -->
334
  <td><?php esc_html_e('Filters', 'duplicator') ?>: </td>
335
  <td><?php echo $package->Database->FilterOn == 1 ? 'On' : 'Off'; ?></td>
336
  </tr>
337
- <tr class="sub-item <?php echo esc_attr($css_db_filter_on); ?>">
338
- <td><?php esc_html_e('Tables', 'duplicator') ?>: </td>
339
  <td>
 
340
  <?php
341
  echo isset($package->Database->FilterTables) && strlen($package->Database->FilterTables)
342
  ? str_replace(',', "<br>\n", $package->Database->FilterTables)
@@ -419,15 +458,17 @@ jQuery(document).ready(function($)
419
  * @param pack The path to the package file */
420
  Duplicator.Pack.ShowLinksDialog = function(json)
421
  {
422
- var url = '#TB_inline?width=650&height=350&inlineId=dup-dlg-quick-path';
423
  tb_show("<?php esc_html_e('Package File Links', 'duplicator') ?>", url);
424
 
425
-
426
- var msg = <?php printf('"%s:\n" + json.sql + "\n\n%s:\n" + json.archive + "\n\n%s:\n" + json.log;',
427
- esc_html__("DATABASE", 'duplicator'),
428
- esc_html__("ARCHIVE", 'duplicator'),
429
- esc_html__("LOG", 'duplicator'));
430
- ?>
 
 
431
  $("#dup-dlg-quick-path-data").val(msg);
432
  return false;
433
  }
6
  $ui_css_archive = (isset($view_state['dup-package-dtl-archive-panel']) && $view_state['dup-package-dtl-archive-panel']) ? 'display:block' : 'display:none';
7
  $ui_css_install = (isset($view_state['dup-package-dtl-install-panel']) && $view_state['dup-package-dtl-install-panel']) ? 'display:block' : 'display:none';
8
 
 
9
  $archiveDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::Archive);
10
  $logDownloadInfo = $package->getPackageFileDownloadInfo(DUP_PackageFileType::Log);
 
11
  $installerDownloadInfo = $package->getInstallerDownloadInfo();
 
12
  $archiveDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($archiveDownloadInfo);
13
  $logDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($logDownloadInfo);
 
14
  $installerDownloadInfoJson = DupLiteSnapJsonU::json_encode_esc_attr($installerDownloadInfo);
15
  $showLinksDialogJson = DupLiteSnapJsonU::json_encode_esc_attr(array(
 
16
  "archive" => $archiveDownloadInfo["url"],
17
  "log" => $logDownloadInfo["url"],
18
  ));
36
  table.dup-dtl-data-tbl tr:first-child td {margin:0; padding-top:0 !important;}
37
  table.dup-dtl-data-tbl td {padding:0 5px 0 0; padding-top:10px !important;}
38
  table.dup-dtl-data-tbl td:first-child {font-weight: bold; width:130px}
39
+ table.dup-sub-list td:first-child {white-space: nowrap; vertical-align: middle; width:100px !important;}
40
+ table.dup-sub-list td {white-space: nowrap; vertical-align:top; padding:2px !important;}
41
+ div.dup-box-panel-hdr {font-size:14px; display:block; border-bottom: 1px solid #efefef; margin:5px 0 5px 0; font-weight: bold; padding: 0 0 5px 0}
42
+ td.sub-notes {font-weight: normal !important; font-style: italic; color:#999; padding-top:10px;}
 
 
43
 
44
  /*STORAGE*/
45
  div.dup-store-pro {font-size:12px; font-style:italic;}
47
  div.dup-store-pro a {text-decoration: underline}
48
 
49
  /*GENERAL*/
50
+ div#dup-name-info, div#dup-version-info {display: none; line-height:20px; margin:4px 0 0 0}
51
+ table.dup-sub-info td {padding: 1px !important}
52
+ table.dup-sub-info td:first-child {font-weight: bold; width:100px; padding-left:10px}
53
+
54
  div#dup-downloads-area {padding: 5px 0 5px 0; }
55
  div#dup-downloads-msg {margin-bottom:-5px; font-style: italic}
56
  div.sub-section {padding:7px 0 0 0}
86
  <td>
87
  <a href="javascript:void(0);" onclick="jQuery('#dup-name-info').toggle()"><?php echo esc_js($package->Name); ?></a>
88
  <div id="dup-name-info">
89
+ <table class="dup-sub-info">
90
+ <tr>
91
+ <td><?php esc_html_e('ID', 'duplicator') ?>:</td>
92
+ <td><?php echo absint($package->ID); ?></td>
93
+ </tr>
94
+ <tr>
95
+ <td><?php esc_html_e('Hash', 'duplicator') ?>:</td>
96
+ <td><?php echo esc_html($package->Hash); ?></td>
97
+ </tr>
98
+ <tr>
99
+ <td><?php esc_html_e('Full Name', 'duplicator') ?>:</td>
100
+ <td><?php echo esc_html($package->NameHash); ?></td>
101
+ </tr>
102
+ </table>
103
  </div>
104
  </td>
105
  </tr>
107
  <td><?php esc_html_e('Notes', 'duplicator') ?>:</td>
108
  <td><?php echo strlen($package->Notes) ? $package->Notes : esc_html__('- no notes -', 'duplicator') ?></td>
109
  </tr>
110
+ <tr>
111
+ <td><?php esc_html_e('Created', 'duplicator') ?>:</td>
112
+ <td><?php echo $package->Created; ?></td>
113
+ </tr>
114
  <tr>
115
  <td><?php esc_html_e('Versions', 'duplicator') ?>:</td>
116
  <td>
117
  <a href="javascript:void(0);" onclick="jQuery('#dup-version-info').toggle()"><?php echo esc_html($package->Version); ?></a>
118
  <div id="dup-version-info">
119
+ <table class="dup-sub-info">
120
+ <tr>
121
+ <td><?php esc_html_e('WordPress', 'duplicator') ?>:</td>
122
+ <td><?php echo strlen($package->VersionWP) ? esc_html($package->VersionWP) : esc_html__('- unknown -', 'duplicator') ?></td>
123
+ </tr>
124
+ <tr>
125
+ <td><?php esc_html_e('PHP', 'duplicator') ?>: </td>
126
+ <td><?php echo strlen($package->VersionPHP) ? esc_html($package->VersionPHP) : esc_html__('- unknown -', 'duplicator') ?></td>
127
+ </tr>
128
+ <tr>
129
+ <td><?php esc_html_e('Mysql', 'duplicator') ?>:</td>
130
+ <td>
131
+ <?php echo strlen($package->VersionDB) ? esc_html($package->VersionDB) : esc_html__('- unknown -', 'duplicator') ?> |
132
+ <?php echo strlen($package->Database->Comments) ? esc_html($package->Database->Comments) : esc_html__('- unknown -', 'duplicator') ?>
133
+ </td>
134
+ </tr>
135
+ </table>
136
  </div>
137
  </td>
138
  </tr>
153
  <td>
154
  <div id="dup-downloads-area">
155
  <?php if (!$err_found) :?>
156
+ <button class="button" onclick="Duplicator.Pack.DownloadInstaller(<?php echo $installerDownloadInfoJson; ?>);return false;"><i class="fa fa-bolt fa-sm"></i>&nbsp; Installer</button>
157
+ <button class="button" onclick="Duplicator.Pack.DownloadFile(<?php echo $archiveDownloadInfoJson; ?>);return false;"><i class="far fa-file-archive"></i>&nbsp; Archive - <?php echo esc_html($package->ZipSize); ?></button>
158
+ <!--button class="button" onclick="Duplicator.Pack.DownloadFile(<?php echo $logDownloadInfoJson; ?>);return false;"><i class="fas fa-file-contract fa-sm"></i>&nbsp; <?php esc_html_e('Log', 'duplicator'); ?> </button-->
159
+ <button class="button" onclick="Duplicator.Pack.ShowLinksDialog(<?php echo $showLinksDialogJson;?>);" class="thickbox"><i class="fas fa-share-alt"></i>&nbsp; <?php esc_html_e("Share File Links", 'duplicator')?></button>
 
 
160
  <?php else: ?>
161
+ <button class="button" onclick="Duplicator.Pack.DownloadFile(<?php echo $logDownloadInfoJson; ?>);return false;"><i class="fas fa-file-contract fa-sm"></i>&nbsp; Log </button>
162
  <?php endif; ?>
163
  </div>
164
  <?php if (!$err_found) :?>
171
  <td><?php esc_html_e('Installer', 'duplicator') ?>: </td>
172
  <td><a href="#" onclick="Duplicator.Pack.DownloadInstaller(<?php echo $installerDownloadInfoJson; ?>);return false;" ><?php echo esc_html($package->Installer->File) ?></a></td>
173
  </tr>
174
+ <tr>
175
+ <td><?php esc_html_e("Build Log", 'duplicator') ?>: </td>
176
+ <td><a href="<?php echo $logDownloadInfo["url"] ?>" target="file_results"><?php echo $logDownloadInfo["filename"]; ?></a></td>
177
+ </tr>
178
+ <tr>
179
+ <td class="sub-notes">
180
+ <i class="fas fa-download"></i> <?php _e("Click links to download", 'duplicator-pro') ?>
181
+ </td>
182
+ </tr>
183
  </table>
184
  <?php endif; ?>
185
  </td>
192
  DIALOG: QUICK PATH -->
193
  <?php add_thickbox(); ?>
194
  <div id="dup-dlg-quick-path" title="<?php esc_attr_e('Download Links', 'duplicator'); ?>" style="display:none">
195
+ <p style="color:maroon">
196
  <i class="fa fa-lock fa-xs"></i>
197
+ <?php esc_html_e("The following links contain sensitive data. Share with caution!", 'duplicator'); ?>
198
  </p>
199
 
200
+ <div style="padding: 0px 5px 5px 5px;">
201
  <a href="javascript:void(0)" style="display:inline-block; text-align:right" onclick="Duplicator.Pack.GetLinksText()">[Select All]</a> <br/>
202
+ <textarea id="dup-dlg-quick-path-data" style='border:1px solid silver; border-radius:2px; width:100%; height:175px; font-size:11px'></textarea><br/>
203
  <i style='font-size:11px'>
204
  <?php
205
  printf("%s <a href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-052-q' target='_blank'>%s</a>",
206
+ esc_html__("A copy of the database.sql and installer.php files can both be found inside of the archive.zip/daf file. "
207
  . "Download and extract the archive file to get a copy of the installer which will be named 'installer-backup.php'. "
208
  . "For details on how to extract a archive.daf file please see: ", 'duplicator'),
209
+ esc_html__("How to work with DAF files and the DupArchive extraction tool?", 'duplicator'));
210
  ?>
211
  </i>
212
  </div>
216
  STORAGE -->
217
  <div class="dup-box">
218
  <div class="dup-box-title">
219
+ <i class="fas fa-server fa-sm"></i>
220
+ <?php esc_html_e('Storage', 'duplicator') ?>
221
  <div class="dup-box-arrow"></div>
222
  </div>
223
  <div class="dup-box-panel" id="dup-package-dtl-storage-panel" style="<?php echo esc_attr($ui_css_storage); ?>">
244
  ?>
245
  </i>
246
  </td>
247
+ <td>
248
+ <i class="far fa-hdd fa-fw"></i>
249
+ <?php esc_html_e("Local", 'duplicator'); ?>
250
+ </td>
251
  <td><?php echo DUP_Settings::getSsdirPath(); ?></td>
252
  </tr>
253
  <tr>
279
 
280
  <!-- ===============================
281
  ARCHIVE -->
 
 
 
282
  <div class="dup-box">
283
  <div class="dup-box-title">
284
  <i class="far fa-file-archive"></i> <?php esc_html_e('Archive', 'duplicator') ?>
287
  <div class="dup-box-panel" id="dup-package-dtl-archive-panel" style="<?php echo esc_attr($ui_css_archive); ?>">
288
 
289
  <!-- FILES -->
290
+ <div class="dup-box-panel-hdr">
291
+ <i class="fas fa-folder-open fa-sm"></i>
292
+ <?php esc_html_e('FILES', 'duplicator'); ?>
293
+ </div>
294
  <table class='dup-dtl-data-tbl'>
295
  <tr>
296
  <td><?php esc_html_e('Build Mode', 'duplicator') ?>: </td>
342
  </table><br/>
343
 
344
  <!-- DATABASE -->
345
+ <div class="dup-box-panel-hdr">
346
+ <i class="fas fa-database fa-sm"></i>
347
+ <?php esc_html_e('DATABASE', 'duplicator'); ?>
348
+ </div>
349
  <table class='dup-dtl-data-tbl'>
350
+ <tr>
351
+ <td><?php esc_html_e('Name', 'duplicator') ?>: </td>
352
+ <td><?php echo esc_html($package->Database->info->name); ?></td>
353
+ </tr>
354
  <tr>
355
  <td><?php esc_html_e('Type', 'duplicator') ?>: </td>
356
  <td><?php echo esc_html($package->Database->Type); ?></td>
357
  </tr>
358
  <tr>
359
+ <td><?php esc_html_e('SQL Mode', 'duplicator') ?>: </td>
360
  <td>
361
  <a href="?page=duplicator-settings&tab=package" target="_blank"><?php echo esc_html($dbbuild_mode); ?></a>
362
  <?php if ($mysqlcompat_on) : ?>
372
  <td><?php esc_html_e('Filters', 'duplicator') ?>: </td>
373
  <td><?php echo $package->Database->FilterOn == 1 ? 'On' : 'Off'; ?></td>
374
  </tr>
375
+ <tr class="sub-section">
376
+ <td>&nbsp;</td>
377
  <td>
378
+ <b><?php esc_html_e('Tables', 'duplicator') ?>:</b><br/>
379
  <?php
380
  echo isset($package->Database->FilterTables) && strlen($package->Database->FilterTables)
381
  ? str_replace(',', "<br>\n", $package->Database->FilterTables)
458
  * @param pack The path to the package file */
459
  Duplicator.Pack.ShowLinksDialog = function(json)
460
  {
461
+ var url = '#TB_inline?width=650&height=325&inlineId=dup-dlg-quick-path';
462
  tb_show("<?php esc_html_e('Package File Links', 'duplicator') ?>", url);
463
 
464
+ var msg = <?php printf(
465
+ '"%s" + "\n\n%s:\n" + json.archive + "\n\n%s:\n" + json.log + "\n\n%s";',
466
+ '=========== SENSITIVE INFORMATION START ===========',
467
+ esc_html__("ARCHIVE", 'duplicator'),
468
+ esc_html__("LOG", 'duplicator'),
469
+ '=========== SENSITIVE INFORMATION END ==========='
470
+ );
471
+ ?>
472
  $("#dup-dlg-quick-path-data").val(msg);
473
  return false;
474
  }
views/packages/details/transfer.php CHANGED
@@ -21,8 +21,8 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
21
  <li><i class="fab fa-dropbox"></i> <?php esc_html_e('Dropbox', 'duplicator'); ?></li>
22
  <li><i class="fab fa-google-drive"></i> <?php esc_html_e('Google Drive', 'duplicator'); ?></li>
23
  <li><i class="fa fa-cloud fa-sm"></i> <?php esc_html_e('One Drive', 'duplicator'); ?></li>
24
- <li><i class="fa fa-upload"></i> <?php esc_html_e('FTP &amp; SFTP', 'duplicator'); ?></li>
25
- <li><i class="far fa-folder-open"></i> <?php esc_html_e('Custom Directory', 'duplicator'); ?></li>
26
  </ul>
27
  </div>
28
  <?php
21
  <li><i class="fab fa-dropbox"></i> <?php esc_html_e('Dropbox', 'duplicator'); ?></li>
22
  <li><i class="fab fa-google-drive"></i> <?php esc_html_e('Google Drive', 'duplicator'); ?></li>
23
  <li><i class="fa fa-cloud fa-sm"></i> <?php esc_html_e('One Drive', 'duplicator'); ?></li>
24
+ <li><i class="fas fa-network-wired"></i> <?php esc_html_e('FTP &amp; SFTP', 'duplicator'); ?></li>
25
+ <li><i class="fas fa-hdd"></i> <?php esc_html_e('Custom Directory', 'duplicator'); ?></li>
26
  </ul>
27
  </div>
28
  <?php
views/packages/main/packages.php CHANGED
@@ -120,10 +120,10 @@ if (DUP_Settings::Get('installer_name_mode') == DUP_Settings::INSTALLER_NAME_MOD
120
  <td>
121
  <div id='dup-list-alert-nodata'>
122
  <i class="fa fa-archive fa-sm"></i>
123
- <?php esc_html_e("No Packages Found.", 'duplicator'); ?><br/>
124
- <?php esc_html_e("Click the 'Create New' button to build a package.", 'duplicator'); ?><br/>
125
  <div class="dup-quick-start" <?php echo ($is_mu) ? 'style="display:none"' : ''; ?>>
126
- <?php esc_html_e("New to Duplicator?", 'duplicator'); ?><br/>
127
  <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=packages_empty1&utm_campaign=quick_start" target="_blank">
128
  <?php esc_html_e("Check out the 'Quick Start' guide!", 'duplicator'); ?>
129
  </a>
@@ -173,8 +173,8 @@ if (DUP_Settings::Get('installer_name_mode') == DUP_Settings::INSTALLER_NAME_MOD
173
  <td colspan="6">
174
  <div id='dup-list-alert-nodata'>
175
  <i class="fa fa-archive fa-sm"></i>
176
- <?php esc_html_e("No Packages Found.", 'duplicator'); ?><br/>
177
- <?php esc_html_e("Click the 'Create New' button to build a package.", 'duplicator'); ?><br/>
178
  <div class="dup-quick-start">
179
  <?php esc_html_e("New to Duplicator?", 'duplicator'); ?><br/>
180
  <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=packages_empty2&utm_campaign=quick_start" target="_blank">
@@ -367,10 +367,14 @@ DIALOG: HELP DIALOG -->
367
  <br/><br/>
368
 
369
  <b><?php esc_html_e("Other Resources:", 'duplicator') ?></b><hr size='1'/>
370
- <i class="fas fa-question-circle fa-sm"></i> <a href="https://snapcreek.com/ticket?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=help_btn_ticket&utm_campaign=duplicator_free" target="_blank"><?php esc_html_e("Need help with the plugin?", 'duplicator') ?></a> <br/>
371
- <i class="fa fa-lightbulb"></i> <a href="https://snapcreek.com/ticket/index.php?a=add&category=69" target="_blank"><?php esc_html_e("Have an idea for the plugin?", 'duplicator') ?></a> <br/>
 
 
 
372
  <?php if ($completeCount >= 3) : ?>
373
- <i class="fa fa-star"></i> <a href="https://wordpress.org/support/plugin/duplicator/reviews/?filter=5" target="vote-wp"><?php esc_html_e("Help review the plugin!", 'duplicator') ?></a>
 
374
  <?php endif; ?>
375
  </div>
376
 
120
  <td>
121
  <div id='dup-list-alert-nodata'>
122
  <i class="fa fa-archive fa-sm"></i>
123
+ <?php esc_html_e("No Packages Found", 'duplicator'); ?><br/>
124
+ <i><?php esc_html_e("Click 'Create New' To Build Package", 'duplicator'); ?></i><br/>
125
  <div class="dup-quick-start" <?php echo ($is_mu) ? 'style="display:none"' : ''; ?>>
126
+ <b><?php esc_html_e("New to Duplicator?", 'duplicator'); ?></b><br/>
127
  <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=packages_empty1&utm_campaign=quick_start" target="_blank">
128
  <?php esc_html_e("Check out the 'Quick Start' guide!", 'duplicator'); ?>
129
  </a>
173
  <td colspan="6">
174
  <div id='dup-list-alert-nodata'>
175
  <i class="fa fa-archive fa-sm"></i>
176
+ <?php esc_html_e("No Packages Found", 'duplicator'); ?><br/>
177
+ <i><?php esc_html_e("Click 'Create New' To Build Package", 'duplicator'); ?></i><br/>
178
  <div class="dup-quick-start">
179
  <?php esc_html_e("New to Duplicator?", 'duplicator'); ?><br/>
180
  <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=packages_empty2&utm_campaign=quick_start" target="_blank">
367
  <br/><br/>
368
 
369
  <b><?php esc_html_e("Other Resources:", 'duplicator') ?></b><hr size='1'/>
370
+ <i class="fas fa-question-circle fa-sm fa-fw"></i>
371
+ <a href="https://snapcreek.com/ticket?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=help_btn_ticket&utm_campaign=duplicator_free" target="_blank"><?php esc_html_e("Need help with the plugin?", 'duplicator') ?></a> <br/>
372
+
373
+ <i class="fa fa-lightbulb fa-fw"></i>
374
+ <a href="https://snapcreek.com/ticket/index.php?a=add&category=69" target="_blank"><?php esc_html_e("Have an idea for the plugin?", 'duplicator') ?></a> <br/>
375
  <?php if ($completeCount >= 3) : ?>
376
+ <i class="fa fa-star fa-fw"></i>
377
+ <a href="https://wordpress.org/support/plugin/duplicator/reviews/?filter=5" target="vote-wp"><?php esc_html_e("Help review the plugin!", 'duplicator') ?></a>
378
  <?php endif; ?>
379
  </div>
380
 
views/packages/main/s1.setup2.php CHANGED
@@ -7,17 +7,18 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
7
  form#dup-form-opts label {line-height:22px}
8
  form#dup-form-opts input[type=checkbox] {margin-top:3px}
9
  form#dup-form-opts textarea, input[type="text"] {width:100%}
10
- form#dup-form-opts textarea#filter-dirs {height:95px;}
11
- form#dup-form-opts textarea#filter-exts {height:27px}
12
  textarea#package-notes {height:75px;}
13
  div.dup-notes-add {float:right; margin:-4px 2px 4px 0;}
14
  div#dup-notes-area {display:none}
15
  input#package-name {padding:4px; height: 2em; font-size: 1.2em; line-height: 100%; width: 100%; margin: 0 0 3px;}
16
  tr.dup-store-path td {padding:14px}
17
  label.lbl-larger {font-size:1.2em}
 
 
18
 
19
- /*ARCHIVE SECTION*/
20
- form#dup-form-opts div.tabs-panel{max-height:800px; padding:10px; min-height:280px}
21
  form#dup-form-opts ul li.tabs{font-weight:bold}
22
  sup.archive-ext {font-style:italic;font-size:10px; cursor: pointer; vertical-align: baseline; position: relative; top: -0.8em; font-weight: normal}
23
  ul.category-tabs li {padding:4px 15px 4px 15px}
@@ -25,25 +26,33 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
25
  span#dup-archive-filter-file {color:#A62426; display:none}
26
  span#dup-archive-filter-db {color:#A62426; display:none}
27
  span#dup-archive-db-only {color:#A62426; display:none}
28
- div#dup-file-filter-items, div#dup-db-filter-items {padding:5px 0;}
 
29
  div#dup-db-filter-items {font-stretch:ultra-condensed; font-family:Calibri; }
30
- form#dup-form-opts textarea#filter-files {height:85px}
 
 
31
  div.dup-quick-links {font-size:11px; float:right; display:inline-block; margin-top:2px; font-style:italic}
32
- div.dup-tabs-opts-help {font-style:italic; font-size:11px; margin:10px 0 0 10px; color:#777}
33
 
34
- /* Tab: Database */
35
- table#dup-dbtables td {padding:1px 7px 1px 4px}
 
 
36
  label.core-table {color:#9A1E26;font-style:italic;font-weight:bold}
37
  i.core-table-info {color:#9A1E26;font-style:italic;}
38
  label.non-core-table {color:#000}
39
  label.non-core-table:hover, label.core-table:hover {text-decoration:line-through}
40
- table.dbmysql-compatibility td{padding:2px 20px 2px 2px}
 
41
  div.dup-store-pro {font-size:12px; font-style:italic;}
42
  div.dup-store-pro img {height:14px; width:14px; vertical-align:text-top}
43
  div.dup-store-pro a {text-decoration:underline}
44
  span.dup-pro-text {font-style:italic; font-size:12px; color:#555; font-style:italic }
45
  div#dup-exportdb-items-checked, div#dup-exportdb-items-off {min-height:275px; display:none}
46
  div#dup-exportdb-items-checked {padding: 5px; max-width:700px}
 
 
47
 
48
  /*INSTALLER SECTION*/
49
  div.dup-installer-header-1 {font-weight:bold; padding-bottom:2px; width:100%}
@@ -59,6 +68,7 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
59
  div#dup-pass-toggle {position: relative; margin:8px 0 0 0; width:243px}
60
  input#secure-pass {border-radius:4px 0 0 4px; width:217px; height: 23px; min-height: auto; margin:0; padding: 0 4px;}
61
  button.pass-toggle {height: 23px; width: 27px; position:absolute; top:0px; right:0px; border:1px solid silver; border-radius:0 4px 4px 0; cursor:pointer}
 
62
 
63
  /*TABS*/
64
  ul.add-menu-item-tabs li, ul.category-tabs li {padding:3px 30px 5px}
@@ -93,7 +103,8 @@ $storage_position = DUP_Settings::Get('storage_position');
93
  STORAGE -->
94
  <div class="dup-box">
95
  <div class="dup-box-title">
96
- <i class="fas fa-database fa-sm"></i>&nbsp;<?php esc_html_e("Storage", 'duplicator'); ?>
 
97
  <div class="dup-box-arrow"></div>
98
  </div>
99
  <div class="dup-box-panel" id="dup-pack-storage-panel" style="<?php echo esc_html($ui_css_storage); ?>">
@@ -132,7 +143,10 @@ STORAGE -->
132
  ?>
133
  </i>
134
  </td>
135
- <td><i class="fas fa-server fa-fw"></i> <?php esc_html_e("Local", 'duplicator'); ?></td>
 
 
 
136
  <td><?php echo DUP_Settings::getSsdirPath(); ?></td>
137
  </tr>
138
  <tr>
@@ -172,9 +186,15 @@ ARCHIVE -->
172
  echo "&nbsp;<sup class='archive-ext'>{$archive_build_mode}</sup>";
173
  ?> &nbsp;
174
  <span style="font-size:13px">
175
- <span id="dup-archive-filter-file" title="<?php esc_attr_e('File filter enabled', 'duplicator') ?>"><i class="far fa-copy fa-sm"></i> <i class="fa fa-filter fa-sm"></i> &nbsp;&nbsp;</span>
176
- <span id="dup-archive-filter-db" title="<?php esc_attr_e('Database filter enabled', 'duplicator') ?>"><i class="fa fa-table fa-sm"></i> <i class="fa fa-filter fa-sm"></i></span>
177
- <span id="dup-archive-db-only" title="<?php esc_attr_e('Archive Only the Database', 'duplicator') ?>"> <?php esc_html_e('Database Only', 'duplicator') ?> </span>
 
 
 
 
 
 
178
  </span>
179
  <div class="dup-box-arrow"></div>
180
  </div>
@@ -190,6 +210,10 @@ ARCHIVE -->
190
 
191
  <!-- TAB1:PACKAGE -->
192
  <div>
 
 
 
 
193
  <!-- FILTERS -->
194
  <?php
195
  $uploads = wp_upload_dir();
@@ -213,7 +237,7 @@ ARCHIVE -->
213
  <div id="dup-file-filter-items">
214
  <label for="filter-dirs" title="<?php esc_attr_e("Separate all filters by semicolon", 'duplicator'); ?>">
215
  <?php
216
- _e("Directories:", 'duplicator');
217
  echo sprintf("<sup title='%s'>({$filter_dir_count})</sup>", esc_html__("Number of directories filtered", 'duplicator'));
218
  ?>
219
  </label>
@@ -223,15 +247,19 @@ ARCHIVE -->
223
  <a href="javascript:void(0)" onclick="Duplicator.Pack.AddExcludePath('<?php echo esc_js(DUP_Util::safePath(WP_CONTENT_DIR)); ?>/cache')">[<?php esc_html_e("cache", 'duplicator') ?>]</a>
224
  <a href="javascript:void(0)" onclick="jQuery('#filter-dirs').val('')"><?php esc_html_e("(clear)", 'duplicator') ?></a>
225
  </div>
226
- <textarea name="filter-dirs" id="filter-dirs" placeholder="/full_path/exclude_path1;/full_path/exclude_path2;"><?php echo str_replace(";", ";\n", esc_textarea($Package->Archive->FilterDirs)) ?></textarea><br/>
 
227
 
228
- <label class="no-select" title="<?php esc_attr_e("Separate all filters by semicolon", 'duplicator'); ?>"><?php esc_html_e("File extensions", 'duplicator') ?>:</label>
 
 
229
  <div class='dup-quick-links'>
230
  <a href="javascript:void(0)" onclick="Duplicator.Pack.AddExcludeExts('avi;mov;mp4;mpeg;mpg;swf;wmv;aac;m3u;mp3;mpa;wav;wma')">[<?php esc_html_e("media", 'duplicator') ?>]</a>
231
  <a href="javascript:void(0)" onclick="Duplicator.Pack.AddExcludeExts('zip;rar;tar;gz;bz2;7z')">[<?php esc_html_e("archive", 'duplicator') ?>]</a>
232
  <a href="javascript:void(0)" onclick="jQuery('#filter-exts').val('')"><?php esc_html_e("(clear)", 'duplicator') ?></a>
233
  </div>
234
- <textarea name="filter-exts" id="filter-exts" placeholder="ext1;ext2;ext3;"><?php echo esc_textarea($Package->Archive->FilterExts); ?></textarea>
 
235
 
236
  <label class="no-select" title="<?php esc_attr_e("Separate all filters by semicolon", 'duplicator'); ?>">
237
  <?php
@@ -282,18 +310,16 @@ ARCHIVE -->
282
  </div>
283
 
284
  <!-- TAB2: DATABASE -->
285
- <div>
 
 
 
 
286
  <table>
287
- <tr>
288
- <td colspan="2" style="padding:0 0 10px 0">
289
- <?php esc_html_e("Build Mode", 'duplicator') ?>:&nbsp;
290
- <a href="?page=duplicator-settings&amp;tab=package" target="settings"><?php echo esc_html($dbbuild_mode); ?></a>
291
- </td>
292
- </tr>
293
  <tr>
294
  <td><input type="checkbox" id="dbfilter-on" name="dbfilter-on" onclick="Duplicator.Pack.ToggleDBFilters()" <?php echo ($Package->Database->FilterOn) ? "checked='checked'" :""; ?> /></td>
295
  <td>
296
- <label for="dbfilter-on"><?php esc_html_e("Enable Table Filters", 'duplicator') ?> &nbsp;</label>
297
  <i class="fas fa-question-circle fa-sm"
298
  data-tooltip-title="<?php esc_attr_e("Enable Table Filters:", 'duplicator'); ?>"
299
  data-tooltip="<?php esc_attr_e('Checked tables will not be added to the database script. Excluding certain tables can possibly cause your site or plugins to not work correctly after install!', 'duplicator'); ?>">
@@ -302,9 +328,11 @@ ARCHIVE -->
302
  </tr>
303
  </table>
304
  <div id="dup-db-filter-items">
305
- <a href="javascript:void(0)" id="dball" onclick="jQuery('#dup-dbtables .checkbox').prop('checked', true).trigger('click');">[ <?php esc_html_e('Include All', 'duplicator'); ?> ]</a> &nbsp;
306
- <a href="javascript:void(0)" id="dbnone" onclick="jQuery('#dup-dbtables .checkbox').prop('checked', false).trigger('click');">[ <?php esc_html_e('Exclude All', 'duplicator'); ?> ]</a>
307
- <div style="white-space:nowrap">
 
 
308
  <?php
309
  $tables = $wpdb->get_results("SHOW FULL TABLES FROM `" . DB_NAME . "` WHERE Table_Type = 'BASE TABLE' ", ARRAY_N);
310
  $num_rows = count($tables);
@@ -352,51 +380,64 @@ ARCHIVE -->
352
  _e("<i class='core-table-info'> Use caution when excluding tables! It is highly recommended to not exclude WordPress core tables*, unless you know the impact.</i>", 'duplicator');
353
  ?>
354
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
 
356
- <br/>
357
- <?php esc_html_e("Compatibility Mode", 'duplicator') ?> &nbsp;
358
- <i class="fas fa-question-circle fa-sm"
359
- data-tooltip-title="<?php esc_attr_e("Compatibility Mode:", 'duplicator'); ?>"
360
- data-tooltip="<?php esc_attr_e('This is an advanced database backwards compatibility feature that should ONLY be used if having problems installing packages.'
361
- . ' If the database server version is lower than the version where the package was built then these options may help generate a script that is more compliant'
362
- . ' with the older database server. It is recommended to try each option separately starting with mysql40.', 'duplicator'); ?>">
363
- </i> &nbsp;
364
- <small style="font-style:italic">
365
- <a href="https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_compatible" target="_blank">[<?php esc_html_e('details', 'duplicator'); ?>]</a>
366
- </small>
367
- <br/>
368
-
369
- <?php if ($dbbuild_mode == 'mysqldump') :?>
370
- <?php
371
- $modes = explode(',', $Package->Database->Compatible);
372
- $is_mysql40 = in_array('mysql40', $modes);
373
- $is_no_table = in_array('no_table_options', $modes);
374
- $is_no_key = in_array('no_key_options', $modes);
375
- $is_no_field = in_array('no_field_options', $modes);
376
- ?>
377
- <table class="dbmysql-compatibility">
378
- <tr>
379
- <td>
380
- <input type="checkbox" name="dbcompat[]" id="dbcompat-mysql40" value="mysql40" <?php echo $is_mysql40 ? 'checked="true"' :''; ?> >
381
- <label for="dbcompat-mysql40"><?php esc_html_e("mysql40", 'duplicator') ?></label>
382
- </td>
383
- <td>
384
- <input type="checkbox" name="dbcompat[]" id="dbcompat-no_table_options" value="no_table_options" <?php echo $is_no_table ? 'checked="true"' :''; ?>>
385
- <label for="dbcompat-no_table_options"><?php esc_html_e("no_table_options", 'duplicator') ?></label>
386
- </td>
387
- <td>
388
- <input type="checkbox" name="dbcompat[]" id="dbcompat-no_key_options" value="no_key_options" <?php echo $is_no_key ? 'checked="true"' :''; ?>>
389
- <label for="dbcompat-no_key_options"><?php esc_html_e("no_key_options", 'duplicator') ?></label>
390
- </td>
391
- <td>
392
- <input type="checkbox" name="dbcompat[]" id="dbcompat-no_field_options" value="no_field_options" <?php echo $is_no_field ? 'checked="true"' :''; ?>>
393
- <label for="dbcompat-no_field_options"><?php esc_html_e("no_field_options", 'duplicator') ?></label>
394
- </td>
395
- </tr>
396
- </table>
397
- <?php else :?>
398
- <i><?php esc_html_e("This option is only available with mysqldump mode.", 'duplicator'); ?></i>
399
- <?php endif; ?>
400
 
401
  </div>
402
  </div>
@@ -601,9 +642,11 @@ jQuery(document).ready(function ($)
601
  $filterItems.removeAttr('disabled').css({color:'#000'});
602
  $('#dup-dbtables input').removeAttr('readonly').css({color:'#000'});
603
  $('#dup-archive-filter-db').show();
 
604
  } else {
605
  $filterItems.attr('disabled', 'disabled').css({color:'#999'});
606
  $('#dup-dbtables input').attr('readonly', 'readonly').css({color:'#999'});
 
607
  $('#dup-archive-filter-db').hide();
608
  }
609
  };
7
  form#dup-form-opts label {line-height:22px}
8
  form#dup-form-opts input[type=checkbox] {margin-top:3px}
9
  form#dup-form-opts textarea, input[type="text"] {width:100%}
10
+
 
11
  textarea#package-notes {height:75px;}
12
  div.dup-notes-add {float:right; margin:-4px 2px 4px 0;}
13
  div#dup-notes-area {display:none}
14
  input#package-name {padding:4px; height: 2em; font-size: 1.2em; line-height: 100%; width: 100%; margin: 0 0 3px;}
15
  tr.dup-store-path td {padding:14px}
16
  label.lbl-larger {font-size:1.2em}
17
+ form#dup-form-opts ul li.tabs {font-size:16px}
18
+ div.tab-hdr-title {font-size: 16px; font-weight: bold; padding: 1px; margin:2px 0 5px 0; border-bottom:1px solid #dcdcde }
19
 
20
+ /*TAB-1: ARCHIVE SECTION*/
21
+ form#dup-form-opts div.tabs-panel{max-height:800px; padding:15px 20px 20px 20px; min-height:280px}
22
  form#dup-form-opts ul li.tabs{font-weight:bold}
23
  sup.archive-ext {font-style:italic;font-size:10px; cursor: pointer; vertical-align: baseline; position: relative; top: -0.8em; font-weight: normal}
24
  ul.category-tabs li {padding:4px 15px 4px 15px}
26
  span#dup-archive-filter-file {color:#A62426; display:none}
27
  span#dup-archive-filter-db {color:#A62426; display:none}
28
  span#dup-archive-db-only {color:#A62426; display:none}
29
+ div#dup-file-filter-items {padding:5px 0 0;}
30
+ div#dup-db-filter-items {padding:0; margin-top:-15px}
31
  div#dup-db-filter-items {font-stretch:ultra-condensed; font-family:Calibri; }
32
+ form#dup-form-opts textarea#filter-dirs {height:125px; background:#fafafa; padding:5px 10px 5px 10px;}
33
+ form#dup-form-opts textarea#filter-exts {height:30px; background:#fafafa; padding:3px 10px 1px 10px;}
34
+ form#dup-form-opts textarea#filter-files {height:125px; background:#fafafa; padding:5px 10px 5px 10px;}
35
  div.dup-quick-links {font-size:11px; float:right; display:inline-block; margin-top:2px; font-style:italic}
36
+ div.dup-tabs-opts-help {font-style:italic; font-size:11px; margin:10px 0 0 2px; color:#777;}
37
 
38
+ /* TAB-2: DATABASE */
39
+ table#dup-dbtables td {padding:0 20px 5px 10px;}
40
+ label.core-table,
41
+ label.non-core-table {padding:2px 0 2px 0; font-size:14px; display: inline-block}
42
  label.core-table {color:#9A1E26;font-style:italic;font-weight:bold}
43
  i.core-table-info {color:#9A1E26;font-style:italic;}
44
  label.non-core-table {color:#000}
45
  label.non-core-table:hover, label.core-table:hover {text-decoration:line-through}
46
+ table.dbmysql-compatibility {margin-top:-10px}
47
+ table.dbmysql-compatibility td{padding:0 20px 0 2px}
48
  div.dup-store-pro {font-size:12px; font-style:italic;}
49
  div.dup-store-pro img {height:14px; width:14px; vertical-align:text-top}
50
  div.dup-store-pro a {text-decoration:underline}
51
  span.dup-pro-text {font-style:italic; font-size:12px; color:#555; font-style:italic }
52
  div#dup-exportdb-items-checked, div#dup-exportdb-items-off {min-height:275px; display:none}
53
  div#dup-exportdb-items-checked {padding: 5px; max-width:700px}
54
+ div.dup-tbl-scroll {white-space:nowrap; height:350px; overflow-y: scroll; border:1px solid silver; padding:5px 10px; border-radius: 2px;
55
+ background:#fafafa; margin:3px 0 0 0; width:98%}
56
 
57
  /*INSTALLER SECTION*/
58
  div.dup-installer-header-1 {font-weight:bold; padding-bottom:2px; width:100%}
68
  div#dup-pass-toggle {position: relative; margin:8px 0 0 0; width:243px}
69
  input#secure-pass {border-radius:4px 0 0 4px; width:217px; height: 23px; min-height: auto; margin:0; padding: 0 4px;}
70
  button.pass-toggle {height: 23px; width: 27px; position:absolute; top:0px; right:0px; border:1px solid silver; border-radius:0 4px 4px 0; cursor:pointer}
71
+ div.dup-install-prefill-tab-pnl.tabs-panel {overflow:visible;}
72
 
73
  /*TABS*/
74
  ul.add-menu-item-tabs li, ul.category-tabs li {padding:3px 30px 5px}
103
  STORAGE -->
104
  <div class="dup-box">
105
  <div class="dup-box-title">
106
+ <i class="fas fa-server fa-fw fa-sm"></i>
107
+ <?php esc_html_e("Storage", 'duplicator'); ?>
108
  <div class="dup-box-arrow"></div>
109
  </div>
110
  <div class="dup-box-panel" id="dup-pack-storage-panel" style="<?php echo esc_html($ui_css_storage); ?>">
143
  ?>
144
  </i>
145
  </td>
146
+ <td>
147
+ <i class="far fa-hdd fa-fw"></i>
148
+ <?php esc_html_e("Local", 'duplicator'); ?>
149
+ </td>
150
  <td><?php echo DUP_Settings::getSsdirPath(); ?></td>
151
  </tr>
152
  <tr>
186
  echo "&nbsp;<sup class='archive-ext'>{$archive_build_mode}</sup>";
187
  ?> &nbsp;
188
  <span style="font-size:13px">
189
+ <span id="dup-archive-filter-file" title="<?php esc_attr_e('File filter enabled', 'duplicator') ?>">
190
+ <i class="far fa-copy fa-sm"></i> <i class="fa fa-filter fa-sm"></i> &nbsp;&nbsp;
191
+ </span>
192
+ <span id="dup-archive-filter-db" title="<?php esc_attr_e('Database filter enabled', 'duplicator') ?>">
193
+ <i class="fa fa-table fa-sm"></i> <i class="fa fa-filter fa-sm"></i>
194
+ </span>
195
+ <span id="dup-archive-db-only" title="<?php esc_attr_e('Archive Only the Database', 'duplicator') ?>">
196
+ <i class="fas fa-database fa-sm"></i> <?php esc_html_e('Database Only', 'duplicator') ?>
197
+ </span>
198
  </span>
199
  <div class="dup-box-arrow"></div>
200
  </div>
210
 
211
  <!-- TAB1:PACKAGE -->
212
  <div>
213
+ <div class="tab-hdr-title">
214
+ <?php esc_html_e('Filters', 'duplicator') ?>
215
+ </div>
216
+
217
  <!-- FILTERS -->
218
  <?php
219
  $uploads = wp_upload_dir();
237
  <div id="dup-file-filter-items">
238
  <label for="filter-dirs" title="<?php esc_attr_e("Separate all filters by semicolon", 'duplicator'); ?>">
239
  <?php
240
+ _e("Folders:", 'duplicator');
241
  echo sprintf("<sup title='%s'>({$filter_dir_count})</sup>", esc_html__("Number of directories filtered", 'duplicator'));
242
  ?>
243
  </label>
247
  <a href="javascript:void(0)" onclick="Duplicator.Pack.AddExcludePath('<?php echo esc_js(DUP_Util::safePath(WP_CONTENT_DIR)); ?>/cache')">[<?php esc_html_e("cache", 'duplicator') ?>]</a>
248
  <a href="javascript:void(0)" onclick="jQuery('#filter-dirs').val('')"><?php esc_html_e("(clear)", 'duplicator') ?></a>
249
  </div>
250
+ <textarea name="filter-dirs" id="filter-dirs" placeholder="/full_path/exclude_path1;/full_path/exclude_path2;"><?php echo str_replace(";", ";\n", esc_textarea($Package->Archive->FilterDirs)) ?></textarea>
251
+ <br/><br/>
252
 
253
+ <label class="no-select" title="<?php esc_attr_e("Separate all filters by semicolon", 'duplicator'); ?>">
254
+ <?php esc_html_e("File extensions", 'duplicator') ?>:
255
+ </label>
256
  <div class='dup-quick-links'>
257
  <a href="javascript:void(0)" onclick="Duplicator.Pack.AddExcludeExts('avi;mov;mp4;mpeg;mpg;swf;wmv;aac;m3u;mp3;mpa;wav;wma')">[<?php esc_html_e("media", 'duplicator') ?>]</a>
258
  <a href="javascript:void(0)" onclick="Duplicator.Pack.AddExcludeExts('zip;rar;tar;gz;bz2;7z')">[<?php esc_html_e("archive", 'duplicator') ?>]</a>
259
  <a href="javascript:void(0)" onclick="jQuery('#filter-exts').val('')"><?php esc_html_e("(clear)", 'duplicator') ?></a>
260
  </div>
261
+ <textarea name="filter-exts" id="filter-exts" placeholder="<?php esc_attr_e("example:", 'duplicator'); ?> mov;zip;mp4"><?php echo esc_textarea($Package->Archive->FilterExts); ?></textarea>
262
+ <br/><br/>
263
 
264
  <label class="no-select" title="<?php esc_attr_e("Separate all filters by semicolon", 'duplicator'); ?>">
265
  <?php
310
  </div>
311
 
312
  <!-- TAB2: DATABASE -->
313
+ <div>
314
+ <div class="tab-hdr-title">
315
+ <?php esc_html_e('Filters', 'duplicator') ?>
316
+ </div>
317
+
318
  <table>
 
 
 
 
 
 
319
  <tr>
320
  <td><input type="checkbox" id="dbfilter-on" name="dbfilter-on" onclick="Duplicator.Pack.ToggleDBFilters()" <?php echo ($Package->Database->FilterOn) ? "checked='checked'" :""; ?> /></td>
321
  <td>
322
+ <label for="dbfilter-on"><?php esc_html_e("Enable Table Filters", 'duplicator') ?>&nbsp;</label>
323
  <i class="fas fa-question-circle fa-sm"
324
  data-tooltip-title="<?php esc_attr_e("Enable Table Filters:", 'duplicator'); ?>"
325
  data-tooltip="<?php esc_attr_e('Checked tables will not be added to the database script. Excluding certain tables can possibly cause your site or plugins to not work correctly after install!', 'duplicator'); ?>">
328
  </tr>
329
  </table>
330
  <div id="dup-db-filter-items">
331
+ <div style="float:right; padding-right:10px;">
332
+ <a href="javascript:void(0)" id="dball" onclick="jQuery('#dup-dbtables .checkbox').prop('checked', true).trigger('click');"><?php esc_html_e('Include All', 'duplicator'); ?></a> &nbsp;
333
+ <a href="javascript:void(0)" id="dbnone" onclick="jQuery('#dup-dbtables .checkbox').prop('checked', false).trigger('click');"><?php esc_html_e('Exclude All', 'duplicator'); ?></a>
334
+ </div>
335
+ <div class="dup-tbl-scroll">
336
  <?php
337
  $tables = $wpdb->get_results("SHOW FULL TABLES FROM `" . DB_NAME . "` WHERE Table_Type = 'BASE TABLE' ", ARRAY_N);
338
  $num_rows = count($tables);
380
  _e("<i class='core-table-info'> Use caution when excluding tables! It is highly recommended to not exclude WordPress core tables*, unless you know the impact.</i>", 'duplicator');
381
  ?>
382
  </div>
383
+ <br/>
384
+
385
+ <div class="tab-hdr-title">
386
+ <?php esc_html_e('Configuration', 'duplicator') ?>
387
+ </div>
388
+
389
+ <div class="db-configuration" style="line-height: 30px">
390
+
391
+ <?php esc_html_e("SQL Mode", 'duplicator') ?>:&nbsp;
392
+ <a href="?page=duplicator-settings&amp;tab=package" target="settings"><?php echo esc_html($dbbuild_mode); ?></a>
393
+
394
+ <br/>
395
+ <?php esc_html_e("Compatibility Mode", 'duplicator') ?>:&nbsp;
396
+ <i class="fas fa-question-circle fa-sm"
397
+ data-tooltip-title="<?php esc_attr_e("Compatibility Mode:", 'duplicator'); ?>"
398
+ data-tooltip="<?php esc_attr_e('This is an advanced database backwards compatibility feature that should ONLY be used if having problems installing packages.'
399
+ . ' If the database server version is lower than the version where the package was built then these options may help generate a script that is more compliant'
400
+ . ' with the older database server. It is recommended to try each option separately starting with mysql40.', 'duplicator'); ?>">
401
+ </i>&nbsp;
402
+ <small style="font-style:italic">
403
+ <a href="https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_compatible" target="_blank">[<?php esc_html_e('details', 'duplicator'); ?>]</a>
404
+ </small>
405
+
406
+ <?php if ($dbbuild_mode == 'mysqldump') :?>
407
+ <?php
408
+ $modes = explode(',', $Package->Database->Compatible);
409
+ $is_mysql40 = in_array('mysql40', $modes);
410
+ $is_no_table = in_array('no_table_options', $modes);
411
+ $is_no_key = in_array('no_key_options', $modes);
412
+ $is_no_field = in_array('no_field_options', $modes);
413
+ ?>
414
+ <table class="dbmysql-compatibility">
415
+ <tr>
416
+ <td>
417
+ <input type="checkbox" name="dbcompat[]" id="dbcompat-mysql40" value="mysql40" <?php echo $is_mysql40 ? 'checked="true"' :''; ?> >
418
+ <label for="dbcompat-mysql40"><?php esc_html_e("mysql40", 'duplicator') ?></label>
419
+ </td>
420
+ <td>
421
+ <input type="checkbox" name="dbcompat[]" id="dbcompat-no_table_options" value="no_table_options" <?php echo $is_no_table ? 'checked="true"' :''; ?>>
422
+ <label for="dbcompat-no_table_options"><?php esc_html_e("no_table_options", 'duplicator') ?></label>
423
+ </td>
424
+ <td>
425
+ <input type="checkbox" name="dbcompat[]" id="dbcompat-no_key_options" value="no_key_options" <?php echo $is_no_key ? 'checked="true"' :''; ?>>
426
+ <label for="dbcompat-no_key_options"><?php esc_html_e("no_key_options", 'duplicator') ?></label>
427
+ </td>
428
+ <td>
429
+ <input type="checkbox" name="dbcompat[]" id="dbcompat-no_field_options" value="no_field_options" <?php echo $is_no_field ? 'checked="true"' :''; ?>>
430
+ <label for="dbcompat-no_field_options"><?php esc_html_e("no_field_options", 'duplicator') ?></label>
431
+ </td>
432
+ </tr>
433
+ </table>
434
+ <?php else :?>
435
+ <i><?php esc_html_e("This option is only available with mysqldump mode.", 'duplicator'); ?></i>
436
+ <?php endif; ?>
437
+
438
+ </div>
439
+
440
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
441
 
442
  </div>
443
  </div>
642
  $filterItems.removeAttr('disabled').css({color:'#000'});
643
  $('#dup-dbtables input').removeAttr('readonly').css({color:'#000'});
644
  $('#dup-archive-filter-db').show();
645
+ $('div.dup-tbl-scroll label').css({color:'#000'});
646
  } else {
647
  $filterItems.attr('disabled', 'disabled').css({color:'#999'});
648
  $('#dup-dbtables input').attr('readonly', 'readonly').css({color:'#999'});
649
+ $('div.dup-tbl-scroll label').css({color:'#999'});
650
  $('#dup-archive-filter-db').hide();
651
  }
652
  };
views/packages/main/s2.scan2.php CHANGED
@@ -4,7 +4,7 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
4
  <!-- ================================================================
5
  SETUP -->
6
  <div class="details-title">
7
- <i class="fa fa-hdd-o"></i> <i class="far fa-hdd fa-sm"></i> <?php esc_html_e("Setup", 'duplicator'); ?>
8
  <div class="dup-more-details">
9
  <a href="?page=duplicator-tools&tab=diagnostics" target="_blank" title="<?php esc_attr_e('Show Diagnostics', 'duplicator');?>"><i class="fa fa-microchip"></i></a>&nbsp;
10
  <a href="site-health.php" target="_blank" title="<?php esc_attr_e('Check Site Health', 'duplicator');?>"><i class="fas fa-file-medical-alt"></i></a>
@@ -137,7 +137,7 @@ WP SETTINGS -->
137
  $filter_text="";
138
  if($core_dir_notice) {
139
  echo '<small id="data-srv-wp-core-missing-dirs">';
140
- esc_html_e("The core WordPress paths below will <u>not</u> be included in the archive. These paths are required for WordPress to function!");
141
  echo "<br/>";
142
  foreach($core_dir_included as $core_dir) {
143
  echo '&nbsp; &nbsp; <b><i class="fa fa-exclamation-circle scan-warn"></i>&nbsp;'. $core_dir . '</b><br/>';
@@ -148,7 +148,7 @@ WP SETTINGS -->
148
 
149
  if($core_file_notice) {
150
  echo '<small id="data-srv-wp-core-missing-dirs">';
151
- esc_html_e("The core WordPress file below will <u>not</u> be included in the archive. This file is required for WordPress to function!");
152
  echo "<br/>";
153
  foreach($core_files_included as $core_file) {
154
  echo '&nbsp; &nbsp; <b><i class="fa fa-exclamation-circle scan-warn"></i>&nbsp;'. $core_file . '</b><br/>';
4
  <!-- ================================================================
5
  SETUP -->
6
  <div class="details-title">
7
+ <i class="fas fa-tasks"></i> <?php esc_html_e("Setup", 'duplicator'); ?>
8
  <div class="dup-more-details">
9
  <a href="?page=duplicator-tools&tab=diagnostics" target="_blank" title="<?php esc_attr_e('Show Diagnostics', 'duplicator');?>"><i class="fa fa-microchip"></i></a>&nbsp;
10
  <a href="site-health.php" target="_blank" title="<?php esc_attr_e('Check Site Health', 'duplicator');?>"><i class="fas fa-file-medical-alt"></i></a>
137
  $filter_text="";
138
  if($core_dir_notice) {
139
  echo '<small id="data-srv-wp-core-missing-dirs">';
140
+ esc_html_e("The core WordPress paths below will NOT be included in the archive. These paths are required for WordPress to function!", 'duplicator');
141
  echo "<br/>";
142
  foreach($core_dir_included as $core_dir) {
143
  echo '&nbsp; &nbsp; <b><i class="fa fa-exclamation-circle scan-warn"></i>&nbsp;'. $core_dir . '</b><br/>';
148
 
149
  if($core_file_notice) {
150
  echo '<small id="data-srv-wp-core-missing-dirs">';
151
+ esc_html_e("The core WordPress file below will NOT be included in the archive. This file is required for WordPress to function!", 'duplicator');
152
  echo "<br/>";
153
  foreach($core_files_included as $core_file) {
154
  echo '&nbsp; &nbsp; <b><i class="fa fa-exclamation-circle scan-warn"></i>&nbsp;'. $core_file . '</b><br/>';
views/packages/main/s2.scan3.php CHANGED
@@ -24,7 +24,7 @@ ARCHIVE -->
24
  </div>
25
 
26
  <div class="scan-header scan-item-first">
27
- <i class="far fa-copy fa-sm"></i>
28
  <?php esc_html_e("Files", 'duplicator'); ?>
29
 
30
  <div class="scan-header-details">
@@ -390,7 +390,7 @@ Restore only package -->
390
  DATABASE -->
391
  <div id="dup-scan-db">
392
  <div class="scan-header">
393
- <i class="fa fa-table fa-sm"></i>
394
  <?php esc_html_e("Database", 'duplicator'); ?>
395
  <div class="scan-header-details">
396
  <div class="dup-scan-filter-status">
@@ -616,7 +616,7 @@ DIALOG: Scan Results -->
616
  <br/><br/>
617
 
618
  <!-- DATABASE -->
619
- <h2><i class="fa fa-table fa-sm"></i> <?php esc_html_e('Database', 'duplicator');?></h2>
620
  <table id="db-area">
621
  <tr><td><b><?php esc_html_e('Name:', 'duplicator');?></b></td><td><?php echo DB_NAME; ?> </td></tr>
622
  <tr><td><b><?php esc_html_e('Host:', 'duplicator');?></b></td><td><?php echo DB_HOST; ?> </td></tr>
24
  </div>
25
 
26
  <div class="scan-header scan-item-first">
27
+ <i class="fas fa-folder-open"></i>
28
  <?php esc_html_e("Files", 'duplicator'); ?>
29
 
30
  <div class="scan-header-details">
390
  DATABASE -->
391
  <div id="dup-scan-db">
392
  <div class="scan-header">
393
+ <i class="fas fa-database fa-sm"></i>
394
  <?php esc_html_e("Database", 'duplicator'); ?>
395
  <div class="scan-header-details">
396
  <div class="dup-scan-filter-status">
616
  <br/><br/>
617
 
618
  <!-- DATABASE -->
619
+ <h2><i class="fas fa-database fa-sm"></i> <?php esc_html_e('Database', 'duplicator');?></h2>
620
  <table id="db-area">
621
  <tr><td><b><?php esc_html_e('Name:', 'duplicator');?></b></td><td><?php echo DB_NAME; ?> </td></tr>
622
  <tr><td><b><?php esc_html_e('Host:', 'duplicator');?></b></td><td><?php echo DB_HOST; ?> </td></tr>
views/packages/main/s3.build.php CHANGED
@@ -36,7 +36,8 @@ $rand_txt[0] = $atext0;
36
 
37
  <style>
38
  a#dup-create-new {margin-left:-5px}
39
- div#dup-progress-area {text-align:center; max-width:800px; min-height:200px; border:1px solid silver; border-radius:3px; margin:25px auto 10px auto; padding:0px; box-shadow:0 8px 6px -6px #999;}
 
40
  div.dup-progress-title {font-size:22px;padding:5px 0 20px 0; font-weight:bold}
41
  div#dup-progress-area div.inner {padding:10px; line-height:22px}
42
  div#dup-progress-area h2.title {background-color:#efefef; margin:0px}
@@ -86,7 +87,8 @@ $rand_txt[0] = $atext0;
86
  div.dup-box-panel {text-align:left}
87
  div.no-top {border-top:none}
88
  div.dup-box-panel b.opt-title {font-size:18px}
89
- div.dup-msg-error-area {overflow-y:scroll; padding:5px 15px 15px 15px; max-height:170px; width:95%; border:1px solid silver; border-radius:4px; line-height:22px}
 
90
  div#dup-logs {text-align:center; margin:auto; padding:5px; width:350px;}
91
  div#dup-logs a {display:inline-block;}
92
  span.sub-data {display:inline-block; padding-left:20px}
@@ -114,7 +116,7 @@ TOOL BAR:STEPS -->
114
  <a id="dup-packages-btn" href="?page=duplicator" class="button <?php echo ($active_package_present ? 'no-display' :''); ?>">
115
  <?php esc_html_e("Packages",'duplicator'); ?>
116
  </a>
117
- </span>
118
  <?php
119
  $package_url = admin_url('admin.php?page=duplicator&tab=new1');
120
  $package_nonce_url = wp_nonce_url($package_url, 'new1-package');
@@ -127,7 +129,7 @@ TOOL BAR:STEPS -->
127
  </a>
128
  </td>
129
  </tr>
130
- </table>
131
  <hr class="dup-toolbar-line">
132
 
133
 
@@ -185,11 +187,11 @@ TOOL BAR:STEPS -->
185
  </sup>
186
  </div>
187
  <div style="margin-top:20px; font-size:11px">
188
- <span id="dup-click-to-copy-installer-name"
189
  class="link-style no-decoration"
190
  data-dup-copy-text="<?php echo esc_attr(DUP_Installer::DEFAULT_INSTALLER_FILE_NAME_WITHOUT_HASH); ?>">
191
  <?php esc_html_e("[Copy Installer Name to Clipboard]", 'duplicator'); ?>
192
- <i class="far fa-copy"></i>
193
  </span><br/>
194
  <span id="dup-installer-name" data-installer-name="">
195
  <a href="javascript:void(0)" onclick="Duplicator.Pack.ShowInstallerName()">
@@ -217,7 +219,7 @@ TOOL BAR:STEPS -->
217
  }
218
  ?>
219
 
220
- <div class="dup-howto-exe">
221
  <div class="dup-howto-exe-title" onclick="Duplicator.Pack.ToggleHelpInstall(this)">
222
  <a href="javascript:void(0)">
223
  <i class="far fa-plus-square"></i>
@@ -254,7 +256,7 @@ TOOL BAR:STEPS -->
254
 
255
 
256
  <!-- IMPORT -->
257
- <i class="fas fa-download fa-sm fa-fw"></i>
258
  <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=package_built_install_help3_collapse&utm_campaign=duplicator_free#quick-045-q" target="_blank">
259
  <?php esc_html_e('Import Install Feature', 'duplicator'); ?>
260
  <sup><i class="fas fa-external-link-alt fa-xs"></i></sup>
@@ -276,18 +278,18 @@ TOOL BAR:STEPS -->
276
  ERROR MESSAGE -->
277
  <div id="dup-msg-error" style="display:none; color:#000">
278
  <div class="done-title"><i class="fa fa-chain-broken"></i> <?php esc_html_e('Host Build Interrupt', 'duplicator'); ?></div>
279
- <b><?php esc_html_e('This server cannot complete the build due to host setup constraints.', 'duplicator'); ?></b><br/>
280
- <i><?php esc_html_e("To get past this hosts limitation consider the options below by clicking each section.", 'duplicator'); ?></i>
281
- <br/><br/><br/>
282
 
283
  <!-- OPTION 1:Try DupArchive Engine -->
284
  <div class="dup-box">
285
  <div class="dup-box-title">
286
- <span style="width:20px; display:inline-block"><i class="far fa-check-circle"></i></span><?php esc_html_e('Option 1:Try DupArchive', 'duplicator'); ?>
 
287
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
288
  </div>
289
  <div class="dup-box-panel" id="dup-pack-build-try1" style="display:none">
290
- <!--<b class="opt-title"><?php esc_html_e('OPTION 1:', 'duplicator'); ?></b><br/>-->
291
 
292
  <?php esc_html_e('Enable the DupArchive format which is specific to Duplicator and designed to perform better on constrained budget hosts.', 'duplicator'); ?>
293
  <br/><br/>
@@ -295,7 +297,7 @@ TOOL BAR:STEPS -->
295
  <div style="font-style:italic">
296
  <?php esc_html_e('Note:DupArchive on Duplicator only supports sites up to 500MB. If your site is over 500MB then use a file filter on step 1 to get the size '
297
  . 'below 500MB or try the other options mentioned below. Alternatively, you may want to consider',
298
- 'duplicator'); ?>
299
  <a href="https://snapcreek.com/duplicator/?utm_source=duplicator_free&amp;utm_medium=wordpress_plugin&amp;utm_content=build_interrupt&amp;utm_campaign=duplicator_pro" target="_blank">
300
  Duplicator Pro,
301
  </a>
@@ -324,10 +326,11 @@ TOOL BAR:STEPS -->
324
  <!-- OPTION 2:TRY AGAIN -->
325
  <div class="dup-box no-top">
326
  <div class="dup-box-title">
327
- <span style="width:20px; display:inline-block"><i class="fa fa-filter fa-sm"></i></span><?php esc_html_e('Option 2:File Filters', 'duplicator'); ?>
 
328
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
329
  </div>
330
- <div class="dup-box-panel" id="dup-pack-build-try2" style="display:none">
331
  <?php
332
  esc_html_e('The first pass for reading files on some budget hosts maybe slow and have conflicts with strict timeout settings setup by the hosting provider. '
333
  . 'In these cases, it is recommended to retry the build by adding file filters to larger files/directories.', 'duplicator');
@@ -358,11 +361,11 @@ TOOL BAR:STEPS -->
358
  <!-- OPTION 3:Two-Part Install -->
359
  <div class="dup-box no-top">
360
  <div class="dup-box-title">
361
- <span style="width:20px; display:inline-block"><i class="fa fa-random"></i></span><?php esc_html_e('Option 3:Two-Part Install', 'duplicator'); ?>
 
362
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
363
  </div>
364
- <div class="dup-box-panel" id="dup-pack-build-try2" style="display:none">
365
-
366
 
367
  <?php esc_html_e('A two-part install minimizes server load and can avoid I/O and CPU issues encountered on some budget hosts. With this procedure you simply build a '
368
  .'\'database-only\' archive, manually move the website files, and then run the installer to complete the process.', 'duplicator');
@@ -395,7 +398,8 @@ TOOL BAR:STEPS -->
395
  <!-- OPTION 4:DIAGNOSE SERVER -->
396
  <div class="dup-box no-top">
397
  <div class="dup-box-title">
398
- <span style="width:20px; display:inline-block"><i class="fa fa-cog"></i></span><?php esc_html_e('Option 4:Configure Server', 'duplicator'); ?>
 
399
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
400
  </div>
401
  <div class="dup-box-panel" id="dup-pack-build-try3" style="display:none">
@@ -445,41 +449,51 @@ TOOL BAR:STEPS -->
445
  ?>"></i>
446
  </span>
447
  </div>
448
-
449
  <div id="dup-msg-error-response-status">
450
  <span class="label"><?php esc_html_e("Server Status:", 'duplicator'); ?></span>
451
- <span class="data"></span>
452
- </div>
453
- <div id="dup-msg-error-response-text">
454
- <span class="label"><?php esc_html_e("Error Message:", 'duplicator'); ?></span><br/>
455
- <span class="data"></span>
456
  </div>
457
  </div>
458
-
459
- <!-- LOGS -->
460
- <div id="dup-logs">
461
- <br/>
462
- <i class="fa fa-list-alt"></i>
463
- <a href='javascript:void(0)' style="color:#000" onclick='Duplicator.OpenLogWindow(true)'><?php esc_html_e('Read Package Log File',
464
- 'duplicator'); ?></a>
465
- <br/><br/>
466
- </div>
467
  </div>
468
  </div>
 
469
 
470
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
 
 
 
 
 
 
 
 
 
 
 
472
 
473
- <br/><br/><br/>
474
  </div>
475
 
 
476
  </div>
477
  </div>
478
  </form>
479
 
480
  <script>
481
- jQuery(document).ready(function ($)
482
- {
483
 
484
  Duplicator.Pack.DupArchiveFailureCount = 0;
485
  Duplicator.Pack.DupArchiveMaxRetries = 10;
@@ -490,8 +504,7 @@ jQuery(document).ready(function ($)
490
  /* ----------------------------------------
491
  * METHOD:Performs Ajax post to create a new package
492
  * Timeout (10000000 = 166 minutes) */
493
- Duplicator.Pack.CreateZip = function ()
494
- {
495
  var startTime;
496
  var data = {action:'duplicator_package_build', nonce:'<?php echo esc_js($zip_build_nonce); ?>'}
497
  var statusInterval = setInterval(Duplicator.Pack.GetActivePackageStatus, Duplicator.Pack.StatusFrequency);
@@ -518,26 +531,30 @@ jQuery(document).ready(function ($)
518
  $('#dup-progress-bar-area').hide();
519
  $('#dup-progress-area, #dup-msg-error').show(200);
520
  var status = xHr.status + ' -' + data.statusText;
521
- var response = (xHr.responseText != undefined && xHr.responseText.trim().length > 1) ? xHr.responseText.trim() :'No client side error - see package log file';
 
 
522
  $('#dup-msg-error-response-status span.data').html(status)
523
  $('#dup-msg-error-response-text span.data').html(response);
524
  console.log(xHr);
525
  return false;
526
  }
527
-
528
  if ((data != null) && (typeof (data) != 'undefined') && data.status == 1) {
529
  Duplicator.Pack.WireDownloadLinks(data);
530
  } else {
531
  var message = (typeof (data.error) != 'undefined' && data.error.length) ? data.error :'Error processing package';
532
  Duplicator.Pack.DupArchiveProcessingFailed(message);
533
  }
534
-
535
  },
536
  error:function (xHr) {
537
  $('#dup-progress-bar-area').hide();
538
  $('#dup-progress-area, #dup-msg-error').show(200);
539
  var status = xHr.status + ' -' + data.statusText;
540
- var response = (xHr.responseText != undefined && xHr.responseText.trim().length > 1) ? xHr.responseText.trim() :'No client side error - see package log file';
 
 
541
  $('#dup-msg-error-response-status span.data').html(status)
542
  $('#dup-msg-error-response-text span.data').html(response);
543
  console.log(xHr);
@@ -548,12 +565,11 @@ jQuery(document).ready(function ($)
548
 
549
  /* ----------------------------------------
550
  * METHOD:Performs Ajax post to create a new DupArchive-based package */
551
- Duplicator.Pack.CreateDupArchive = function ()
552
- {
553
  console.log('Duplicator.Pack.CreateDupArchive');
554
  var data = {action:'duplicator_duparchive_package_build', nonce:'<?php echo esc_js($duparchive_build_nonce); ?>'}
555
  var statusInterval = setInterval(Duplicator.Pack.GetActivePackageStatus, Duplicator.Pack.StatusFrequency);
556
-
557
  $.ajax({
558
  type:"POST",
559
  timeout:0, // no timeout
@@ -579,7 +595,6 @@ jQuery(document).ready(function ($)
579
  }
580
 
581
  console.log("CreateDupArchive:AJAX success. Data equals:");
582
-
583
  console.log(data);
584
  // DATA FIELDS
585
  // archive_offset, archive_size, failures, file_index, is_done, timestamp
@@ -603,7 +618,6 @@ jQuery(document).ready(function ($)
603
  // Don't stop for non-critical failures - just display those at the end TODO:put these in the log not popup
604
  console.log("CreateDupArchive:archive has completed");
605
  if (data.failures.length > 0) {
606
-
607
  console.log(data.failures);
608
  var errorMessage = "CreateDupArchive:Problems during package creation. These may be non-critical so continue with install.\n------\n";
609
  var len = data.failures.length;
@@ -623,7 +637,6 @@ jQuery(document).ready(function ($)
623
  setTimeout(Duplicator.Pack.CreateDupArchive, 500);
624
  }
625
  } else {
626
-
627
  console.log("CreateDupArchive:critical failures present");
628
  // If we get a critical failure it means it's something we can't recover from so no purpose in retrying, just fail immediately.
629
  var errorString = 'Error Processing Step 1<br/>';
@@ -658,8 +671,7 @@ jQuery(document).ready(function ($)
658
 
659
  /* ----------------------------------------
660
  * METHOD:Retrieves package status and updates UI with build percentage */
661
- Duplicator.Pack.GetActivePackageStatus = function ()
662
- {
663
  var data = {action:'DUP_CTRL_Package_getActivePackageStatus', nonce:'<?php echo wp_create_nonce('DUP_CTRL_Package_getActivePackageStatus'); ?>'}
664
  console.log('####Duplicator.Pack.GetActivePackageStatus');
665
 
@@ -694,8 +706,7 @@ jQuery(document).ready(function ($)
694
  return false;
695
  }
696
 
697
- Duplicator.Pack.PostTransferCleanup = function(statusInterval, startTime)
698
- {
699
  clearInterval(statusInterval);
700
  endTime = new Date().getTime();
701
  var millis = (endTime - startTime);
@@ -703,12 +714,9 @@ jQuery(document).ready(function ($)
703
  var seconds = ((millis % 60000) / 1000).toFixed(0);
704
  var status = minutes + ":" + (seconds < 10 ? '0' :'') + seconds;
705
  $('#dup-msg-error-response-time span.data').html(status);
706
- //$('#dup-create-area-nolink').hide();
707
- //$('#dup-create-area-link').show();
708
  };
709
 
710
- Duplicator.Pack.WireDownloadLinks = function(data)
711
- {
712
  var pack = data.package;
713
  var archive_json = {
714
  filename:pack.Archive.File,
@@ -727,7 +735,7 @@ jQuery(document).ready(function ($)
727
  $('#data-time').text(data.runtime || 'unable to read time');
728
  $('#dup-create-new').removeClass('no-display');
729
  $('#dup-packages-btn').removeClass('no-display');
730
-
731
  //Wire Up Downloads
732
  $('#dup-btn-installer').click(function() {
733
  Duplicator.Pack.DownloadInstaller(installer_json);
@@ -746,13 +754,12 @@ jQuery(document).ready(function ($)
746
  }, 700);
747
  return false;
748
  });
749
-
750
  $('#dup-click-to-copy-installer-name').data('dup-copy-text', data.instDownloadName);
751
  $('#dup-installer-name').data('data-installer-name', data.instDownloadName);
752
  };
753
 
754
- Duplicator.Pack.HandleDupArchiveInterruption = function (errorText)
755
- {
756
  Duplicator.Pack.DupArchiveFailureCount++;
757
 
758
  if (Duplicator.Pack.DupArchiveFailureCount <= Duplicator.Pack.DupArchiveMaxRetries) {
@@ -767,17 +774,16 @@ jQuery(document).ready(function ($)
767
  }
768
  };
769
 
770
- Duplicator.Pack.DupArchiveProcessingFailed = function (errorText)
771
- {
772
  $('#dup-progress-bar-area').hide();
773
  $('#dup-progress-area, #dup-msg-error').show(200);
774
  $('#dup-msg-error-response-text span.data').html(errorText);
 
775
  };
776
 
777
  Duplicator.Pack.GetFailureText = function (failures, onlyCritical)
778
  {
779
  var retVal = '';
780
-
781
  if ((failures !== null) && (typeof failures !== 'undefined')) {
782
  var len = failures.length;
783
 
@@ -818,7 +824,6 @@ jQuery(document).ready(function ($)
818
  var txt = $('#dup-installer-name').data('data-installer-name');
819
  $('#dup-installer-name').html(txt);
820
  $('#dup-installer-name-help-icon').show();
821
-
822
  };
823
 
824
  //Page Init:
@@ -830,4 +835,4 @@ jQuery(document).ready(function ($)
830
  Duplicator.Pack.CreateDupArchive();
831
  <?php endif; ?>
832
  });
833
- </script>
36
 
37
  <style>
38
  a#dup-create-new {margin-left:-5px}
39
+ div#dup-progress-area {text-align:center; max-width:800px; min-height:200px; border:1px solid silver; border-radius:3px; margin:25px auto 10px auto;
40
+ padding:0px; box-shadow:0 8px 6px -6px #999;}
41
  div.dup-progress-title {font-size:22px;padding:5px 0 20px 0; font-weight:bold}
42
  div#dup-progress-area div.inner {padding:10px; line-height:22px}
43
  div#dup-progress-area h2.title {background-color:#efefef; margin:0px}
87
  div.dup-box-panel {text-align:left}
88
  div.no-top {border-top:none}
89
  div.dup-box-panel b.opt-title {font-size:18px}
90
+ div.dup-msg-error-area {overflow-y:scroll; padding:5px 15px 15px 15px; height:100px; width:95%; border:1px solid #EEEEEE;
91
+ border-radius:2px; line-height:22px; text-align: left; background-color: #FFFFF3}
92
  div#dup-logs {text-align:center; margin:auto; padding:5px; width:350px;}
93
  div#dup-logs a {display:inline-block;}
94
  span.sub-data {display:inline-block; padding-left:20px}
116
  <a id="dup-packages-btn" href="?page=duplicator" class="button <?php echo ($active_package_present ? 'no-display' :''); ?>">
117
  <?php esc_html_e("Packages",'duplicator'); ?>
118
  </a>
119
+ </span>
120
  <?php
121
  $package_url = admin_url('admin.php?page=duplicator&tab=new1');
122
  $package_nonce_url = wp_nonce_url($package_url, 'new1-package');
129
  </a>
130
  </td>
131
  </tr>
132
+ </table>
133
  <hr class="dup-toolbar-line">
134
 
135
 
187
  </sup>
188
  </div>
189
  <div style="margin-top:20px; font-size:11px">
190
+ <span id="dup-click-to-copy-installer-name"
191
  class="link-style no-decoration"
192
  data-dup-copy-text="<?php echo esc_attr(DUP_Installer::DEFAULT_INSTALLER_FILE_NAME_WITHOUT_HASH); ?>">
193
  <?php esc_html_e("[Copy Installer Name to Clipboard]", 'duplicator'); ?>
194
+ <i class="far fa-copy"></i>
195
  </span><br/>
196
  <span id="dup-installer-name" data-installer-name="">
197
  <a href="javascript:void(0)" onclick="Duplicator.Pack.ShowInstallerName()">
219
  }
220
  ?>
221
 
222
+ <div class="dup-howto-exe">
223
  <div class="dup-howto-exe-title" onclick="Duplicator.Pack.ToggleHelpInstall(this)">
224
  <a href="javascript:void(0)">
225
  <i class="far fa-plus-square"></i>
256
 
257
 
258
  <!-- IMPORT -->
259
+ <i class="fas fa-arrow-alt-circle-down fa-sm fa-fw"></i>
260
  <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=package_built_install_help3_collapse&utm_campaign=duplicator_free#quick-045-q" target="_blank">
261
  <?php esc_html_e('Import Install Feature', 'duplicator'); ?>
262
  <sup><i class="fas fa-external-link-alt fa-xs"></i></sup>
278
  ERROR MESSAGE -->
279
  <div id="dup-msg-error" style="display:none; color:#000">
280
  <div class="done-title"><i class="fa fa-chain-broken"></i> <?php esc_html_e('Host Build Interrupt', 'duplicator'); ?></div>
281
+ <b><?php esc_html_e('This server cannot complete the build due to host setup constraints, see the error message for more details.', 'duplicator'); ?></b><br/>
282
+ <i><?php esc_html_e("If the error details are not specific consider the options below by clicking each section.", 'duplicator'); ?></i>
283
+ <br/><br/>
284
 
285
  <!-- OPTION 1:Try DupArchive Engine -->
286
  <div class="dup-box">
287
  <div class="dup-box-title">
288
+ <i class="far fa-check-circle fa-sm fa-fw"></i>
289
+ <?php esc_html_e('Option 1: DupArchive', 'duplicator'); ?>
290
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
291
  </div>
292
  <div class="dup-box-panel" id="dup-pack-build-try1" style="display:none">
 
293
 
294
  <?php esc_html_e('Enable the DupArchive format which is specific to Duplicator and designed to perform better on constrained budget hosts.', 'duplicator'); ?>
295
  <br/><br/>
297
  <div style="font-style:italic">
298
  <?php esc_html_e('Note:DupArchive on Duplicator only supports sites up to 500MB. If your site is over 500MB then use a file filter on step 1 to get the size '
299
  . 'below 500MB or try the other options mentioned below. Alternatively, you may want to consider',
300
+ 'duplicator'); ?>
301
  <a href="https://snapcreek.com/duplicator/?utm_source=duplicator_free&amp;utm_medium=wordpress_plugin&amp;utm_content=build_interrupt&amp;utm_campaign=duplicator_pro" target="_blank">
302
  Duplicator Pro,
303
  </a>
326
  <!-- OPTION 2:TRY AGAIN -->
327
  <div class="dup-box no-top">
328
  <div class="dup-box-title">
329
+ <i class="fas fa-filter fa-sm fa-fw"></i>
330
+ <?php esc_html_e('Option 2: File Filters', 'duplicator'); ?>
331
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
332
  </div>
333
+ <div class="dup-box-panel" style="display:none">
334
  <?php
335
  esc_html_e('The first pass for reading files on some budget hosts maybe slow and have conflicts with strict timeout settings setup by the hosting provider. '
336
  . 'In these cases, it is recommended to retry the build by adding file filters to larger files/directories.', 'duplicator');
361
  <!-- OPTION 3:Two-Part Install -->
362
  <div class="dup-box no-top">
363
  <div class="dup-box-title">
364
+ <i class="fas fa-random fa-sm fa-fw"></i>
365
+ <?php esc_html_e('Option 3: Two-Part Install', 'duplicator'); ?>
366
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
367
  </div>
368
+ <div class="dup-box-panel" style="display:none">
 
369
 
370
  <?php esc_html_e('A two-part install minimizes server load and can avoid I/O and CPU issues encountered on some budget hosts. With this procedure you simply build a '
371
  .'\'database-only\' archive, manually move the website files, and then run the installer to complete the process.', 'duplicator');
398
  <!-- OPTION 4:DIAGNOSE SERVER -->
399
  <div class="dup-box no-top">
400
  <div class="dup-box-title">
401
+ <i class="fas fa-cog fa-sm fa-fw"></i>
402
+ <?php esc_html_e('Option 4: Configure Server', 'duplicator'); ?>
403
  <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
404
  </div>
405
  <div class="dup-box-panel" id="dup-pack-build-try3" style="display:none">
449
  ?>"></i>
450
  </span>
451
  </div>
 
452
  <div id="dup-msg-error-response-status">
453
  <span class="label"><?php esc_html_e("Server Status:", 'duplicator'); ?></span>
454
+ <span class="data"><?php esc_html_e("unavailable", 'duplicator'); ?></span>
 
 
 
 
455
  </div>
456
  </div>
 
 
 
 
 
 
 
 
 
457
  </div>
458
  </div>
459
+ <br/><br/>
460
 
461
 
462
+ <!-- ERROR DETAILS-->
463
+ <div class="dup-box no-top">
464
+ <div class="dup-box-title" id="dup-pack-build-err-info" >
465
+ <i class="fas fa-file-contract fa-fw fa-sm"></i>
466
+ <?php esc_html_e('System Details', 'duplicator'); ?>
467
+ <div class="dup-box-arrow"><i class="fa fa-caret-down"></i></div>
468
+ </div>
469
+ <div class="dup-box-panel" style="display:none">
470
+ <span class="label"><?php esc_html_e("Error Message:", 'duplicator'); ?></span>
471
+ <div class="dup-msg-error-area">
472
+ <div id="dup-msg-error-response-text">
473
+ <span class="data"><?php esc_html_e("Error status unavailable.", 'duplicator'); ?></span>
474
+ </div>
475
+ </div>
476
 
477
+ <div id="dup-logs" style="color:maroon; font-size:16px">
478
+ <br/>
479
+ <i class="fas fa-file-contract fa-fw "></i>
480
+ <a href='javascript:void(0)' style="color:maroon" onclick='Duplicator.OpenLogWindow(true)'>
481
+ <?php esc_html_e('See Package Log For Complete Details', 'duplicator'); ?>
482
+ </a>
483
+ </div>
484
+ </div>
485
+ </div>
486
+ <br/><br/>
487
 
 
488
  </div>
489
 
490
+
491
  </div>
492
  </div>
493
  </form>
494
 
495
  <script>
496
+ jQuery(document).ready(function ($) {
 
497
 
498
  Duplicator.Pack.DupArchiveFailureCount = 0;
499
  Duplicator.Pack.DupArchiveMaxRetries = 10;
504
  /* ----------------------------------------
505
  * METHOD:Performs Ajax post to create a new package
506
  * Timeout (10000000 = 166 minutes) */
507
+ Duplicator.Pack.CreateZip = function () {
 
508
  var startTime;
509
  var data = {action:'duplicator_package_build', nonce:'<?php echo esc_js($zip_build_nonce); ?>'}
510
  var statusInterval = setInterval(Duplicator.Pack.GetActivePackageStatus, Duplicator.Pack.StatusFrequency);
531
  $('#dup-progress-bar-area').hide();
532
  $('#dup-progress-area, #dup-msg-error').show(200);
533
  var status = xHr.status + ' -' + data.statusText;
534
+ var response = (xHr.responseText != undefined && xHr.responseText.trim().length > 1)
535
+ ? xHr.responseText.trim()
536
+ : 'No client side error - see package log file';
537
  $('#dup-msg-error-response-status span.data').html(status)
538
  $('#dup-msg-error-response-text span.data').html(response);
539
  console.log(xHr);
540
  return false;
541
  }
542
+
543
  if ((data != null) && (typeof (data) != 'undefined') && data.status == 1) {
544
  Duplicator.Pack.WireDownloadLinks(data);
545
  } else {
546
  var message = (typeof (data.error) != 'undefined' && data.error.length) ? data.error :'Error processing package';
547
  Duplicator.Pack.DupArchiveProcessingFailed(message);
548
  }
549
+
550
  },
551
  error:function (xHr) {
552
  $('#dup-progress-bar-area').hide();
553
  $('#dup-progress-area, #dup-msg-error').show(200);
554
  var status = xHr.status + ' -' + data.statusText;
555
+ var response = (xHr.responseText != undefined && xHr.responseText.trim().length > 1)
556
+ ? xHr.responseText.trim()
557
+ : 'No client side error - see package log file';
558
  $('#dup-msg-error-response-status span.data').html(status)
559
  $('#dup-msg-error-response-text span.data').html(response);
560
  console.log(xHr);
565
 
566
  /* ----------------------------------------
567
  * METHOD:Performs Ajax post to create a new DupArchive-based package */
568
+ Duplicator.Pack.CreateDupArchive = function () {
 
569
  console.log('Duplicator.Pack.CreateDupArchive');
570
  var data = {action:'duplicator_duparchive_package_build', nonce:'<?php echo esc_js($duparchive_build_nonce); ?>'}
571
  var statusInterval = setInterval(Duplicator.Pack.GetActivePackageStatus, Duplicator.Pack.StatusFrequency);
572
+
573
  $.ajax({
574
  type:"POST",
575
  timeout:0, // no timeout
595
  }
596
 
597
  console.log("CreateDupArchive:AJAX success. Data equals:");
 
598
  console.log(data);
599
  // DATA FIELDS
600
  // archive_offset, archive_size, failures, file_index, is_done, timestamp
618
  // Don't stop for non-critical failures - just display those at the end TODO:put these in the log not popup
619
  console.log("CreateDupArchive:archive has completed");
620
  if (data.failures.length > 0) {
 
621
  console.log(data.failures);
622
  var errorMessage = "CreateDupArchive:Problems during package creation. These may be non-critical so continue with install.\n------\n";
623
  var len = data.failures.length;
637
  setTimeout(Duplicator.Pack.CreateDupArchive, 500);
638
  }
639
  } else {
 
640
  console.log("CreateDupArchive:critical failures present");
641
  // If we get a critical failure it means it's something we can't recover from so no purpose in retrying, just fail immediately.
642
  var errorString = 'Error Processing Step 1<br/>';
671
 
672
  /* ----------------------------------------
673
  * METHOD:Retrieves package status and updates UI with build percentage */
674
+ Duplicator.Pack.GetActivePackageStatus = function () {
 
675
  var data = {action:'DUP_CTRL_Package_getActivePackageStatus', nonce:'<?php echo wp_create_nonce('DUP_CTRL_Package_getActivePackageStatus'); ?>'}
676
  console.log('####Duplicator.Pack.GetActivePackageStatus');
677
 
706
  return false;
707
  }
708
 
709
+ Duplicator.Pack.PostTransferCleanup = function(statusInterval, startTime) {
 
710
  clearInterval(statusInterval);
711
  endTime = new Date().getTime();
712
  var millis = (endTime - startTime);
714
  var seconds = ((millis % 60000) / 1000).toFixed(0);
715
  var status = minutes + ":" + (seconds < 10 ? '0' :'') + seconds;
716
  $('#dup-msg-error-response-time span.data').html(status);
 
 
717
  };
718
 
719
+ Duplicator.Pack.WireDownloadLinks = function(data) {
 
720
  var pack = data.package;
721
  var archive_json = {
722
  filename:pack.Archive.File,
735
  $('#data-time').text(data.runtime || 'unable to read time');
736
  $('#dup-create-new').removeClass('no-display');
737
  $('#dup-packages-btn').removeClass('no-display');
738
+
739
  //Wire Up Downloads
740
  $('#dup-btn-installer').click(function() {
741
  Duplicator.Pack.DownloadInstaller(installer_json);
754
  }, 700);
755
  return false;
756
  });
757
+
758
  $('#dup-click-to-copy-installer-name').data('dup-copy-text', data.instDownloadName);
759
  $('#dup-installer-name').data('data-installer-name', data.instDownloadName);
760
  };
761
 
762
+ Duplicator.Pack.HandleDupArchiveInterruption = function (errorText) {
 
763
  Duplicator.Pack.DupArchiveFailureCount++;
764
 
765
  if (Duplicator.Pack.DupArchiveFailureCount <= Duplicator.Pack.DupArchiveMaxRetries) {
774
  }
775
  };
776
 
777
+ Duplicator.Pack.DupArchiveProcessingFailed = function (errorText) {
 
778
  $('#dup-progress-bar-area').hide();
779
  $('#dup-progress-area, #dup-msg-error').show(200);
780
  $('#dup-msg-error-response-text span.data').html(errorText);
781
+ $('#dup-pack-build-err-info').trigger('click');
782
  };
783
 
784
  Duplicator.Pack.GetFailureText = function (failures, onlyCritical)
785
  {
786
  var retVal = '';
 
787
  if ((failures !== null) && (typeof failures !== 'undefined')) {
788
  var len = failures.length;
789
 
824
  var txt = $('#dup-installer-name').data('data-installer-name');
825
  $('#dup-installer-name').html(txt);
826
  $('#dup-installer-name-help-icon').show();
 
827
  };
828
 
829
  //Page Init:
835
  Duplicator.Pack.CreateDupArchive();
836
  <?php endif; ?>
837
  });
838
+ </script>
views/settings/import.php CHANGED
@@ -3,7 +3,6 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
3
  ?>
4
  <style>
5
  div.panel {padding: 20px 5px 10px 10px; text-align: center; }
6
- div.sc-note {color:maroon; font-style: italic; line-height:17px; font-size:13px; margin:30px auto 40px auto; max-width: 650px; display:none}
7
  </style>
8
 
9
  <div class="panel">
@@ -20,13 +19,6 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
20
  ?>
21
  </div>
22
 
23
- <div class="sc-note">
24
- <?php esc_html_e(' Drag and Drop import functionality works with packages created by Duplicator Pro. In the near future, the Duplicator Pro importer '
25
- . 'will be enhanced to allow the importing of Duplicator Lite packages. For instructions on how to perform a classic or overwrite install with Duplicator Lite '
26
- . 'packages visit the ', 'duplicator'); ?>
27
- <a href="https://snapcreek.com/duplicator/docs/quick-start/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=package_built_install_help5&utm_campaign=duplicator_free#install_site" target="_blank"><?php esc_html_e('Quick Start Guide', 'duplicator'); ?></a>.
28
- </div>
29
-
30
  <a class="dup-btn-call-action" href="https://snapcreek.com/duplicator/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=free_tools_imports_checkitout&utm_campaign=duplicator_pro" target="_blank">
31
  <?php esc_html_e('Check It Out!', 'duplicator') ?>
32
  </a>
3
  ?>
4
  <style>
5
  div.panel {padding: 20px 5px 10px 10px; text-align: center; }
 
6
  </style>
7
 
8
  <div class="panel">
19
  ?>
20
  </div>
21
 
 
 
 
 
 
 
 
22
  <a class="dup-btn-call-action" href="https://snapcreek.com/duplicator/?utm_source=duplicator_free&utm_medium=wordpress_plugin&utm_content=free_tools_imports_checkitout&utm_campaign=duplicator_pro" target="_blank">
23
  <?php esc_html_e('Check It Out!', 'duplicator') ?>
24
  </a>
views/settings/packages.php CHANGED
@@ -87,7 +87,7 @@ $installerNameMode = DUP_Settings::Get('installer_name_mode');
87
  <hr size="1" />
88
  <table class="form-table">
89
  <tr>
90
- <th scope="row"><label><?php esc_html_e("SQL Script", 'duplicator'); ?></label></th>
91
  <td>
92
  <div class="engine-radio <?php echo ($is_shellexec_on) ? '' : 'engine-radio-disabled'; ?>">
93
  <input type="radio" name="package_dbmode" value="mysql" id="package_mysqldump" <?php echo ($package_mysqldump) ? 'checked="checked"' : ''; ?> />
87
  <hr size="1" />
88
  <table class="form-table">
89
  <tr>
90
+ <th scope="row"><label><?php esc_html_e("SQL Mode", 'duplicator'); ?></label></th>
91
  <td>
92
  <div class="engine-radio <?php echo ($is_shellexec_on) ? '' : 'engine-radio-disabled'; ?>">
93
  <input type="radio" name="package_dbmode" value="mysql" id="package_mysqldump" <?php echo ($package_mysqldump) ? 'checked="checked"' : ''; ?> />
views/settings/storage.php CHANGED
@@ -13,9 +13,9 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
13
  $action_response = esc_html__("Storage Settings Saved", 'duplicator');
14
 
15
  //SAVE RESULTS
16
- if (filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING) === 'save') {
17
  //Nonce Check
18
- if (!wp_verify_nonce(filter_input(INPUT_POST, 'dup_storage_settings_save_nonce_field', FILTER_SANITIZE_STRING), 'dup_settings_save')) {
19
  die('Invalid token permissions to perform this request.');
20
  }
21
 
@@ -91,8 +91,8 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
91
  . "the 'Contents Path'. Upon clicking the save button all files are moved to the new location and the previous path is removed.", 'duplicator');
92
  ?><br/>
93
 
94
-
95
- <i class="fas fa-database fa-sm"></i>&nbsp; <span id="duplicator_advanced_storage_text" class="link-style">[<?php esc_html_e("More Advanced Storage Options...", 'duplicator'); ?>]</span>
96
  </p>
97
  </td>
98
  </tr>
@@ -129,19 +129,19 @@ function dup_lite_storage_advanced_pro_content()
129
  <div style="text-align: center">
130
  <img src="<?php echo esc_url(DUPLICATOR_PLUGIN_URL."assets/img/logo-dpro-300x50.png"); ?>" style="height:50px; width:250px" /><br/>
131
  <?php
132
- esc_html_e('Store &amp; Automate to Multiple Endpoints', 'duplicator');
133
  echo '<br/>';
134
  esc_html_e('with Duplicator Pro', 'duplicator');
135
  ?>
136
 
137
- <div style="text-align: left; margin:auto; width:175px">
138
  <ul>
139
- <li><i class="fab fa-amazon"></i> <?php esc_html_e('Amazon S3', 'duplicator'); ?></li>
140
- <li><i class="fab fa-dropbox"></i> <?php esc_html_e(' Dropbox', 'duplicator'); ?></li>
141
- <li><i class="fab fa-google-drive"></i> <?php esc_html_e('Google Drive', 'duplicator'); ?></li>
142
- <li><i class="fa fa-cloud fa-sm"></i> <?php esc_html_e('One Drive', 'duplicator'); ?></li>
143
- <li><i class="fa fa-upload"></i> <?php esc_html_e('FTP &amp; SFTP', 'duplicator'); ?></li>
144
- <li><i class="far fa-folder-open"></i> <?php esc_html_e('Custom Directory', 'duplicator'); ?></li>
145
  </ul>
146
  </div>
147
  <i>
13
  $action_response = esc_html__("Storage Settings Saved", 'duplicator');
14
 
15
  //SAVE RESULTS
16
+ if (filter_input(INPUT_POST, 'action', FILTER_UNSAFE_RAW) === 'save') {
17
  //Nonce Check
18
+ if (!wp_verify_nonce(filter_input(INPUT_POST, 'dup_storage_settings_save_nonce_field', FILTER_UNSAFE_RAW), 'dup_settings_save')) {
19
  die('Invalid token permissions to perform this request.');
20
  }
21
 
91
  . "the 'Contents Path'. Upon clicking the save button all files are moved to the new location and the previous path is removed.", 'duplicator');
92
  ?><br/>
93
 
94
+ <i class="fas fa-server fa-sm"></i>&nbsp;
95
+ <span id="duplicator_advanced_storage_text" class="link-style">[<?php esc_html_e("More Advanced Storage Options...", 'duplicator'); ?>]</span>
96
  </p>
97
  </td>
98
  </tr>
129
  <div style="text-align: center">
130
  <img src="<?php echo esc_url(DUPLICATOR_PLUGIN_URL."assets/img/logo-dpro-300x50.png"); ?>" style="height:50px; width:250px" /><br/>
131
  <?php
132
+ esc_html_e('Store to Multiple Endpoints', 'duplicator');
133
  echo '<br/>';
134
  esc_html_e('with Duplicator Pro', 'duplicator');
135
  ?>
136
 
137
+ <div style="text-align: left; margin:auto; width:200px">
138
  <ul>
139
+ <li><i class="fab fa-amazon"></i>&nbsp;<?php esc_html_e('Amazon S3', 'duplicator'); ?></li>
140
+ <li><i class="fab fa-dropbox"></i>&nbsp;<?php esc_html_e(' Dropbox', 'duplicator'); ?></li>
141
+ <li><i class="fab fa-google-drive"></i>&nbsp;<?php esc_html_e('Google Drive', 'duplicator'); ?></li>
142
+ <li><i class="fa fa-cloud fa-sm"></i>&nbsp;<?php esc_html_e('One Drive', 'duplicator'); ?></li>
143
+ <li><i class="fas fa-network-wired"></i>&nbsp;<?php esc_html_e('FTP &amp; SFTP', 'duplicator'); ?></li>
144
+ <li><i class="fas fa-hdd"></i>&nbsp;<?php esc_html_e('Custom Directory', 'duplicator'); ?></li>
145
  </ul>
146
  </div>
147
  <i>
views/tools/diagnostics/inc.settings.php CHANGED
@@ -193,7 +193,7 @@ SERVER SETTINGS -->
193
  </tr>
194
  <tr>
195
  <td><?php esc_html_e("Charset", 'duplicator'); ?></td>
196
- <td><?php echo DB_CHARSET ?></td>
197
  </tr>
198
  <tr>
199
  <td><a href="http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_wait_timeout" target="_blank"><?php esc_html_e("Wait Timeout", 'duplicator'); ?></a></td>
193
  </tr>
194
  <tr>
195
  <td><?php esc_html_e("Charset", 'duplicator'); ?></td>
196
+ <td><?php echo defined('DB_CHARSET') ? DB_CHARSET : 'DB_CHARSET not set' ; ?></td>
197
  </tr>
198
  <tr>
199
  <td><a href="http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_wait_timeout" target="_blank"><?php esc_html_e("Wait Timeout", 'duplicator'); ?></a></td>
views/tools/diagnostics/logging.php CHANGED
@@ -175,7 +175,7 @@ jQuery(document).ready(function($)
175
  <tr>
176
  <td id="dup-log-panel-left">
177
  <div class="name">
178
- <i class='fa fa-list-alt'></i> <b><?php echo basename($logurl); ?></b> &nbsp; | &nbsp;
179
  <i style="cursor: pointer"
180
  data-tooltip-title="<?php esc_attr_e("Host Recommendation:", 'duplicator'); ?>"
181
  data-tooltip="<?php esc_attr_e('Duplicator recommends going with the high performance pro plan or better from our recommended list', 'duplicator'); ?>">
175
  <tr>
176
  <td id="dup-log-panel-left">
177
  <div class="name">
178
+ <i class='fas fa-file-contract fa-fw'></i> <b><?php echo basename($logurl); ?></b> &nbsp; | &nbsp;
179
  <i style="cursor: pointer"
180
  data-tooltip-title="<?php esc_attr_e("Host Recommendation:", 'duplicator'); ?>"
181
  data-tooltip="<?php esc_attr_e('Duplicator recommends going with the high performance pro plan or better from our recommended list', 'duplicator'); ?>">