Version Description
Download this release
Release Info
Developer | cory@lamle.org |
Plugin | Duplicator – WordPress Migration Plugin |
Version | 1.3.16 |
Comparing to | |
See all releases |
Code changes from version 1.3.14 to 1.3.16
- classes/class.constants.php +1 -1
- classes/class.logging.php +275 -33
- classes/class.settings.php +9 -2
- classes/host/class.godaddy.host.php +15 -0
- classes/host/class.wpengine.host.php +34 -0
- classes/package/class.pack.archive.filters.php +8 -0
- classes/package/class.pack.archive.php +9 -2
- classes/package/class.pack.archive.zip.php +2 -2
- classes/package/class.pack.database.php +1 -1
- classes/package/class.pack.installer.php +4 -6
- classes/package/class.pack.php +14 -3
- classes/package/duparchive/class.pack.archive.duparchive.php +2 -5
- classes/utilities/class.u.php +41 -42
- ctrls/class.web.services.php +81 -76
- ctrls/ctrl.package.php +29 -15
- ctrls/ctrl.tools.php +2 -0
- ctrls/ctrl.ui.php +1 -0
- deactivation.php +4 -0
- define.php +3 -2
- duplicator.php +16 -3
- installer/dup-installer/assets/inc.css.php +23 -15
- installer/dup-installer/assets/inc.libs.js.php +0 -2
- installer/dup-installer/classes/class.db.php +45 -12
- installer/dup-installer/classes/class.engine.php +780 -373
- installer/dup-installer/classes/class.http.php +7 -1
- installer/dup-installer/classes/class.s3.func.php +1319 -0
- installer/dup-installer/classes/class.view.php +72 -72
- installer/dup-installer/classes/config/class.boot.php +1 -0
- installer/dup-installer/classes/config/class.conf.srv.php +92 -177
- installer/dup-installer/classes/config/class.constants.php +19 -4
- installer/dup-installer/classes/utilities/class.u.php +38 -7
- installer/dup-installer/classes/utilities/class.u.search.reaplce.manager.php +611 -0
- installer/dup-installer/ctrls/ctrl.base.php +38 -37
- installer/dup-installer/ctrls/ctrl.s1.php +74 -71
- installer/dup-installer/ctrls/ctrl.s2.base.php +21 -1
- installer/dup-installer/ctrls/ctrl.s3.php +34 -655
- installer/dup-installer/index.php +7 -1
- installer/dup-installer/main.installer.php +17 -12
- installer/dup-installer/views/view.help.php +71 -54
- installer/dup-installer/views/view.s1.base.php +4 -3
- installer/dup-installer/views/view.s3.php +10 -0
- installer/dup-installer/views/view.s4.php +1 -0
- installer/installer.tpl +989 -210
- lib/config/class.wp.config.tranformer.php +37 -14
- lib/config/class.wp.config.tranformer.src.php +7 -8
- lib/dup_archive/classes/class.duparchive.engine.php +2 -9
- lib/dup_archive/classes/class.duparchive.mini.expander.php +11 -14
- lib/dup_archive/classes/processors/class.duparchive.processor.file.php +7 -13
- lib/dup_archive/daws/daws.php +1 -1
- lib/snaplib/class.snaplib.u.io.php +211 -31
- lib/snaplib/class.snaplib.u.os.php +32 -6
- lib/snaplib/class.snaplib.u.util.php +1 -1
- readme.txt +1 -1
- views/packages/controller.php +2 -0
- views/packages/main/controller.php +2 -0
- views/packages/main/packages.php +1 -1
- views/packages/main/s1.setup2.php +2 -0
- views/packages/main/s3.build.php +1 -1
- views/settings/controller.php +1 -0
- views/settings/gopro.php +2 -2
- views/tools/controller.php +2 -0
classes/class.constants.php
CHANGED
@@ -2,5 +2,5 @@
|
|
2 |
defined("ABSPATH") || exit;
|
3 |
class DUP_Constants
|
4 |
{
|
5 |
-
const ZIP_STRING_LIMIT =
|
6 |
}
|
2 |
defined("ABSPATH") || exit;
|
3 |
class DUP_Constants
|
4 |
{
|
5 |
+
const ZIP_STRING_LIMIT = 70000; // Cutoff for using ZipArchive addtostring vs addfile
|
6 |
}
|
classes/class.logging.php
CHANGED
@@ -16,15 +16,18 @@ abstract class Dup_ErrorBehavior
|
|
16 |
|
17 |
class DUP_Log
|
18 |
{
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
28 |
/**
|
29 |
* Init this static object
|
30 |
*/
|
@@ -33,37 +36,71 @@ class DUP_Log
|
|
33 |
self::$traceEnabled = (DUP_Settings::Get('trace_log_enabled') == 1);
|
34 |
}
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
|
46 |
/**
|
47 |
-
*
|
48 |
-
*/
|
49 |
-
public static function Close()
|
50 |
-
{
|
51 |
-
@fclose(self::$logFileHandle);
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* General information logging
|
56 |
* @param string $msg The message to log
|
57 |
*
|
58 |
* REPLACE TO DEBUG: Memory consumption as script runs
|
59 |
* $results = DUP_Util::byteSize(memory_get_peak_usage(true)) . "\t" . $msg;
|
60 |
* @fwrite(self::$logFileHandle, "{$results} \n");
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
68 |
/**
|
69 |
* Does the trace file exists
|
@@ -134,6 +171,13 @@ class DUP_Log
|
|
134 |
}
|
135 |
}
|
136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
public static function errLog($message)
|
138 |
{
|
139 |
$message = 'DUP:'.$message;
|
@@ -279,4 +323,202 @@ class DUP_Log
|
|
279 |
}
|
280 |
}
|
281 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
282 |
DUP_Log::Init();
|
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 |
*/
|
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(DUPLICATOR_SSDIR_PATH."/{$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 |
+
if (!is_null(self::$logFileHandle)) {
|
72 |
+
$result = @fclose(self::$logFileHandle);
|
73 |
+
self::$logFileHandle = null;
|
74 |
+
}
|
75 |
+
return $result;
|
76 |
+
}
|
77 |
|
78 |
/**
|
79 |
+
* General information send to the package log if opened
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
* @param string $msg The message to log
|
81 |
*
|
82 |
* REPLACE TO DEBUG: Memory consumption as script runs
|
83 |
* $results = DUP_Util::byteSize(memory_get_peak_usage(true)) . "\t" . $msg;
|
84 |
* @fwrite(self::$logFileHandle, "{$results} \n");
|
85 |
+
*
|
86 |
+
* @param string $msg The message to log
|
87 |
+
*
|
88 |
+
* @return null
|
89 |
+
*/
|
90 |
+
public static function Info($msg)
|
91 |
+
{
|
92 |
+
self::Trace($msg);
|
93 |
+
if (!is_null(self::$logFileHandle)) {
|
94 |
+
@fwrite(self::$logFileHandle, $msg."\n");
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
public static function print_r_info($val, $name = '')
|
99 |
+
{
|
100 |
+
$msg = empty($name) ? '' : 'VALUE '.$name.': ';
|
101 |
+
$msg .= print_r($val, true);
|
102 |
+
self::info($msg);
|
103 |
+
}
|
104 |
|
105 |
/**
|
106 |
* Does the trace file exists
|
171 |
}
|
172 |
}
|
173 |
|
174 |
+
public static function print_r_trace($val, $name = '', $calling_function_override = null)
|
175 |
+
{
|
176 |
+
$msg = empty($name) ? '' : 'VALUE '.$name.': ';
|
177 |
+
$msg .= print_r($val, true);
|
178 |
+
self::trace($msg, $calling_function_override);
|
179 |
+
}
|
180 |
+
|
181 |
public static function errLog($message)
|
182 |
{
|
183 |
$message = 'DUP:'.$message;
|
323 |
}
|
324 |
}
|
325 |
}
|
326 |
+
|
327 |
+
class DUP_Handler
|
328 |
+
{
|
329 |
+
const MODE_OFF = 0; // don't write in log
|
330 |
+
const MODE_LOG = 1; // write errors in log file
|
331 |
+
const MODE_VAR = 2; // put php errors in $varModeLog static var
|
332 |
+
const SHUTDOWN_TIMEOUT = 'tm';
|
333 |
+
|
334 |
+
/**
|
335 |
+
*
|
336 |
+
* @var bool
|
337 |
+
*/
|
338 |
+
private static $inizialized = false;
|
339 |
+
|
340 |
+
/**
|
341 |
+
*
|
342 |
+
* @var array
|
343 |
+
*/
|
344 |
+
private static $shutdownReturns = array(
|
345 |
+
'tm' => 'timeout'
|
346 |
+
);
|
347 |
+
|
348 |
+
/**
|
349 |
+
*
|
350 |
+
* @var int
|
351 |
+
*/
|
352 |
+
private static $handlerMode = self::MODE_LOG;
|
353 |
+
|
354 |
+
/**
|
355 |
+
*
|
356 |
+
* @var bool // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100]
|
357 |
+
*/
|
358 |
+
private static $codeReference = true;
|
359 |
+
|
360 |
+
/**
|
361 |
+
*
|
362 |
+
* @var bool // print prefix in php error line [PHP ERR][WARN] MSG: .....
|
363 |
+
*/
|
364 |
+
private static $errPrefix = true;
|
365 |
+
|
366 |
+
/**
|
367 |
+
*
|
368 |
+
* @var string // php errors in MODE_VAR
|
369 |
+
*/
|
370 |
+
private static $varModeLog = '';
|
371 |
+
|
372 |
+
/**
|
373 |
+
* This function only initializes the error handler the first time it is called
|
374 |
+
*/
|
375 |
+
public static function init_error_handler()
|
376 |
+
{
|
377 |
+
if (!self::$inizialized) {
|
378 |
+
@set_error_handler(array(__CLASS__, 'error'));
|
379 |
+
@register_shutdown_function(array(__CLASS__, 'shutdown'));
|
380 |
+
self::$inizialized = true;
|
381 |
+
}
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* Error handler
|
386 |
+
*
|
387 |
+
* @param integer $errno Error level
|
388 |
+
* @param string $errstr Error message
|
389 |
+
* @param string $errfile Error file
|
390 |
+
* @param integer $errline Error line
|
391 |
+
* @return void
|
392 |
+
*/
|
393 |
+
public static function error($errno, $errstr, $errfile, $errline)
|
394 |
+
{
|
395 |
+
switch (self::$handlerMode) {
|
396 |
+
case self::MODE_OFF:
|
397 |
+
if ($errno == E_ERROR) {
|
398 |
+
$log_message = self::getMessage($errno, $errstr, $errfile, $errline);
|
399 |
+
DUP_Log::Error($log_message);
|
400 |
+
}
|
401 |
+
break;
|
402 |
+
case self::MODE_VAR:
|
403 |
+
self::$varModeLog .= self::getMessage($errno, $errstr, $errfile, $errline)."\n";
|
404 |
+
break;
|
405 |
+
case self::MODE_LOG:
|
406 |
+
default:
|
407 |
+
switch ($errno) {
|
408 |
+
case E_ERROR :
|
409 |
+
$log_message = self::getMessage($errno, $errstr, $errfile, $errline);
|
410 |
+
DUP_Log::Error($log_message);
|
411 |
+
break;
|
412 |
+
case E_NOTICE :
|
413 |
+
case E_WARNING :
|
414 |
+
default :
|
415 |
+
$log_message = self::getMessage($errno, $errstr, $errfile, $errline);
|
416 |
+
DUP_Log::Info($log_message);
|
417 |
+
break;
|
418 |
+
}
|
419 |
+
}
|
420 |
+
}
|
421 |
+
|
422 |
+
private static function getMessage($errno, $errstr, $errfile, $errline)
|
423 |
+
{
|
424 |
+
$result = '';
|
425 |
+
|
426 |
+
if (self::$errPrefix) {
|
427 |
+
$result = '[PHP ERR]';
|
428 |
+
switch ($errno) {
|
429 |
+
case E_ERROR :
|
430 |
+
$result .= '[FATAL]';
|
431 |
+
break;
|
432 |
+
case E_WARNING :
|
433 |
+
$result .= '[WARN]';
|
434 |
+
break;
|
435 |
+
case E_NOTICE :
|
436 |
+
$result .= '[NOTICE]';
|
437 |
+
break;
|
438 |
+
default :
|
439 |
+
$result .= '[ISSUE]';
|
440 |
+
break;
|
441 |
+
}
|
442 |
+
$result .= ' MSG:';
|
443 |
+
}
|
444 |
+
|
445 |
+
$result .= $errstr;
|
446 |
+
|
447 |
+
if (self::$codeReference) {
|
448 |
+
$result .= ' [CODE:'.$errno.'|FILE:'.$errfile.'|LINE:'.$errline.']';
|
449 |
+
}
|
450 |
+
|
451 |
+
return $result;
|
452 |
+
}
|
453 |
+
|
454 |
+
/**
|
455 |
+
* if setMode is called without params set as default
|
456 |
+
*
|
457 |
+
* @param int $mode
|
458 |
+
* @param bool $errPrefix // print prefix in php error line [PHP ERR][WARN] MSG: .....
|
459 |
+
* @param bool $codeReference // print code reference and errno at end of php error line [CODE:10|FILE:test.php|LINE:100]
|
460 |
+
*/
|
461 |
+
public static function setMode($mode = self::MODE_LOG, $errPrefix = true, $codeReference = true)
|
462 |
+
{
|
463 |
+
switch ($mode) {
|
464 |
+
case self::MODE_OFF:
|
465 |
+
case self::MODE_VAR:
|
466 |
+
self::$handlerMode = $mode;
|
467 |
+
break;
|
468 |
+
case self::MODE_LOG:
|
469 |
+
default:
|
470 |
+
self::$handlerMode = self::MODE_LOG;
|
471 |
+
}
|
472 |
+
|
473 |
+
self::$varModeLog = '';
|
474 |
+
self::$errPrefix = $errPrefix;
|
475 |
+
self::$codeReference = $codeReference;
|
476 |
+
}
|
477 |
+
|
478 |
+
/**
|
479 |
+
*
|
480 |
+
* @return string // return var log string in MODE_VAR
|
481 |
+
*/
|
482 |
+
public static function getVarLog()
|
483 |
+
{
|
484 |
+
return self::$varModeLog;
|
485 |
+
}
|
486 |
+
|
487 |
+
/**
|
488 |
+
*
|
489 |
+
* @return string // return var log string in MODE_VAR and clean var
|
490 |
+
*/
|
491 |
+
public static function getVarLogClean()
|
492 |
+
{
|
493 |
+
$result = self::$varModeLog;
|
494 |
+
self::$varModeLog = '';
|
495 |
+
return $result;
|
496 |
+
}
|
497 |
+
|
498 |
+
/**
|
499 |
+
*
|
500 |
+
* @param string $status // timeout
|
501 |
+
* @param string
|
502 |
+
*/
|
503 |
+
public static function setShutdownReturn($status, $str)
|
504 |
+
{
|
505 |
+
self::$shutdownReturns[$status] = $str;
|
506 |
+
}
|
507 |
+
|
508 |
+
/**
|
509 |
+
* Shutdown handler
|
510 |
+
*
|
511 |
+
* @return void
|
512 |
+
*/
|
513 |
+
public static function shutdown()
|
514 |
+
{
|
515 |
+
if (($error = error_get_last())) {
|
516 |
+
if (preg_match('/^Maximum execution time (?:.+) exceeded$/i', $error['message'])) {
|
517 |
+
echo self::$shutdownReturns[self::SHUTDOWN_TIMEOUT];
|
518 |
+
}
|
519 |
+
self::error($error['type'], $error['message'], $error['file'], $error['line']);
|
520 |
+
}
|
521 |
+
}
|
522 |
+
}
|
523 |
+
|
524 |
DUP_Log::Init();
|
classes/class.settings.php
CHANGED
@@ -89,7 +89,7 @@ class DUP_Settings
|
|
89 |
public static function SetDefaults()
|
90 |
{
|
91 |
$defaults = self::GetAllDefaults();
|
92 |
-
self::$Data = $defaults;
|
93 |
return self::Save();
|
94 |
}
|
95 |
|
@@ -130,7 +130,14 @@ class DUP_Settings
|
|
130 |
//Flag for .htaccess file
|
131 |
$default['storage_htaccess_off'] = isset(self::$Data['storage_htaccess_off']) ? self::$Data['storage_htaccess_off'] : false;
|
132 |
// Initial archive build mode
|
133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
|
135 |
//Skip scan archive
|
136 |
$default['skip_archive_scan'] = isset(self::$Data['skip_archive_scan']) ? self::$Data['skip_archive_scan'] : false;
|
89 |
public static function SetDefaults()
|
90 |
{
|
91 |
$defaults = self::GetAllDefaults();
|
92 |
+
self::$Data = apply_filters('duplicator_defaults_settings', $defaults);
|
93 |
return self::Save();
|
94 |
}
|
95 |
|
130 |
//Flag for .htaccess file
|
131 |
$default['storage_htaccess_off'] = isset(self::$Data['storage_htaccess_off']) ? self::$Data['storage_htaccess_off'] : false;
|
132 |
// Initial archive build mode
|
133 |
+
if (isset(self::$Data['archive_build_mode'])) {
|
134 |
+
$default['archive_build_mode'] = self::$Data['archive_build_mode'];
|
135 |
+
} else {
|
136 |
+
$is_ziparchive_available = apply_filters('duplicator_is_ziparchive_available', class_exists('ZipArchive'));
|
137 |
+
$default['archive_build_mode'] = $is_ziparchive_available ? DUP_Archive_Build_Mode::ZipArchive : DUP_Archive_Build_Mode::DupArchive;
|
138 |
+
}
|
139 |
+
|
140 |
+
// $default['package_zip_flush'] = apply_filters('duplicator_package_zip_flush_default_setting', '0');
|
141 |
|
142 |
//Skip scan archive
|
143 |
$default['skip_archive_scan'] = isset(self::$Data['skip_archive_scan']) ? self::$Data['skip_archive_scan'] : false;
|
classes/host/class.godaddy.host.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined("ABSPATH") or die("");
|
3 |
+
|
4 |
+
class DUP_GoDaddy_Host {
|
5 |
+
public static function init() {
|
6 |
+
add_filter('duplicator_defaults_settings', array('DUP_GoDaddy_Host', 'defaultsSettings'));
|
7 |
+
}
|
8 |
+
|
9 |
+
public static function defaultsSettings($defaults) {
|
10 |
+
$defaults['archive_build_mode'] = DUP_Archive_Build_Mode::DupArchive;
|
11 |
+
return $defaults;
|
12 |
+
}
|
13 |
+
}
|
14 |
+
|
15 |
+
DUP_GoDaddy_Host::init();
|
classes/host/class.wpengine.host.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
defined("ABSPATH") or die("");
|
3 |
+
// New encryption class
|
4 |
+
|
5 |
+
class DUP_WPEngine_Host {
|
6 |
+
public static function init() {
|
7 |
+
add_filter('duplicator_installer_file_path', array('DUP_WPEngine_Host', 'installerFilePath'), 10, 1);
|
8 |
+
add_filter('duplicator_global_file_filters_on', '__return_true');
|
9 |
+
add_filter('duplicator_global_file_filters', array('DUP_WPEngine_Host', 'globalFileFilters'), 10, 1);
|
10 |
+
add_filter('duplicator_defaults_settings', array('DUP_WPEngine_Host', 'defaultsSettings'));
|
11 |
+
}
|
12 |
+
|
13 |
+
public static function installerFilePath($path) {
|
14 |
+
$path_info = pathinfo($path);
|
15 |
+
$newPath = $path;
|
16 |
+
if ('php' == $path_info['extension']) {
|
17 |
+
$newPath = substr_replace($path, '.txt', -4);
|
18 |
+
}
|
19 |
+
return $newPath;
|
20 |
+
}
|
21 |
+
|
22 |
+
public static function globalFileFilters($files) {
|
23 |
+
$files[] = wp_normalize_path(WP_CONTENT_DIR).'/mysql.sql';
|
24 |
+
return $files;
|
25 |
+
}
|
26 |
+
|
27 |
+
public static function defaultsSettings($defaults) {
|
28 |
+
$defaults['package_zip_flush'] = '1';
|
29 |
+
return $defaults;
|
30 |
+
}
|
31 |
+
|
32 |
+
}
|
33 |
+
|
34 |
+
DUP_WPEngine_Host::init();
|
classes/package/class.pack.archive.filters.php
CHANGED
@@ -76,6 +76,14 @@ class DUP_Archive_Filter_Info
|
|
76 |
* Init this object
|
77 |
*/
|
78 |
public function __construct()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
{
|
80 |
$this->Dirs = new DUP_Archive_Filter_Scope_Directory();
|
81 |
$this->Files = new DUP_Archive_Filter_Scope_File();
|
76 |
* Init this object
|
77 |
*/
|
78 |
public function __construct()
|
79 |
+
{
|
80 |
+
$this->reset();
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* reset and clean all object
|
85 |
+
*/
|
86 |
+
public function reset()
|
87 |
{
|
88 |
$this->Dirs = new DUP_Archive_Filter_Scope_Directory();
|
89 |
$this->Files = new DUP_Archive_Filter_Scope_File();
|
classes/package/class.pack.archive.php
CHANGED
@@ -37,7 +37,12 @@ class DUP_Archive
|
|
37 |
public $Size = 0;
|
38 |
public $Dirs = array();
|
39 |
public $Files = array();
|
40 |
-
|
|
|
|
|
|
|
|
|
|
|
41 |
public $RecursiveLinks = array();
|
42 |
public $file_count = -1;
|
43 |
//PROTECTED
|
@@ -344,8 +349,10 @@ class DUP_Archive
|
|
344 |
$this->FilterInfo->Dirs->Core[] = $wp_content.'/'.$backwpup_cfg_logfolder;
|
345 |
}
|
346 |
}
|
|
|
347 |
if ($GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS_ON']) {
|
348 |
-
$
|
|
|
349 |
}
|
350 |
|
351 |
// Prevent adding double wp-content dir conflicts
|
37 |
public $Size = 0;
|
38 |
public $Dirs = array();
|
39 |
public $Files = array();
|
40 |
+
|
41 |
+
/**
|
42 |
+
*
|
43 |
+
* @var DUP_Archive_Filter_Info
|
44 |
+
*/
|
45 |
+
public $FilterInfo = null;
|
46 |
public $RecursiveLinks = array();
|
47 |
public $file_count = -1;
|
48 |
//PROTECTED
|
349 |
$this->FilterInfo->Dirs->Core[] = $wp_content.'/'.$backwpup_cfg_logfolder;
|
350 |
}
|
351 |
}
|
352 |
+
$duplicator_global_file_filters_on = apply_filters('duplicator_global_file_filters_on', $GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS_ON']);
|
353 |
if ($GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS_ON']) {
|
354 |
+
$duplicator_global_file_filters = apply_filters('duplicator_global_file_filters', $GLOBALS['DUPLICATOR_GLOBAL_FILE_FILTERS']);
|
355 |
+
$this->FilterInfo->Files->Global = $duplicator_global_file_filters;
|
356 |
}
|
357 |
|
358 |
// Prevent adding double wp-content dir conflicts
|
classes/package/class.pack.archive.zip.php
CHANGED
@@ -127,7 +127,7 @@ class DUP_Zip extends DUP_Archive
|
|
127 |
$localFileName = $archive->getLocalFilePath($file);
|
128 |
|
129 |
if (is_readable($file)) {
|
130 |
-
if ($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++;
|
@@ -164,7 +164,7 @@ class DUP_Zip extends DUP_Archive
|
|
164 |
$localFileName = $archive->getLocalFilePath($file);
|
165 |
|
166 |
if (is_readable($file)) {
|
167 |
-
if ($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++;
|
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++;
|
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++;
|
classes/package/class.pack.database.php
CHANGED
@@ -640,7 +640,7 @@ class DUP_Database
|
|
640 |
}
|
641 |
|
642 |
if ($is_select_error) {
|
643 |
-
$fix = esc_html__('Please
|
644 |
$errorMessage = $select_last_error.' '.$fix.'.';
|
645 |
$package->BuildProgress->set_failed($errorMessage);
|
646 |
$package->BuildProgress->failed = true;
|
640 |
}
|
641 |
|
642 |
if ($is_select_error) {
|
643 |
+
$fix = esc_html__('Please contact your DataBase administrator to fix the error.', 'duplicator');
|
644 |
$errorMessage = $select_last_error.' '.$fix.'.';
|
645 |
$package->BuildProgress->set_failed($errorMessage);
|
646 |
$package->BuildProgress->failed = true;
|
classes/package/class.pack.installer.php
CHANGED
@@ -76,7 +76,7 @@ class DUP_Installer
|
|
76 |
{
|
77 |
$success = true;
|
78 |
$archive_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Archive->File}");
|
79 |
-
$installer_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_installer.php";
|
80 |
$template_filepath = DUPLICATOR_PLUGIN_PATH.'/installer/installer.tpl';
|
81 |
$mini_expander_filepath = DUPLICATOR_PLUGIN_PATH.'/lib/dup_archive/classes/class.duparchive.mini.expander.php';
|
82 |
|
@@ -183,7 +183,7 @@ class DUP_Installer
|
|
183 |
private function add_extra_files($package)
|
184 |
{
|
185 |
$success = false;
|
186 |
-
$installer_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_installer.php";
|
187 |
$scan_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_scan.json";
|
188 |
$sql_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Database->File}");
|
189 |
$archive_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Archive->File}");
|
@@ -299,12 +299,10 @@ class DUP_Installer
|
|
299 |
private function add_installer_files_using_duparchive($archive_filepath, $installer_filepath, $archive_config_filepath)
|
300 |
{
|
301 |
$installer_backup_filename = 'installer-backup.php';
|
302 |
-
|
303 |
|
304 |
DUP_Log::Info('Adding enhanced installer files to archive using DupArchive');
|
305 |
-
|
306 |
-
DupArchiveEngine::addFileToArchiveUsingBaseDirST($archive_filepath, dirname($installer_backup_filepath), $installer_backup_filepath);
|
307 |
-
DupLiteSnapLibIOU::rm($installer_backup_filepath);
|
308 |
|
309 |
$this->numFilesAdded++;
|
310 |
|
76 |
{
|
77 |
$success = true;
|
78 |
$archive_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Archive->File}");
|
79 |
+
$installer_filepath = apply_filters('duplicator_installer_file_path', DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_installer.php");
|
80 |
$template_filepath = DUPLICATOR_PLUGIN_PATH.'/installer/installer.tpl';
|
81 |
$mini_expander_filepath = DUPLICATOR_PLUGIN_PATH.'/lib/dup_archive/classes/class.duparchive.mini.expander.php';
|
82 |
|
183 |
private function add_extra_files($package)
|
184 |
{
|
185 |
$success = false;
|
186 |
+
$installer_filepath = apply_filters('duplicator_installer_file_path', DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_installer.php");
|
187 |
$scan_filepath = DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP)."/{$this->Package->NameHash}_scan.json";
|
188 |
$sql_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Database->File}");
|
189 |
$archive_filepath = DUP_Util::safePath("{$this->Package->StorePath}/{$this->Package->Archive->File}");
|
299 |
private function add_installer_files_using_duparchive($archive_filepath, $installer_filepath, $archive_config_filepath)
|
300 |
{
|
301 |
$installer_backup_filename = 'installer-backup.php';
|
302 |
+
|
303 |
|
304 |
DUP_Log::Info('Adding enhanced installer files to archive using DupArchive');
|
305 |
+
DupArchiveEngine::addRelativeFileToArchiveST($archive_filepath, $installer_filepath, $installer_backup_filename);
|
|
|
|
|
306 |
|
307 |
$this->numFilesAdded++;
|
308 |
|
classes/package/class.pack.php
CHANGED
@@ -360,6 +360,11 @@ class DUP_Package
|
|
360 |
return DUP_Settings::Get('active_package_id') == $this->ID && $this->Status >= 0 && $this->Status < 100;
|
361 |
}
|
362 |
|
|
|
|
|
|
|
|
|
|
|
363 |
/**
|
364 |
* Saves the active package to the package table
|
365 |
*
|
@@ -371,7 +376,7 @@ class DUP_Package
|
|
371 |
|
372 |
$this->Archive->Format = strtoupper($extension);
|
373 |
$this->Archive->File = "{$this->NameHash}_archive.{$extension}";
|
374 |
-
$this->Installer->File = "{$this->NameHash}_installer.php";
|
375 |
$this->Database->File = "{$this->NameHash}_database.sql";
|
376 |
$this->WPUser = isset($current_user->user_login) ? $current_user->user_login : 'unknown';
|
377 |
|
@@ -383,6 +388,7 @@ class DUP_Package
|
|
383 |
$this->writeLogHeader();
|
384 |
|
385 |
//CREATE DB RECORD
|
|
|
386 |
$packageObj = serialize($this);
|
387 |
if (!$packageObj) {
|
388 |
DUP_Log::Error("Unable to serialize package object while building record.");
|
@@ -720,6 +726,9 @@ class DUP_Package
|
|
720 |
if ($rows != null) {
|
721 |
$Package = @unserialize($rows[0]->package);
|
722 |
if ($Package) {
|
|
|
|
|
|
|
723 |
// We was not storing Status in Lite 1.2.52, so it is for backward compatibility
|
724 |
if (!isset($Package->Status)) {
|
725 |
$Package->Status = $row['status'];
|
@@ -943,7 +952,7 @@ class DUP_Package
|
|
943 |
|
944 |
if ($file_type == DUP_PackageFileType::Installer) {
|
945 |
DUP_Log::Trace("Installer requested");
|
946 |
-
$file_name = $this->getInstallerFilename();
|
947 |
} else if ($file_type == DUP_PackageFileType::Archive) {
|
948 |
DUP_Log::Trace("Archive requested");
|
949 |
$file_name = $this->getArchiveFilename();
|
@@ -1365,6 +1374,8 @@ class DUP_Package
|
|
1365 |
{
|
1366 |
global $wpdb;
|
1367 |
|
|
|
|
|
1368 |
$packageObj = serialize($this);
|
1369 |
|
1370 |
if (!$packageObj) {
|
@@ -1500,7 +1511,7 @@ class DUP_Package
|
|
1500 |
$row = $wpdb->get_row($sql);
|
1501 |
if (is_object($row)) {
|
1502 |
$obj = @unserialize($row->package);
|
1503 |
-
$obj->Status = $row->status;
|
1504 |
}
|
1505 |
//Incase unserilaize fails
|
1506 |
$obj = (is_object($obj)) ? $obj : null;
|
360 |
return DUP_Settings::Get('active_package_id') == $this->ID && $this->Status >= 0 && $this->Status < 100;
|
361 |
}
|
362 |
|
363 |
+
protected function cleanObjectBeforeSave()
|
364 |
+
{
|
365 |
+
$this->Archive->FilterInfo->reset();
|
366 |
+
}
|
367 |
+
|
368 |
/**
|
369 |
* Saves the active package to the package table
|
370 |
*
|
376 |
|
377 |
$this->Archive->Format = strtoupper($extension);
|
378 |
$this->Archive->File = "{$this->NameHash}_archive.{$extension}";
|
379 |
+
$this->Installer->File = apply_filters('duplicator_installer_file_path', "{$this->NameHash}_installer.php");
|
380 |
$this->Database->File = "{$this->NameHash}_database.sql";
|
381 |
$this->WPUser = isset($current_user->user_login) ? $current_user->user_login : 'unknown';
|
382 |
|
388 |
$this->writeLogHeader();
|
389 |
|
390 |
//CREATE DB RECORD
|
391 |
+
$this->cleanObjectBeforeSave();
|
392 |
$packageObj = serialize($this);
|
393 |
if (!$packageObj) {
|
394 |
DUP_Log::Error("Unable to serialize package object while building record.");
|
726 |
if ($rows != null) {
|
727 |
$Package = @unserialize($rows[0]->package);
|
728 |
if ($Package) {
|
729 |
+
if (empty($Package->ID)) {
|
730 |
+
$Package->ID = $rows[0]->id;
|
731 |
+
}
|
732 |
// We was not storing Status in Lite 1.2.52, so it is for backward compatibility
|
733 |
if (!isset($Package->Status)) {
|
734 |
$Package->Status = $row['status'];
|
952 |
|
953 |
if ($file_type == DUP_PackageFileType::Installer) {
|
954 |
DUP_Log::Trace("Installer requested");
|
955 |
+
$file_name = apply_filters('duplicator_installer_file_path', $this->getInstallerFilename());
|
956 |
} else if ($file_type == DUP_PackageFileType::Archive) {
|
957 |
DUP_Log::Trace("Archive requested");
|
958 |
$file_name = $this->getArchiveFilename();
|
1374 |
{
|
1375 |
global $wpdb;
|
1376 |
|
1377 |
+
$this->Status = number_format($this->Status, 1, '.', '');
|
1378 |
+
$this->cleanObjectBeforeSave();
|
1379 |
$packageObj = serialize($this);
|
1380 |
|
1381 |
if (!$packageObj) {
|
1511 |
$row = $wpdb->get_row($sql);
|
1512 |
if (is_object($row)) {
|
1513 |
$obj = @unserialize($row->package);
|
1514 |
+
// $obj->Status = $row->status;
|
1515 |
}
|
1516 |
//Incase unserilaize fails
|
1517 |
$obj = (is_object($obj)) ? $obj : null;
|
classes/package/duparchive/class.pack.archive.duparchive.php
CHANGED
@@ -35,11 +35,8 @@ class DUP_DupArchive
|
|
35 |
|
36 |
DUP_LOG::trace("start");
|
37 |
try {
|
38 |
-
|
39 |
-
|
40 |
-
}
|
41 |
-
|
42 |
-
DUP_LOG::trace("c2");
|
43 |
|
44 |
if ($buildProgress->retries > DUPLICATOR_MAX_BUILD_RETRIES) {
|
45 |
DUP_LOG::trace("c3");
|
35 |
|
36 |
DUP_LOG::trace("start");
|
37 |
try {
|
38 |
+
DUP_Log::Open($package->NameHash);
|
39 |
+
DUP_Log::trace("c2");
|
|
|
|
|
|
|
40 |
|
41 |
if ($buildProgress->retries > DUPLICATOR_MAX_BUILD_RETRIES) {
|
42 |
DUP_LOG::trace("c3");
|
classes/utilities/class.u.php
CHANGED
@@ -466,21 +466,43 @@ class DUP_Util
|
|
466 |
return base64_encode($string);
|
467 |
}
|
468 |
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
* @return null Dies if user doesn't have the correct capability
|
473 |
-
*/
|
474 |
-
public static function hasCapability($permission = 'read')
|
475 |
-
{
|
476 |
-
$capability = $permission;
|
477 |
-
$capability = apply_filters('wpfront_user_role_editor_duplicator_translate_capability', $capability);
|
478 |
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
484 |
|
485 |
/**
|
486 |
* Gets the name of the owner of the current PHP script
|
@@ -539,25 +561,20 @@ class DUP_Util
|
|
539 |
//--------------------------------
|
540 |
//CHMOD DIRECTORY ACCESS
|
541 |
//wordpress root directory
|
542 |
-
|
543 |
|
544 |
//snapshot directory
|
545 |
-
|
546 |
-
@chmod($path_ssdir, 0755);
|
547 |
|
548 |
// restore original root perms
|
549 |
-
|
550 |
}
|
551 |
|
552 |
$path_ssdir_tmp = $path_ssdir.'/tmp';
|
553 |
-
|
554 |
-
//snapshot tmp directory
|
555 |
-
@mkdir($path_ssdir_tmp, 0755);
|
556 |
-
@chmod($path_ssdir_tmp, 0755);
|
557 |
-
}
|
558 |
|
559 |
//plugins dir/files
|
560 |
-
|
561 |
|
562 |
//--------------------------------
|
563 |
//FILE CREATION
|
@@ -570,15 +587,6 @@ class DUP_Util
|
|
570 |
@fclose($ssfile);
|
571 |
}
|
572 |
|
573 |
-
//SSDIR: Create token file in snapshot
|
574 |
-
$fileName = $path_ssdir.'/dtoken.php';
|
575 |
-
if (!file_exists($fileName)) {
|
576 |
-
$tokenfile = @fopen($fileName, 'w');
|
577 |
-
@fwrite($tokenfile,
|
578 |
-
'<?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(); ?>');
|
579 |
-
@fclose($tokenfile);
|
580 |
-
}
|
581 |
-
|
582 |
//SSDIR: Create .htaccess
|
583 |
$storage_htaccess_off = DUP_Settings::Get('storage_htaccess_off');
|
584 |
$fileName = $path_ssdir.'/.htaccess';
|
@@ -598,15 +606,6 @@ class DUP_Util
|
|
598 |
@fwrite($robotfile, "User-agent: * \nDisallow: /".DUPLICATOR_SSDIR_NAME.'/');
|
599 |
@fclose($robotfile);
|
600 |
}
|
601 |
-
|
602 |
-
//PLUG DIR: Create token file in plugin
|
603 |
-
$fileName = $path_plugin.'installer/dtoken.php';
|
604 |
-
if (!file_exists($fileName)) {
|
605 |
-
$tokenfile2 = @fopen($fileName, 'w');
|
606 |
-
@fwrite($tokenfile2,
|
607 |
-
'<?php @error_reporting(0); @require_once("../../../../wp-admin/admin.php"); global $wp_query; $wp_query->set_404(); header("HTTP/1.1 404 Not Found", true, 404); header("Status: 404 Not Found"); @include(get_template_directory () . "/404.php"); ?>');
|
608 |
-
@fclose($tokenfile2);
|
609 |
-
}
|
610 |
}
|
611 |
|
612 |
/**
|
466 |
return base64_encode($string);
|
467 |
}
|
468 |
|
469 |
+
const SECURE_ISSUE_DIE = 'die';
|
470 |
+
const SECURE_ISSUE_THROW = 'throw';
|
471 |
+
const SECURE_ISSUE_RETURN = 'return';
|
|
|
|
|
|
|
|
|
|
|
|
|
472 |
|
473 |
+
/**
|
474 |
+
* Does the current user have the capability
|
475 |
+
*
|
476 |
+
* @param type $permission
|
477 |
+
* @param type $exit // SECURE_ISSUE_DIE die script with die function
|
478 |
+
* SECURE_ISSUE_THROW throw an exception if fail
|
479 |
+
* SECURE_ISSUE_RETURN return false if fail
|
480 |
+
*
|
481 |
+
* @return boolean // return false is fail and $exit is SECURE_ISSUE_THROW
|
482 |
+
* // true if success
|
483 |
+
*
|
484 |
+
* @throws Exception // thow exception if $exit is SECURE_ISSUE_THROW
|
485 |
+
*/
|
486 |
+
public static function hasCapability($permission = 'read', $exit = self::SECURE_ISSUE_DIE)
|
487 |
+
{
|
488 |
+
$capability = apply_filters('wpfront_user_role_editor_duplicator_translate_capability', $permission);
|
489 |
+
|
490 |
+
if (!current_user_can($capability)) {
|
491 |
+
$exitMsg = __('You do not have sufficient permissions to access this page.', 'duplicator');
|
492 |
+
DUP_LOG::Trace('You do not have sufficient permissions to access this page. PERMISSION: '.$permission);
|
493 |
+
|
494 |
+
switch ($exit) {
|
495 |
+
case self::SECURE_ISSUE_THROW:
|
496 |
+
throw new Exception($exitMsg);
|
497 |
+
case self::SECURE_ISSUE_RETURN:
|
498 |
+
return false;
|
499 |
+
case self::SECURE_ISSUE_DIE:
|
500 |
+
default:
|
501 |
+
wp_die($exitMsg);
|
502 |
+
}
|
503 |
+
}
|
504 |
+
return true;
|
505 |
+
}
|
506 |
|
507 |
/**
|
508 |
* Gets the name of the owner of the current PHP script
|
561 |
//--------------------------------
|
562 |
//CHMOD DIRECTORY ACCESS
|
563 |
//wordpress root directory
|
564 |
+
DupLiteSnapLibIOU::chmod($path_wproot, 'u+rwx');
|
565 |
|
566 |
//snapshot directory
|
567 |
+
DupLiteSnapLibIOU::dirWriteCheckOrMkdir($path_ssdir, 'u+rwx');
|
|
|
568 |
|
569 |
// restore original root perms
|
570 |
+
DupLiteSnapLibIOU::chmod($path_wproot, $old_root_perm);
|
571 |
}
|
572 |
|
573 |
$path_ssdir_tmp = $path_ssdir.'/tmp';
|
574 |
+
DupLiteSnapLibIOU::dirWriteCheckOrMkdir($path_ssdir_tmp, 'u+rwx');
|
|
|
|
|
|
|
|
|
575 |
|
576 |
//plugins dir/files
|
577 |
+
DupLiteSnapLibIOU::dirWriteCheckOrMkdir($path_plugin.'files', 'u+rwx');
|
578 |
|
579 |
//--------------------------------
|
580 |
//FILE CREATION
|
587 |
@fclose($ssfile);
|
588 |
}
|
589 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
590 |
//SSDIR: Create .htaccess
|
591 |
$storage_htaccess_off = DUP_Settings::Get('storage_htaccess_off');
|
592 |
$fileName = $path_ssdir.'/.htaccess';
|
606 |
@fwrite($robotfile, "User-agent: * \nDisallow: /".DUPLICATOR_SSDIR_NAME.'/');
|
607 |
@fclose($robotfile);
|
608 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
609 |
}
|
610 |
|
611 |
/**
|
ctrls/class.web.services.php
CHANGED
@@ -1,77 +1,82 @@
|
|
1 |
-
<?php
|
2 |
-
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
-
|
4 |
-
class DUP_Web_Services
|
5 |
-
{
|
6 |
-
|
7 |
-
/**
|
8 |
-
* init ajax actions
|
9 |
-
*/
|
10 |
-
public static function init()
|
11 |
-
{
|
12 |
-
add_action('wp_ajax_duplicator_reset_all_settings', array(__CLASS__, 'ajax_reset_all'));
|
13 |
-
}
|
14 |
-
|
15 |
-
/**
|
16 |
-
*
|
17 |
-
* @param
|
18 |
-
*/
|
19 |
-
public static function package_delete_callback($package)
|
20 |
-
{
|
21 |
-
$package->delete();
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* reset all ajax action
|
26 |
-
*
|
27 |
-
* the output must be json
|
28 |
-
*/
|
29 |
-
public static function ajax_reset_all()
|
30 |
-
{
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
|
|
|
|
|
|
|
|
|
|
77 |
}
|
1 |
+
<?php
|
2 |
+
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
+
|
4 |
+
class DUP_Web_Services
|
5 |
+
{
|
6 |
+
|
7 |
+
/**
|
8 |
+
* init ajax actions
|
9 |
+
*/
|
10 |
+
public static function init()
|
11 |
+
{
|
12 |
+
add_action('wp_ajax_duplicator_reset_all_settings', array(__CLASS__, 'ajax_reset_all'));
|
13 |
+
}
|
14 |
+
|
15 |
+
/**
|
16 |
+
*
|
17 |
+
* @param DUP_Package $package
|
18 |
+
*/
|
19 |
+
public static function package_delete_callback($package)
|
20 |
+
{
|
21 |
+
$package->delete();
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* reset all ajax action
|
26 |
+
*
|
27 |
+
* the output must be json
|
28 |
+
*/
|
29 |
+
public static function ajax_reset_all()
|
30 |
+
{
|
31 |
+
ob_start();
|
32 |
+
try {
|
33 |
+
DUP_Handler::init_error_handler();
|
34 |
+
|
35 |
+
if (!check_ajax_referer('duplicator_reset_all_settings', 'nonce', false)) {
|
36 |
+
DUP_LOG::Trace('Security issue');
|
37 |
+
throw new Exception('Security issue');
|
38 |
+
}
|
39 |
+
DUP_Util::hasCapability('export', DUP_Util::SECURE_ISSUE_THROW);
|
40 |
+
|
41 |
+
/** Execute function * */
|
42 |
+
$error = false;
|
43 |
+
$result = array(
|
44 |
+
'data' => array(),
|
45 |
+
'html' => '',
|
46 |
+
'message' => ''
|
47 |
+
);
|
48 |
+
|
49 |
+
$nonce = sanitize_text_field($_POST['nonce']);
|
50 |
+
if (!wp_verify_nonce($nonce, 'duplicator_reset_all_settings')) {
|
51 |
+
DUP_Log::trace('Security issue');
|
52 |
+
throw new Exception('Security issue');
|
53 |
+
}
|
54 |
+
|
55 |
+
DUP_Package::by_status_callback(array(__CLASS__,'package_delete_callback'),array(
|
56 |
+
array('op' => '<', 'status' => DUP_PackageStatus::COMPLETE)
|
57 |
+
));
|
58 |
+
|
59 |
+
/** reset active package id * */
|
60 |
+
DUP_Settings::Set('active_package_id', -1);
|
61 |
+
DUP_Settings::Save();
|
62 |
+
|
63 |
+
/** Clean tmp folder * */
|
64 |
+
DUP_Package::not_active_files_tmp_cleanup();
|
65 |
+
|
66 |
+
//throw new Exception('force error test');
|
67 |
+
} catch (Exception $e) {
|
68 |
+
$error = true;
|
69 |
+
$result['message'] = $e->getMessage();
|
70 |
+
}
|
71 |
+
|
72 |
+
/** Intercept output * */
|
73 |
+
$result['html'] = ob_get_clean();
|
74 |
+
|
75 |
+
/** check error and return json * */
|
76 |
+
if ($error) {
|
77 |
+
wp_send_json_error($result);
|
78 |
+
} else {
|
79 |
+
wp_send_json_success($result);
|
80 |
+
}
|
81 |
+
}
|
82 |
}
|
ctrls/ctrl.package.php
CHANGED
@@ -19,6 +19,8 @@ require_once(DUPLICATOR_PLUGIN_PATH.'/classes/package/duparchive/class.pack.arch
|
|
19 |
*/
|
20 |
function duplicator_package_scan()
|
21 |
{
|
|
|
|
|
22 |
check_ajax_referer('duplicator_package_scan', 'nonce');
|
23 |
DUP_Util::hasCapability('export');
|
24 |
|
@@ -49,6 +51,8 @@ function duplicator_package_scan()
|
|
49 |
*/
|
50 |
function duplicator_package_build()
|
51 |
{
|
|
|
|
|
52 |
check_ajax_referer('duplicator_package_build', 'nonce');
|
53 |
DUP_Util::hasCapability('export');
|
54 |
|
@@ -95,6 +99,8 @@ function duplicator_package_build()
|
|
95 |
*/
|
96 |
function duplicator_duparchive_package_build()
|
97 |
{
|
|
|
|
|
98 |
DUP_LOG::Trace("call to duplicator_duparchive_package_build");
|
99 |
|
100 |
check_ajax_referer('duplicator_duparchive_package_build', 'nonce');
|
@@ -199,6 +205,7 @@ function duplicator_duparchive_package_build()
|
|
199 |
*/
|
200 |
function duplicator_package_delete()
|
201 |
{
|
|
|
202 |
check_ajax_referer('duplicator_package_delete', 'nonce');
|
203 |
DUP_Util::hasCapability('export');
|
204 |
|
@@ -233,27 +240,26 @@ function duplicator_package_delete()
|
|
233 |
$nameHash = "{$row['name']}_{$row['hash']}";
|
234 |
$delResult = $wpdb->query($wpdb->prepare("DELETE FROM `{$tblName}` WHERE id = %d", $id));
|
235 |
if ($delResult != 0) {
|
|
|
|
|
|
|
|
|
|
|
236 |
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
//WP-SNAPSHOT FILES
|
244 |
-
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_archive.daf"));
|
245 |
-
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_archive.zip"));
|
246 |
-
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_database.sql"));
|
247 |
-
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_installer.php"));
|
248 |
-
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_scan.json"));
|
249 |
-
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}_wp-config.txt"));
|
250 |
-
_unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}.log"));
|
251 |
|
252 |
//Unfinished Zip files
|
|
|
253 |
$tmpZip = DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_archive.zip.*";
|
254 |
if ($tmpZip !== false) {
|
255 |
array_map('unlink', glob($tmpZip));
|
256 |
}
|
|
|
257 |
$delCount++;
|
258 |
}
|
259 |
}
|
@@ -280,8 +286,10 @@ function duplicator_package_delete()
|
|
280 |
function duplicator_active_package_info()
|
281 |
{
|
282 |
ob_start();
|
283 |
-
DUP_Util::hasCapability('export');
|
284 |
try {
|
|
|
|
|
|
|
285 |
if (!check_ajax_referer('duplicator_active_package_info', 'nonce', false)) {
|
286 |
throw new Exception(__('An unathorized security request was made to this page. Please try again!','duplicator'));
|
287 |
}
|
@@ -350,6 +358,8 @@ class DUP_CTRL_Package extends DUP_CTRL_Base
|
|
350 |
*/
|
351 |
public function addQuickFilters($post)
|
352 |
{
|
|
|
|
|
353 |
check_ajax_referer('DUP_CTRL_Package_addQuickFilters', 'nonce');
|
354 |
DUP_Util::hasCapability('export');
|
355 |
$post = $this->postParamMerge($post);
|
@@ -404,6 +414,8 @@ class DUP_CTRL_Package extends DUP_CTRL_Base
|
|
404 |
*/
|
405 |
function getPackageFile($post)
|
406 |
{
|
|
|
|
|
407 |
check_ajax_referer('DUP_CTRL_Package_getPackageFile', 'nonce' );
|
408 |
DUP_Util::hasCapability('export');
|
409 |
$params = $this->postParamMerge($post);
|
@@ -501,6 +513,8 @@ class DUP_CTRL_Package extends DUP_CTRL_Base
|
|
501 |
*/
|
502 |
public function getActivePackageStatus($post)
|
503 |
{
|
|
|
|
|
504 |
check_ajax_referer('DUP_CTRL_Package_getActivePackageStatus', 'nonce');
|
505 |
DUP_Util::hasCapability('export');
|
506 |
|
19 |
*/
|
20 |
function duplicator_package_scan()
|
21 |
{
|
22 |
+
DUP_Handler::init_error_handler();
|
23 |
+
|
24 |
check_ajax_referer('duplicator_package_scan', 'nonce');
|
25 |
DUP_Util::hasCapability('export');
|
26 |
|
51 |
*/
|
52 |
function duplicator_package_build()
|
53 |
{
|
54 |
+
DUP_Handler::init_error_handler();
|
55 |
+
|
56 |
check_ajax_referer('duplicator_package_build', 'nonce');
|
57 |
DUP_Util::hasCapability('export');
|
58 |
|
99 |
*/
|
100 |
function duplicator_duparchive_package_build()
|
101 |
{
|
102 |
+
DUP_Handler::init_error_handler();
|
103 |
+
|
104 |
DUP_LOG::Trace("call to duplicator_duparchive_package_build");
|
105 |
|
106 |
check_ajax_referer('duplicator_duparchive_package_build', 'nonce');
|
205 |
*/
|
206 |
function duplicator_package_delete()
|
207 |
{
|
208 |
+
DUP_Handler::init_error_handler();
|
209 |
check_ajax_referer('duplicator_package_delete', 'nonce');
|
210 |
DUP_Util::hasCapability('export');
|
211 |
|
240 |
$nameHash = "{$row['name']}_{$row['hash']}";
|
241 |
$delResult = $wpdb->query($wpdb->prepare("DELETE FROM `{$tblName}` WHERE id = %d", $id));
|
242 |
if ($delResult != 0) {
|
243 |
+
//TMP FILES
|
244 |
+
$globTmpFiles = glob(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}*"));
|
245 |
+
foreach ($globTmpFiles as $globTmpFile) {
|
246 |
+
_unlinkFile($globTmpFile);
|
247 |
+
}
|
248 |
|
249 |
+
//WP-SNAPSHOT FILES
|
250 |
+
$globSnapshotFiles = glob(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}*"));
|
251 |
+
foreach ($globSnapshotFiles as $globSnapshotFile) {
|
252 |
+
_unlinkFile($globSnapshotFile);
|
253 |
+
}
|
254 |
+
// _unlinkFile(DUP_Util::safePath(DUPLICATOR_SSDIR_PATH."/{$nameHash}.log"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
|
256 |
//Unfinished Zip files
|
257 |
+
/*
|
258 |
$tmpZip = DUPLICATOR_SSDIR_PATH_TMP."/{$nameHash}_archive.zip.*";
|
259 |
if ($tmpZip !== false) {
|
260 |
array_map('unlink', glob($tmpZip));
|
261 |
}
|
262 |
+
*/
|
263 |
$delCount++;
|
264 |
}
|
265 |
}
|
286 |
function duplicator_active_package_info()
|
287 |
{
|
288 |
ob_start();
|
|
|
289 |
try {
|
290 |
+
DUP_Handler::init_error_handler();
|
291 |
+
DUP_Util::hasCapability('export', DUP_Util::SECURE_ISSUE_THROW);
|
292 |
+
|
293 |
if (!check_ajax_referer('duplicator_active_package_info', 'nonce', false)) {
|
294 |
throw new Exception(__('An unathorized security request was made to this page. Please try again!','duplicator'));
|
295 |
}
|
358 |
*/
|
359 |
public function addQuickFilters($post)
|
360 |
{
|
361 |
+
DUP_Handler::init_error_handler();
|
362 |
+
|
363 |
check_ajax_referer('DUP_CTRL_Package_addQuickFilters', 'nonce');
|
364 |
DUP_Util::hasCapability('export');
|
365 |
$post = $this->postParamMerge($post);
|
414 |
*/
|
415 |
function getPackageFile($post)
|
416 |
{
|
417 |
+
DUP_Handler::init_error_handler();
|
418 |
+
|
419 |
check_ajax_referer('DUP_CTRL_Package_getPackageFile', 'nonce' );
|
420 |
DUP_Util::hasCapability('export');
|
421 |
$params = $this->postParamMerge($post);
|
513 |
*/
|
514 |
public function getActivePackageStatus($post)
|
515 |
{
|
516 |
+
DUP_Handler::init_error_handler();
|
517 |
+
|
518 |
check_ajax_referer('DUP_CTRL_Package_getActivePackageStatus', 'nonce');
|
519 |
DUP_Util::hasCapability('export');
|
520 |
|
ctrls/ctrl.tools.php
CHANGED
@@ -31,6 +31,8 @@ class DUP_CTRL_Tools extends DUP_CTRL_Base
|
|
31 |
*/
|
32 |
public function runScanValidator($post)
|
33 |
{
|
|
|
|
|
34 |
check_ajax_referer('DUP_CTRL_Tools_runScanValidator', 'nonce');
|
35 |
DUP_Util::hasCapability('export');
|
36 |
|
31 |
*/
|
32 |
public function runScanValidator($post)
|
33 |
{
|
34 |
+
DUP_Handler::init_error_handler();
|
35 |
+
|
36 |
check_ajax_referer('DUP_CTRL_Tools_runScanValidator', 'nonce');
|
37 |
DUP_Util::hasCapability('export');
|
38 |
|
ctrls/ctrl.ui.php
CHANGED
@@ -39,6 +39,7 @@ class DUP_CTRL_UI extends DUP_CTRL_Base
|
|
39 |
*/
|
40 |
public function SaveViewState($post)
|
41 |
{
|
|
|
42 |
check_ajax_referer('DUP_CTRL_UI_SaveViewState', 'nonce');
|
43 |
DUP_Util::hasCapability('export');
|
44 |
|
39 |
*/
|
40 |
public function SaveViewState($post)
|
41 |
{
|
42 |
+
DUP_Handler::init_error_handler();
|
43 |
check_ajax_referer('DUP_CTRL_UI_SaveViewState', 'nonce');
|
44 |
DUP_Util::hasCapability('export');
|
45 |
|
deactivation.php
CHANGED
@@ -86,12 +86,14 @@ if (!function_exists('duplicator_add_deactivation_feedback_dialog_box')) {
|
|
86 |
'input_type' => '',
|
87 |
'input_placeholder' => ''
|
88 |
),
|
|
|
89 |
array(
|
90 |
'id' => 'OTHER',
|
91 |
'text' => __('Other', 'duplicator'),
|
92 |
'input_type' => 'textarea',
|
93 |
'input_placeholder' => __('Please tell us the reason so we can improve it.', 'duplicator')
|
94 |
)
|
|
|
95 |
);
|
96 |
|
97 |
$reasons_list_items_html = '';
|
@@ -356,6 +358,8 @@ if (!function_exists('duplicator_submit_uninstall_reason_action')) {
|
|
356 |
|
357 |
function duplicator_submit_uninstall_reason_action()
|
358 |
{
|
|
|
|
|
359 |
if (!wp_verify_nonce($_REQUEST['duplicator_ajax_nonce'], 'duplicator_ajax_nonce')) {
|
360 |
wp_die('Security issue');
|
361 |
}
|
86 |
'input_type' => '',
|
87 |
'input_placeholder' => ''
|
88 |
),
|
89 |
+
/*
|
90 |
array(
|
91 |
'id' => 'OTHER',
|
92 |
'text' => __('Other', 'duplicator'),
|
93 |
'input_type' => 'textarea',
|
94 |
'input_placeholder' => __('Please tell us the reason so we can improve it.', 'duplicator')
|
95 |
)
|
96 |
+
*/
|
97 |
);
|
98 |
|
99 |
$reasons_list_items_html = '';
|
358 |
|
359 |
function duplicator_submit_uninstall_reason_action()
|
360 |
{
|
361 |
+
DUP_Handler::init_error_handler();
|
362 |
+
|
363 |
if (!wp_verify_nonce($_REQUEST['duplicator_ajax_nonce'], 'duplicator_ajax_nonce')) {
|
364 |
wp_die('Security issue');
|
365 |
}
|
define.php
CHANGED
@@ -4,8 +4,8 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
4 |
//Prevent directly browsing to the file
|
5 |
if (function_exists('plugin_dir_url'))
|
6 |
{
|
7 |
-
define('DUPLICATOR_VERSION', '1.3.
|
8 |
-
define('DUPLICATOR_VERSION_BUILD', '2019-
|
9 |
define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
|
10 |
define('DUPLICATOR_SITE_URL', get_site_url());
|
11 |
|
@@ -56,6 +56,7 @@ if (function_exists('plugin_dir_url'))
|
|
56 |
define('DUPLICATOR_WEBCONFIG_ORIG_FILENAME', 'web.config.orig');
|
57 |
define("DUPLICATOR_INSTALLER_DIRECTORY", DUPLICATOR_WPROOTPATH . 'dup-installer');
|
58 |
define('DUPLICATOR_MAX_LOG_SIZE', 400000); // The higher this is the more overhead
|
|
|
59 |
|
60 |
$GLOBALS['DUPLICATOR_SERVER_LIST'] = array('Apache','LiteSpeed', 'Nginx', 'Lighttpd', 'IIS', 'WebServerX', 'uWSGI');
|
61 |
$GLOBALS['DUPLICATOR_OPTS_DELETE'] = array('duplicator_ui_view_state', 'duplicator_package_active', 'duplicator_settings');
|
4 |
//Prevent directly browsing to the file
|
5 |
if (function_exists('plugin_dir_url'))
|
6 |
{
|
7 |
+
define('DUPLICATOR_VERSION', '1.3.16');
|
8 |
+
define('DUPLICATOR_VERSION_BUILD', '2019-07-07_14:00');
|
9 |
define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
|
10 |
define('DUPLICATOR_SITE_URL', get_site_url());
|
11 |
|
56 |
define('DUPLICATOR_WEBCONFIG_ORIG_FILENAME', 'web.config.orig');
|
57 |
define("DUPLICATOR_INSTALLER_DIRECTORY", DUPLICATOR_WPROOTPATH . 'dup-installer');
|
58 |
define('DUPLICATOR_MAX_LOG_SIZE', 400000); // The higher this is the more overhead
|
59 |
+
define('DUPLICATOR_ZIP_ARCHIVE_ADD_FROM_STR', false);
|
60 |
|
61 |
$GLOBALS['DUPLICATOR_SERVER_LIST'] = array('Apache','LiteSpeed', 'Nginx', 'Lighttpd', 'IIS', 'WebServerX', 'uWSGI');
|
62 |
$GLOBALS['DUPLICATOR_OPTS_DELETE'] = array('duplicator_ui_view_state', 'duplicator_package_active', 'duplicator_settings');
|
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.3.
|
7 |
Author: Snap Creek
|
8 |
Author URI: http://www.snapcreek.com/duplicator/
|
9 |
Text Domain: duplicator
|
@@ -158,6 +158,19 @@ if (is_admin() == true)
|
|
158 |
require_once 'deactivation.php';
|
159 |
require_once 'lib/snaplib/snaplib.all.php';
|
160 |
require_once 'classes/class.constants.php';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
161 |
require_once 'classes/class.settings.php';
|
162 |
require_once 'classes/class.logging.php';
|
163 |
require_once 'classes/utilities/class.u.php';
|
@@ -168,7 +181,7 @@ if (is_admin() == true)
|
|
168 |
require_once 'classes/ui/class.ui.viewstate.php';
|
169 |
require_once 'classes/ui/class.ui.notice.php';
|
170 |
require_once 'classes/package/class.pack.php';
|
171 |
-
|
172 |
|
173 |
//Controllers
|
174 |
require_once 'ctrls/ctrl.package.php';
|
@@ -206,7 +219,7 @@ if (is_admin() == true)
|
|
206 |
status INT(11) NOT NULL,
|
207 |
created DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
|
208 |
owner VARCHAR(60) NOT NULL,
|
209 |
-
package
|
210 |
PRIMARY KEY (id),
|
211 |
KEY hash (hash))";
|
212 |
|
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.3.16
|
7 |
Author: Snap Creek
|
8 |
Author URI: http://www.snapcreek.com/duplicator/
|
9 |
Text Domain: duplicator
|
158 |
require_once 'deactivation.php';
|
159 |
require_once 'lib/snaplib/snaplib.all.php';
|
160 |
require_once 'classes/class.constants.php';
|
161 |
+
$isWPEngineHost = apply_filters('duplicator_wp_engine_host_check', file_exists(WPMU_PLUGIN_DIR.'/wpengine-common/mu-plugin.php'));
|
162 |
+
if ($isWPEngineHost) {
|
163 |
+
require_once 'classes/host/class.wpengine.host.php';
|
164 |
+
}
|
165 |
+
|
166 |
+
$hostName = gethostname();
|
167 |
+
$goDaddyHostNameSuffix = '.secureserver.net';
|
168 |
+
$lenGoDaddyHostNameSuffix = strlen($goDaddyHostNameSuffix);
|
169 |
+
$isGoDaddyHost = apply_filters('duplicator_godaddy_host_check', (false !== $hostName && substr($hostName, - $lenGoDaddyHostNameSuffix) === $goDaddyHostNameSuffix));
|
170 |
+
if ($isGoDaddyHost) {
|
171 |
+
require_once 'classes/host/class.godaddy.host.php';
|
172 |
+
}
|
173 |
+
|
174 |
require_once 'classes/class.settings.php';
|
175 |
require_once 'classes/class.logging.php';
|
176 |
require_once 'classes/utilities/class.u.php';
|
181 |
require_once 'classes/ui/class.ui.viewstate.php';
|
182 |
require_once 'classes/ui/class.ui.notice.php';
|
183 |
require_once 'classes/package/class.pack.php';
|
184 |
+
require_once 'views/packages/screen.php';
|
185 |
|
186 |
//Controllers
|
187 |
require_once 'ctrls/ctrl.package.php';
|
219 |
status INT(11) NOT NULL,
|
220 |
created DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
|
221 |
owner VARCHAR(60) NOT NULL,
|
222 |
+
package LONGTEXT NOT NULL,
|
223 |
PRIMARY KEY (id),
|
224 |
KEY hash (hash))";
|
225 |
|
installer/dup-installer/assets/inc.css.php
CHANGED
@@ -44,9 +44,10 @@
|
|
44 |
select option {
|
45 |
padding: 2px 5px;
|
46 |
}
|
47 |
-
select option
|
48 |
text-decoration: line-through;
|
49 |
cursor: not-allowed;
|
|
|
50 |
}
|
51 |
|
52 |
select:disabled {background:#EBEBE4}
|
@@ -400,23 +401,30 @@
|
|
400 |
pre.s4-diff-viewer {line-height:11px}
|
401 |
div#s4-notice-reports div.section-content div.title {cursor:pointer}
|
402 |
|
403 |
-
|
404 |
-
|
405 |
-
|
|
|
|
|
|
|
|
|
406 |
div.help-target {float:right;}
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
div#main-help {font-size:13px; line-height:17px}
|
413 |
-
|
414 |
div#main-help span.step {color:#DB4B38}
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
|
|
|
|
|
|
420 |
|
421 |
#main-help section {
|
422 |
border: 1px solid silver;
|
44 |
select option {
|
45 |
padding: 2px 5px;
|
46 |
}
|
47 |
+
select option:disabled {
|
48 |
text-decoration: line-through;
|
49 |
cursor: not-allowed;
|
50 |
+
color: #A9A9A9;
|
51 |
}
|
52 |
|
53 |
select:disabled {background:#EBEBE4}
|
401 |
pre.s4-diff-viewer {line-height:11px}
|
402 |
div#s4-notice-reports div.section-content div.title {cursor:pointer}
|
403 |
|
404 |
+
/* ============================
|
405 |
+
STEP 5 HELP
|
406 |
+
============================ */
|
407 |
+
#body-help div#content {
|
408 |
+
width: 100%;
|
409 |
+
max-width: 1024px;
|
410 |
+
}
|
411 |
div.help-target {float:right;}
|
412 |
+
div.help-target a {float:right; font-size:16px; color:#13659C}
|
413 |
+
div#main-help sup {font-size:11px; font-weight:normal; font-style:italic; color:blue}
|
414 |
+
div.help-online {text-align:center; font-size:18px; padding:10px 0 0 0; line-height:24px}
|
415 |
+
div.help {color:#555; font-style:italic; font-size:11px; padding:4px; border-top:1px solid #dfdfdf}
|
416 |
+
div.help-page fieldset {margin-bottom:25px}
|
417 |
div#main-help {font-size:13px; line-height:17px}
|
418 |
+
div#main-help h3 {border-bottom:1px solid silver; padding:8px; margin:4px 0 8px 0; font-size:20px}
|
419 |
div#main-help span.step {color:#DB4B38}
|
420 |
+
.help-opt {width: 100%; border: none; border-collapse: collapse; margin:5px 0 0 0;}
|
421 |
+
.help-opt .col-opt {
|
422 |
+
width: 250px;
|
423 |
+
}
|
424 |
+
.help-opt td.section {background-color:#dfdfdf;}
|
425 |
+
.help-opt td, .help-opt th {padding:15px 10px; border:1px solid silver;}
|
426 |
+
.help-opt td:first-child {font-weight:bold; padding-right:10px; white-space:nowrap}
|
427 |
+
.help-opt th {background: #333; color: #fff;border:1px solid #333 }
|
428 |
|
429 |
#main-help section {
|
430 |
border: 1px solid silver;
|
installer/dup-installer/assets/inc.libs.js.php
CHANGED
@@ -166,7 +166,6 @@ for(var c=0;c<f.length;c++){var e=true;for(var b=0;b<a&&(b+c+a)<f.length;b++){e=
|
|
166 |
*/
|
167 |
function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t<e.length;t++)i[t]=e[t];return i}return Array.from(e)}var _slice=Array.prototype.slice;!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],t):e.parsley=t(e.jQuery)}(this,function(e){"use strict";function t(e,t){return e.parsleyAdaptedCallback||(e.parsleyAdaptedCallback=function(){var i=Array.prototype.slice.call(arguments,0);i.unshift(this),e.apply(t||A,i)}),e.parsleyAdaptedCallback}function i(e){return 0===e.lastIndexOf(D,0)?e.substr(D.length):e}var n=1,r={},s={attr:function(e,t,i){var n,r,s,a=new RegExp("^"+t,"i");if("undefined"==typeof i)i={};else for(n in i)i.hasOwnProperty(n)&&delete i[n];if("undefined"==typeof e||"undefined"==typeof e[0])return i;for(s=e[0].attributes,n=s.length;n--;)r=s[n],r&&r.specified&&a.test(r.name)&&(i[this.camelize(r.name.slice(t.length))]=this.deserializeValue(r.value));return i},checkAttr:function(e,t,i){return e.is("["+t+i+"]")},setAttr:function(e,t,i,n){e[0].setAttribute(this.dasherize(t+i),String(n))},generateID:function(){return""+n++},deserializeValue:function(t){var i;try{return t?"true"==t||("false"==t?!1:"null"==t?null:isNaN(i=Number(t))?/^[\[\{]/.test(t)?e.parseJSON(t):t:i):t}catch(n){return t}},camelize:function(e){return e.replace(/-+(.)?/g,function(e,t){return t?t.toUpperCase():""})},dasherize:function(e){return e.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()},warn:function(){var e;window.console&&"function"==typeof window.console.warn&&(e=window.console).warn.apply(e,arguments)},warnOnce:function(e){r[e]||(r[e]=!0,this.warn.apply(this,arguments))},_resetWarnings:function(){r={}},trimString:function(e){return e.replace(/^\s+|\s+$/g,"")},namespaceEvents:function(t,i){return t=this.trimString(t||"").split(/\s+/),t[0]?e.map(t,function(e){return e+"."+i}).join(" "):""},objectCreate:Object.create||function(){var e=function(){};return function(t){if(arguments.length>1)throw Error("Second argument not supported");if("object"!=typeof t)throw TypeError("Argument must be an object");e.prototype=t;var i=new e;return e.prototype=null,i}}()},a=s,o={namespace:"data-parsley-",inputs:"input, textarea, select",excluded:"input[type=button], input[type=submit], input[type=reset], input[type=hidden]",priorityEnabled:!0,multiple:null,group:null,uiEnabled:!0,validationThreshold:3,focus:"first",trigger:!1,triggerAfterFailure:"input",errorClass:"parsley-error",successClass:"parsley-success",classHandler:function(e){},errorsContainer:function(e){},errorsWrapper:'<ul class="parsley-errors-list"></ul>',errorTemplate:"<li></li>"},l=function(){};l.prototype={asyncSupport:!0,actualizeOptions:function(){return a.attr(this.$element,this.options.namespace,this.domOptions),this.parent&&this.parent.actualizeOptions&&this.parent.actualizeOptions(),this},_resetOptions:function(e){this.domOptions=a.objectCreate(this.parent.options),this.options=a.objectCreate(this.domOptions);for(var t in e)e.hasOwnProperty(t)&&(this.options[t]=e[t]);this.actualizeOptions()},_listeners:null,on:function(e,t){this._listeners=this._listeners||{};var i=this._listeners[e]=this._listeners[e]||[];return i.push(t),this},subscribe:function(t,i){e.listenTo(this,t.toLowerCase(),i)},off:function(e,t){var i=this._listeners&&this._listeners[e];if(i)if(t)for(var n=i.length;n--;)i[n]===t&&i.splice(n,1);else delete this._listeners[e];return this},unsubscribe:function(t,i){e.unsubscribeTo(this,t.toLowerCase())},trigger:function(e,t,i){t=t||this;var n,r=this._listeners&&this._listeners[e];if(r)for(var s=r.length;s--;)if(n=r[s].call(t,t,i),n===!1)return n;return this.parent?this.parent.trigger(e,t,i):!0},reset:function(){if("ParsleyForm"!==this.__class__)return this._resetUI(),this._trigger("reset");for(var e=0;e<this.fields.length;e++)this.fields[e].reset();this._trigger("reset")},destroy:function(){if(this._destroyUI(),"ParsleyForm"!==this.__class__)return this.$element.removeData("Parsley"),this.$element.removeData("ParsleyFieldMultiple"),void this._trigger("destroy");for(var e=0;e<this.fields.length;e++)this.fields[e].destroy();this.$element.removeData("Parsley"),this._trigger("destroy")},asyncIsValid:function(e,t){return a.warnOnce("asyncIsValid is deprecated; please use whenValid instead"),this.whenValid({group:e,force:t})},_findRelated:function(){return this.options.multiple?this.parent.$element.find("["+this.options.namespace+'multiple="'+this.options.multiple+'"]'):this.$element}};var u={string:function(e){return e},integer:function(e){if(isNaN(e))throw'Requirement is not an integer: "'+e+'"';return parseInt(e,10)},number:function(e){if(isNaN(e))throw'Requirement is not a number: "'+e+'"';return parseFloat(e)},reference:function(t){var i=e(t);if(0===i.length)throw'No such reference: "'+t+'"';return i},"boolean":function(e){return"false"!==e},object:function(e){return a.deserializeValue(e)},regexp:function(e){var t="";return/^\/.*\/(?:[gimy]*)$/.test(e)?(t=e.replace(/.*\/([gimy]*)$/,"$1"),e=e.replace(new RegExp("^/(.*?)/"+t+"$"),"$1")):e="^"+e+"$",new RegExp(e,t)}},d=function(e,t){var i=e.match(/^\s*\[(.*)\]\s*$/);if(!i)throw'Requirement is not an array: "'+e+'"';var n=i[1].split(",").map(a.trimString);if(n.length!==t)throw"Requirement has "+n.length+" values when "+t+" are needed";return n},h=function(e,t){var i=u[e||"string"];if(!i)throw'Unknown requirement specification: "'+e+'"';return i(t)},p=function(e,t,i){var n=null,r={};for(var s in e)if(s){var a=i(s);"string"==typeof a&&(a=h(e[s],a)),r[s]=a}else n=h(e[s],t);return[n,r]},f=function(t){e.extend(!0,this,t)};f.prototype={validate:function(t,i){if(this.fn)return arguments.length>3&&(i=[].slice.call(arguments,1,-1)),this.fn.call(this,t,i);if(e.isArray(t)){if(!this.validateMultiple)throw"Validator `"+this.name+"` does not handle multiple values";return this.validateMultiple.apply(this,arguments)}if(this.validateNumber)return isNaN(t)?!1:(arguments[0]=parseFloat(arguments[0]),this.validateNumber.apply(this,arguments));if(this.validateString)return this.validateString.apply(this,arguments);throw"Validator `"+this.name+"` only handles multiple values"},parseRequirements:function(t,i){if("string"!=typeof t)return e.isArray(t)?t:[t];var n=this.requirementType;if(e.isArray(n)){for(var r=d(t,n.length),s=0;s<r.length;s++)r[s]=h(n[s],r[s]);return r}return e.isPlainObject(n)?p(n,t,i):[h(n,t)]},requirementType:"string",priority:2};var c=function(e,t){this.__class__="ParsleyValidatorRegistry",this.locale="en",this.init(e||{},t||{})},m={email:/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,number:/^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,integer:/^-?\d+$/,digits:/^\d+$/,alphanum:/^\w+$/i,url:new RegExp("^(?:(?:https?|ftp)://)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/\\S*)?$","i")};m.range=m.number;var g=function(e){var t=(""+e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0};c.prototype={init:function(t,i){this.catalog=i,this.validators=e.extend({},this.validators);for(var n in t)this.addValidator(n,t[n].fn,t[n].priority);window.Parsley.trigger("parsley:validator:init")},setLocale:function(e){if("undefined"==typeof this.catalog[e])throw new Error(e+" is not available in the catalog");return this.locale=e,this},addCatalog:function(e,t,i){return"object"==typeof t&&(this.catalog[e]=t),!0===i?this.setLocale(e):this},addMessage:function(e,t,i){return"undefined"==typeof this.catalog[e]&&(this.catalog[e]={}),this.catalog[e][t]=i,this},addMessages:function(e,t){for(var i in t)this.addMessage(e,i,t[i]);return this},addValidator:function(e,t,i){if(this.validators[e])a.warn('Validator "'+e+'" is already defined.');else if(o.hasOwnProperty(e))return void a.warn('"'+e+'" is a restricted keyword and is not a valid validator name.');return this._setValidator.apply(this,arguments)},updateValidator:function(e,t,i){return this.validators[e]?this._setValidator(this,arguments):(a.warn('Validator "'+e+'" is not already defined.'),this.addValidator.apply(this,arguments))},removeValidator:function(e){return this.validators[e]||a.warn('Validator "'+e+'" is not defined.'),delete this.validators[e],this},_setValidator:function(e,t,i){"object"!=typeof t&&(t={fn:t,priority:i}),t.validate||(t=new f(t)),this.validators[e]=t;for(var n in t.messages||{})this.addMessage(n,e,t.messages[n]);return this},getErrorMessage:function(e){var t;if("type"===e.name){var i=this.catalog[this.locale][e.name]||{};t=i[e.requirements]}else t=this.formatMessage(this.catalog[this.locale][e.name],e.requirements);return t||this.catalog[this.locale].defaultMessage||this.catalog.en.defaultMessage},formatMessage:function(e,t){if("object"==typeof t){for(var i in t)e=this.formatMessage(e,t[i]);return e}return"string"==typeof e?e.replace(/%s/i,t):""},validators:{notblank:{validateString:function(e){return/\S/.test(e)},priority:2},required:{validateMultiple:function(e){return e.length>0},validateString:function(e){return/\S/.test(e)},priority:512},type:{validateString:function(e,t){var i=arguments.length<=2||void 0===arguments[2]?{}:arguments[2],n=i.step,r=void 0===n?"1":n,s=i.base,a=void 0===s?0:s,o=m[t];if(!o)throw new Error("validator type `"+t+"` is not supported");if(!o.test(e))return!1;if("number"===t&&!/^any$/i.test(r||"")){var l=Number(e),u=Math.max(g(r),g(a));if(g(l)>u)return!1;var d=function(e){return Math.round(e*Math.pow(10,u))};if((d(l)-d(a))%d(r)!=0)return!1}return!0},requirementType:{"":"string",step:"string",base:"number"},priority:256},pattern:{validateString:function(e,t){return t.test(e)},requirementType:"regexp",priority:64},minlength:{validateString:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxlength:{validateString:function(e,t){return e.length<=t},requirementType:"integer",priority:30},length:{validateString:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},mincheck:{validateMultiple:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxcheck:{validateMultiple:function(e,t){return e.length<=t},requirementType:"integer",priority:30},check:{validateMultiple:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},min:{validateNumber:function(e,t){return e>=t},requirementType:"number",priority:30},max:{validateNumber:function(e,t){return t>=e},requirementType:"number",priority:30},range:{validateNumber:function(e,t,i){return e>=t&&i>=e},requirementType:["number","number"],priority:30},equalto:{validateString:function(t,i){var n=e(i);return n.length?t===n.val():t===i},priority:256}}};var y={},v=function T(e,t,i){for(var n=[],r=[],s=0;s<e.length;s++){for(var a=!1,o=0;o<t.length;o++)if(e[s].assert.name===t[o].assert.name){a=!0;break}a?r.push(e[s]):n.push(e[s])}return{kept:r,added:n,removed:i?[]:T(t,e,!0).added}};y.Form={_actualizeTriggers:function(){var e=this;this.$element.on("submit.Parsley",function(t){e.onSubmitValidate(t)}),this.$element.on("click.Parsley",'input[type="submit"], button[type="submit"]',function(t){e.onSubmitButton(t)}),!1!==this.options.uiEnabled&&this.$element.attr("novalidate","")},focus:function(){if(this._focusedField=null,!0===this.validationResult||"none"===this.options.focus)return null;for(var e=0;e<this.fields.length;e++){var t=this.fields[e];if(!0!==t.validationResult&&t.validationResult.length>0&&"undefined"==typeof t.options.noFocus&&(this._focusedField=t.$element,"first"===this.options.focus))break}return null===this._focusedField?null:this._focusedField.focus()},_destroyUI:function(){this.$element.off(".Parsley")}},y.Field={_reflowUI:function(){if(this._buildUI(),this._ui){var e=v(this.validationResult,this._ui.lastValidationResult);this._ui.lastValidationResult=this.validationResult,this._manageStatusClass(),this._manageErrorsMessages(e),this._actualizeTriggers(),!e.kept.length&&!e.added.length||this._failedOnce||(this._failedOnce=!0,this._actualizeTriggers())}},getErrorsMessages:function(){if(!0===this.validationResult)return[];for(var e=[],t=0;t<this.validationResult.length;t++)e.push(this.validationResult[t].errorMessage||this._getErrorMessage(this.validationResult[t].assert));return e},addError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r?!0:r;this._buildUI(),this._addError(e,{message:i,assert:n}),s&&this._errorClass()},updateError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r?!0:r;this._buildUI(),this._updateError(e,{message:i,assert:n}),s&&this._errorClass()},removeError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.updateClass,n=void 0===i?!0:i;this._buildUI(),this._removeError(e),n&&this._manageStatusClass()},_manageStatusClass:function(){this.hasConstraints()&&this.needsValidation()&&!0===this.validationResult?this._successClass():this.validationResult.length>0?this._errorClass():this._resetClass()},_manageErrorsMessages:function(t){if("undefined"==typeof this.options.errorsMessagesDisabled){if("undefined"!=typeof this.options.errorMessage)return t.added.length||t.kept.length?(this._insertErrorWrapper(),0===this._ui.$errorsWrapper.find(".parsley-custom-error-message").length&&this._ui.$errorsWrapper.append(e(this.options.errorTemplate).addClass("parsley-custom-error-message")),this._ui.$errorsWrapper.addClass("filled").find(".parsley-custom-error-message").html(this.options.errorMessage)):this._ui.$errorsWrapper.removeClass("filled").find(".parsley-custom-error-message").remove();for(var i=0;i<t.removed.length;i++)this._removeError(t.removed[i].assert.name);for(i=0;i<t.added.length;i++)this._addError(t.added[i].assert.name,{message:t.added[i].errorMessage,assert:t.added[i].assert});for(i=0;i<t.kept.length;i++)this._updateError(t.kept[i].assert.name,{message:t.kept[i].errorMessage,assert:t.kept[i].assert})}},_addError:function(t,i){var n=i.message,r=i.assert;this._insertErrorWrapper(),this._ui.$errorsWrapper.addClass("filled").append(e(this.options.errorTemplate).addClass("parsley-"+t).html(n||this._getErrorMessage(r)))},_updateError:function(e,t){var i=t.message,n=t.assert;this._ui.$errorsWrapper.addClass("filled").find(".parsley-"+e).html(i||this._getErrorMessage(n))},_removeError:function(e){this._ui.$errorsWrapper.removeClass("filled").find(".parsley-"+e).remove()},_getErrorMessage:function(e){var t=e.name+"Message";return"undefined"!=typeof this.options[t]?window.Parsley.formatMessage(this.options[t],e.requirements):window.Parsley.getErrorMessage(e)},_buildUI:function(){if(!this._ui&&!1!==this.options.uiEnabled){var t={};this.$element.attr(this.options.namespace+"id",this.__id__),t.$errorClassHandler=this._manageClassHandler(),t.errorsWrapperId="parsley-id-"+(this.options.multiple?"multiple-"+this.options.multiple:this.__id__),t.$errorsWrapper=e(this.options.errorsWrapper).attr("id",t.errorsWrapperId),t.lastValidationResult=[],t.validationInformationVisible=!1,this._ui=t}},_manageClassHandler:function(){if("string"==typeof this.options.classHandler&&e(this.options.classHandler).length)return e(this.options.classHandler);var t=this.options.classHandler.call(this,this);return"undefined"!=typeof t&&t.length?t:!this.options.multiple||this.$element.is("select")?this.$element:this.$element.parent()},_insertErrorWrapper:function(){var t;if(0!==this._ui.$errorsWrapper.parent().length)return this._ui.$errorsWrapper.parent();if("string"==typeof this.options.errorsContainer){if(e(this.options.errorsContainer).length)return e(this.options.errorsContainer).append(this._ui.$errorsWrapper);a.warn("The errors container `"+this.options.errorsContainer+"` does not exist in DOM")}else"function"==typeof this.options.errorsContainer&&(t=this.options.errorsContainer.call(this,this));if("undefined"!=typeof t&&t.length)return t.append(this._ui.$errorsWrapper);var i=this.$element;return this.options.multiple&&(i=i.parent()),i.after(this._ui.$errorsWrapper)},_actualizeTriggers:function(){var e=this,t=this._findRelated();t.off(".Parsley"),this._failedOnce?t.on(a.namespaceEvents(this.options.triggerAfterFailure,"Parsley"),function(){e.validate()}):t.on(a.namespaceEvents(this.options.trigger,"Parsley"),function(t){e._eventValidate(t)})},_eventValidate:function(e){(!/key|input/.test(e.type)||this._ui&&this._ui.validationInformationVisible||!(this.getValue().length<=this.options.validationThreshold))&&this.validate()},_resetUI:function(){this._failedOnce=!1,this._actualizeTriggers(),"undefined"!=typeof this._ui&&(this._ui.$errorsWrapper.removeClass("filled").children().remove(),this._resetClass(),this._ui.lastValidationResult=[],this._ui.validationInformationVisible=!1)},_destroyUI:function(){this._resetUI(),"undefined"!=typeof this._ui&&this._ui.$errorsWrapper.remove(),delete this._ui},_successClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass)},_errorClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass)},_resetClass:function(){this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass)}};var _=function(t,i,n){this.__class__="ParsleyForm",this.__id__=a.generateID(),this.$element=e(t),this.domOptions=i,this.options=n,this.parent=window.Parsley,this.fields=[],this.validationResult=null},w={pending:null,resolved:!0,rejected:!1};_.prototype={onSubmitValidate:function(e){var t=this;if(!0!==e.parsley){var i=this._$submitSource||this.$element.find('input[type="submit"], button[type="submit"]').first();if(this._$submitSource=null,this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!0),!i.is("[formnovalidate]")){var n=this.whenValidate({event:e});"resolved"===n.state()&&!1!==this._trigger("submit")||(e.stopImmediatePropagation(),e.preventDefault(),"pending"===n.state()&&n.done(function(){t._submit(i)}))}}},onSubmitButton:function(t){this._$submitSource=e(t.target)},_submit:function(t){if(!1!==this._trigger("submit")){if(t){var i=this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!1);0===i.length&&(i=e('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element)),i.attr({name:t.attr("name"),value:t.attr("value")})}this.$element.trigger(e.extend(e.Event("submit"),{parsley:!0}))}},validate:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling validate on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1],s=i[2];t={group:n,force:r,event:s}}return w[this.whenValidate(t).state()]},whenValidate:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force,s=i.event;this.submitEvent=s,s&&(this.submitEvent=e.extend({},s,{preventDefault:function(){a.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`"),t.validationResult=!1}})),this.validationResult=!0,this._trigger("validate"),this._refreshFields();var o=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValidate({force:r,group:n})})}),l=function(){var i=e.Deferred();return!1===t.validationResult&&i.reject(),i.resolve().promise()};return e.when.apply(e,_toConsumableArray(o)).done(function(){t._trigger("success")}).fail(function(){t.validationResult=!1,t.focus(),t._trigger("error")}).always(function(){t._trigger("validated")}).pipe(l,l)},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={group:n,force:r}}return w[this.whenValid(t).state()]},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force;this._refreshFields();var s=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValid({group:n,force:r})})});return e.when.apply(e,_toConsumableArray(s))},_refreshFields:function(){return this.actualizeOptions()._bindFields()},_bindFields:function(){var t=this,i=this.fields;return this.fields=[],this.fieldsMappedById={},this._withoutReactualizingFormOptions(function(){t.$element.find(t.options.inputs).not(t.options.excluded).each(function(e,i){var n=new window.Parsley.Factory(i,{},t);"ParsleyField"!==n.__class__&&"ParsleyFieldMultiple"!==n.__class__||!0===n.options.excluded||"undefined"==typeof t.fieldsMappedById[n.__class__+"-"+n.__id__]&&(t.fieldsMappedById[n.__class__+"-"+n.__id__]=n,t.fields.push(n))}),e(i).not(t.fields).each(function(e,t){t._trigger("reset")})}),this},_withoutReactualizingFormOptions:function(e){var t=this.actualizeOptions;this.actualizeOptions=function(){return this};var i=e();return this.actualizeOptions=t,i},_trigger:function(e){return this.trigger("form:"+e)}};var b=function(t,i,n,r,s){if(!/ParsleyField/.test(t.__class__))throw new Error("ParsleyField or ParsleyFieldMultiple instance expected");var a=window.Parsley._validatorRegistry.validators[i],o=new f(a);e.extend(this,{validator:o,name:i,requirements:n,priority:r||t.options[i+"Priority"]||o.priority,isDomConstraint:!0===s}),this._parseRequirements(t.options)},F=function(e){var t=e[0].toUpperCase();return t+e.slice(1)};b.prototype={validate:function(e,t){var i=this.requirementList.slice(0);return i.unshift(e),i.push(t),this.validator.validate.apply(this.validator,i)},_parseRequirements:function(e){var t=this;this.requirementList=this.validator.parseRequirements(this.requirements,function(i){return e[t.name+F(i)]})}};var C=function(t,i,n,r){this.__class__="ParsleyField",this.__id__=a.generateID(),this.$element=e(t),"undefined"!=typeof r&&(this.parent=r),this.options=n,this.domOptions=i,this.constraints=[],this.constraintsByName={},this.validationResult=[],this._bindConstraints()},$={pending:null,resolved:!0,rejected:!1};C.prototype={validate:function(t){arguments.length>=1&&!e.isPlainObject(t)&&(a.warnOnce("Calling validate on a parsley field without passing arguments as an object is deprecated."),t={options:t});var i=this.whenValidate(t);if(!i)return!0;switch(i.state()){case"pending":return null;case"resolved":return!0;case"rejected":return this.validationResult}},whenValidate:function(){var e=this,t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],i=t.force,n=t.group;return this.refreshConstraints(),!n||this._isInGroup(n)?(this.value=this.getValue(),this._trigger("validate"),this.whenValid({force:i,value:this.value,_refreshed:!0}).always(function(){e._reflowUI()}).done(function(){e._trigger("success")}).fail(function(){e._trigger("error")}).always(function(){e._trigger("validated")})):void 0},hasConstraints:function(){return 0!==this.constraints.length},needsValidation:function(e){return"undefined"==typeof e&&(e=this.getValue()),e.length||this._isRequired()||"undefined"!=typeof this.options.validateIfEmpty?!0:!1},_isInGroup:function(t){return e.isArray(this.options.group)?-1!==e.inArray(t,this.options.group):this.options.group===t},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley field without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={force:n,value:r}}var s=this.whenValid(t);return s?$[s.state()]:!0},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.force,r=void 0===n?!1:n,s=i.value,a=i.group,o=i._refreshed;if(o||this.refreshConstraints(),!a||this._isInGroup(a)){if(this.validationResult=!0,!this.hasConstraints())return e.when();if(("undefined"==typeof s||null===s)&&(s=this.getValue()),!this.needsValidation(s)&&!0!==r)return e.when();var l=this._getGroupedConstraints(),u=[];return e.each(l,function(i,n){var r=e.when.apply(e,_toConsumableArray(e.map(n,function(e){return t._validateConstraint(s,e)})));return u.push(r),"rejected"===r.state()?!1:void 0}),e.when.apply(e,u)}},_validateConstraint:function(t,i){var n=this,r=i.validate(t,this);return!1===r&&(r=e.Deferred().reject()),e.when(r).fail(function(e){!0===n.validationResult&&(n.validationResult=[]),n.validationResult.push({assert:i,errorMessage:"string"==typeof e&&e})})},getValue:function(){var e;return e="function"==typeof this.options.value?this.options.value(this):"undefined"!=typeof this.options.value?this.options.value:this.$element.val(),"undefined"==typeof e||null===e?"":this._handleWhitespace(e)},refreshConstraints:function(){return this.actualizeOptions()._bindConstraints()},addConstraint:function(e,t,i,n){if(window.Parsley._validatorRegistry.validators[e]){var r=new b(this,e,t,i,n);"undefined"!==this.constraintsByName[r.name]&&this.removeConstraint(r.name),this.constraints.push(r),this.constraintsByName[r.name]=r}return this},removeConstraint:function(e){for(var t=0;t<this.constraints.length;t++)if(e===this.constraints[t].name){this.constraints.splice(t,1);break}return delete this.constraintsByName[e],this},updateConstraint:function(e,t,i){return this.removeConstraint(e).addConstraint(e,t,i)},_bindConstraints:function(){for(var e=[],t={},i=0;i<this.constraints.length;i++)!1===this.constraints[i].isDomConstraint&&(e.push(this.constraints[i]),t[this.constraints[i].name]=this.constraints[i]);this.constraints=e,this.constraintsByName=t;for(var n in this.options)this.addConstraint(n,this.options[n],void 0,!0);return this._bindHtml5Constraints()},_bindHtml5Constraints:function(){(this.$element.hasClass("required")||this.$element.attr("required"))&&this.addConstraint("required",!0,void 0,!0),"string"==typeof this.$element.attr("pattern")&&this.addConstraint("pattern",this.$element.attr("pattern"),void 0,!0),"undefined"!=typeof this.$element.attr("min")&&"undefined"!=typeof this.$element.attr("max")?this.addConstraint("range",[this.$element.attr("min"),this.$element.attr("max")],void 0,!0):"undefined"!=typeof this.$element.attr("min")?this.addConstraint("min",this.$element.attr("min"),void 0,!0):"undefined"!=typeof this.$element.attr("max")&&this.addConstraint("max",this.$element.attr("max"),void 0,!0),"undefined"!=typeof this.$element.attr("minlength")&&"undefined"!=typeof this.$element.attr("maxlength")?this.addConstraint("length",[this.$element.attr("minlength"),this.$element.attr("maxlength")],void 0,!0):"undefined"!=typeof this.$element.attr("minlength")?this.addConstraint("minlength",this.$element.attr("minlength"),void 0,!0):"undefined"!=typeof this.$element.attr("maxlength")&&this.addConstraint("maxlength",this.$element.attr("maxlength"),void 0,!0);var e=this.$element.attr("type");return"undefined"==typeof e?this:"number"===e?this.addConstraint("type",["number",{step:this.$element.attr("step"),base:this.$element.attr("min")||this.$element.attr("value")}],void 0,!0):/^(email|url|range)$/i.test(e)?this.addConstraint("type",e,void 0,!0):this},_isRequired:function(){return"undefined"==typeof this.constraintsByName.required?!1:!1!==this.constraintsByName.required.requirements},_trigger:function(e){return this.trigger("field:"+e)},_handleWhitespace:function(e){return!0===this.options.trimValue&&a.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"'),"squish"===this.options.whitespace&&(e=e.replace(/\s{2,}/g," ")),("trim"===this.options.whitespace||"squish"===this.options.whitespace||!0===this.options.trimValue)&&(e=a.trimString(e)),e},_getGroupedConstraints:function(){if(!1===this.options.priorityEnabled)return[this.constraints];for(var e=[],t={},i=0;i<this.constraints.length;i++){var n=this.constraints[i].priority;t[n]||e.push(t[n]=[]),t[n].push(this.constraints[i])}return e.sort(function(e,t){return t[0].priority-e[0].priority}),e}};var x=C,P=function(){this.__class__="ParsleyFieldMultiple"};P.prototype={addElement:function(e){return this.$elements.push(e),this},refreshConstraints:function(){var t;if(this.constraints=[],this.$element.is("select"))return this.actualizeOptions()._bindConstraints(),this;for(var i=0;i<this.$elements.length;i++)if(e("html").has(this.$elements[i]).length){t=this.$elements[i].data("ParsleyFieldMultiple").refreshConstraints().constraints;for(var n=0;n<t.length;n++)this.addConstraint(t[n].name,t[n].requirements,t[n].priority,t[n].isDomConstraint)}else this.$elements.splice(i,1);return this},getValue:function(){if("function"==typeof this.options.value)value=this.options.value(this);else if("undefined"!=typeof this.options.value)return this.options.value;if(this.$element.is("input[type=radio]"))return this._findRelated().filter(":checked").val()||"";if(this.$element.is("input[type=checkbox]")){var t=[];return this._findRelated().filter(":checked").each(function(){t.push(e(this).val())}),t}return this.$element.is("select")&&null===this.$element.val()?[]:this.$element.val()},_init:function(){return this.$elements=[this.$element],this}};var E=function(t,i,n){this.$element=e(t);var r=this.$element.data("Parsley");if(r)return"undefined"!=typeof n&&r.parent===window.Parsley&&(r.parent=n,r._resetOptions(r.options)),r;if(!this.$element.length)throw new Error("You must bind Parsley on an existing element.");if("undefined"!=typeof n&&"ParsleyForm"!==n.__class__)throw new Error("Parent instance must be a ParsleyForm instance");return this.parent=n||window.Parsley,this.init(i)};E.prototype={init:function(e){return this.__class__="Parsley",this.__version__="2.3.5",this.__id__=a.generateID(),this._resetOptions(e),this.$element.is("form")||a.checkAttr(this.$element,this.options.namespace,"validate")&&!this.$element.is(this.options.inputs)?this.bind("parsleyForm"):this.isMultiple()?this.handleMultiple():this.bind("parsleyField")},isMultiple:function(){return this.$element.is("input[type=radio], input[type=checkbox]")||this.$element.is("select")&&"undefined"!=typeof this.$element.attr("multiple")},handleMultiple:function(){var t,i,n=this;if(this.options.multiple||("undefined"!=typeof this.$element.attr("name")&&this.$element.attr("name").length?this.options.multiple=t=this.$element.attr("name"):"undefined"!=typeof this.$element.attr("id")&&this.$element.attr("id").length&&(this.options.multiple=this.$element.attr("id"))),this.$element.is("select")&&"undefined"!=typeof this.$element.attr("multiple"))return this.options.multiple=this.options.multiple||this.__id__,this.bind("parsleyFieldMultiple");if(!this.options.multiple)return a.warn("To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.",this.$element),this;this.options.multiple=this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g,""),
|
168 |
"undefined"!=typeof t&&e('input[name="'+t+'"]').each(function(t,i){e(i).is("input[type=radio], input[type=checkbox]")&&e(i).attr(n.options.namespace+"multiple",n.options.multiple)});for(var r=this._findRelated(),s=0;s<r.length;s++)if(i=e(r.get(s)).data("Parsley"),"undefined"!=typeof i){this.$element.data("ParsleyFieldMultiple")||i.addElement(this.$element);break}return this.bind("parsleyField",!0),i||this.bind("parsleyFieldMultiple")},bind:function(t,i){var n;switch(t){case"parsleyForm":n=e.extend(new _(this.$element,this.domOptions,this.options),window.ParsleyExtend)._bindFields();break;case"parsleyField":n=e.extend(new x(this.$element,this.domOptions,this.options,this.parent),window.ParsleyExtend);break;case"parsleyFieldMultiple":n=e.extend(new x(this.$element,this.domOptions,this.options,this.parent),new P,window.ParsleyExtend)._init();break;default:throw new Error(t+"is not a supported Parsley type")}return this.options.multiple&&a.setAttr(this.$element,this.options.namespace,"multiple",this.options.multiple),"undefined"!=typeof i?(this.$element.data("ParsleyFieldMultiple",n),n):(this.$element.data("Parsley",n),n._actualizeTriggers(),n._trigger("init"),n)}};var V=e.fn.jquery.split(".");if(parseInt(V[0])<=1&&parseInt(V[1])<8)throw"The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";V.forEach||a.warn("Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim");var M=e.extend(new l,{$element:e(document),actualizeOptions:null,_resetOptions:null,Factory:E,version:"2.3.5"});e.extend(x.prototype,y.Field,l.prototype),e.extend(_.prototype,y.Form,l.prototype),e.extend(E.prototype,l.prototype),e.fn.parsley=e.fn.psly=function(t){if(this.length>1){var i=[];return this.each(function(){i.push(e(this).parsley(t))}),i}return e(this).length?new E(this,t):void a.warn("You must bind Parsley on an existing element.")},"undefined"==typeof window.ParsleyExtend&&(window.ParsleyExtend={}),M.options=e.extend(a.objectCreate(o),window.ParsleyConfig),window.ParsleyConfig=M.options,window.Parsley=window.psly=M,window.ParsleyUtils=a;var O=window.Parsley._validatorRegistry=new c(window.ParsleyConfig.validators,window.ParsleyConfig.i18n);window.ParsleyValidator={},e.each("setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator".split(" "),function(t,i){window.Parsley[i]=e.proxy(O,i),window.ParsleyValidator[i]=function(){var e;return a.warnOnce("Accessing the method '"+i+"' through ParsleyValidator is deprecated. Simply call 'window.Parsley."+i+"(...)'"),(e=window.Parsley)[i].apply(e,arguments)}}),window.Parsley.UI=y,window.ParsleyUI={removeError:function(e,t,i){var n=!0!==i;return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e.removeError(t,{updateClass:n})},getErrorsMessages:function(e){return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'getErrorsMessages' on the instance directly."),e.getErrorsMessages()}},e.each("addError updateError".split(" "),function(e,t){window.ParsleyUI[t]=function(e,i,n,r,s){var o=!0!==s;return a.warnOnce("Accessing ParsleyUI is deprecated. Call '"+t+"' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e[t](i,{message:n,assert:r,updateClass:o})}}),/firefox/i.test(navigator.userAgent)&&e(document).on("change","select",function(t){e(t.target).trigger("input")}),!1!==window.ParsleyConfig.autoBind&&e(function(){e("[data-parsley-validate]").length&&e("[data-parsley-validate]").parsley()});var A=e({}),R=function(){a.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley")},D="parsley:";e.listen=function(e,n){var r;if(R(),"object"==typeof arguments[1]&&"function"==typeof arguments[2]&&(r=arguments[1],n=arguments[2]),"function"!=typeof n)throw new Error("Wrong parameters");window.Parsley.on(i(e),t(n,r))},e.listenTo=function(e,n,r){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");if("string"!=typeof n||"function"!=typeof r)throw new Error("Wrong parameters");e.on(i(n),t(r))},e.unsubscribe=function(e,t){if(R(),"string"!=typeof e||"function"!=typeof t)throw new Error("Wrong arguments");window.Parsley.off(i(e),t.parsleyAdaptedCallback)},e.unsubscribeTo=function(e,t){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");e.off(i(t))},e.unsubscribeAll=function(t){R(),window.Parsley.off(i(t)),e("form,input,textarea,select").each(function(){var n=e(this).data("Parsley");n&&n.off(i(t))})},e.emit=function(e,t){var n;R();var r=t instanceof x||t instanceof _,s=Array.prototype.slice.call(arguments,r?2:1);s.unshift(i(e)),r||(t=window.Parsley),(n=t).trigger.apply(n,_toConsumableArray(s))};e.extend(!0,M,{asyncValidators:{"default":{fn:function(e){return e.status>=200&&e.status<300},url:!1},reverse:{fn:function(e){return e.status<200||e.status>=300},url:!1}},addAsyncValidator:function(e,t,i,n){return M.asyncValidators[e]={fn:t,url:i||!1,options:n||{}},this}}),M.addValidator("remote",{requirementType:{"":"string",validator:"string",reverse:"boolean",options:"object"},validateString:function(t,i,n,r){var s,a,o={},l=n.validator||(!0===n.reverse?"reverse":"default");if("undefined"==typeof M.asyncValidators[l])throw new Error("Calling an undefined async validator: `"+l+"`");i=M.asyncValidators[l].url||i,i.indexOf("{value}")>-1?i=i.replace("{value}",encodeURIComponent(t)):o[r.$element.attr("name")||r.$element.attr("id")]=t;var u=e.extend(!0,n.options||{},M.asyncValidators[l].options);s=e.extend(!0,{},{url:i,data:o,type:"GET"},u),r.trigger("field:ajaxoptions",r,s),a=e.param(s),"undefined"==typeof M._remoteCache&&(M._remoteCache={});var d=M._remoteCache[a]=M._remoteCache[a]||e.ajax(s),h=function(){var t=M.asyncValidators[l].fn.call(r,d,i,n);return t||(t=e.Deferred().reject()),e.when(t)};return d.then(h,h)},priority:-1}),M.on("form:submit",function(){M._remoteCache={}}),window.ParsleyExtend.addAsyncValidator=function(){return ParsleyUtils.warnOnce("Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`"),M.addAsyncValidator.apply(M,arguments)},M.addMessages("en",{defaultMessage:"This value seems to be invalid.",type:{email:"This value should be a valid email.",url:"This value should be a valid url.",number:"This value should be a valid number.",integer:"This value should be a valid integer.",digits:"This value should be digits.",alphanum:"This value should be alphanumeric."},notblank:"This value should not be blank.",required:"This value is required.",pattern:"This value seems to be invalid.",min:"This value should be greater than or equal to %s.",max:"This value should be lower than or equal to %s.",range:"This value should be between %s and %s.",minlength:"This value is too short. It should have %s characters or more.",maxlength:"This value is too long. It should have %s characters or fewer.",length:"This value length is invalid. It should be between %s and %s characters long.",mincheck:"You must select at least %s choices.",maxcheck:"You must select %s choices or fewer.",check:"You must select between %s and %s choices.",equalto:"This value should be the same."}),M.setLocale("en");var q=M;return q});
|
169 |
-
//# sourceMappingURL=parsley.min.js.map
|
170 |
</script>
|
171 |
|
172 |
|
@@ -186,5 +185,4 @@ f.push(" != null ? helper : ",this.aliasable("helpers.helperMissing"))),this.pus
|
|
186 |
|
187 |
!function(a,b,c){!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)}(function(d){"use strict";function e(a,b,c,e){this.id=c,this.target=a,this.tooltip=F,this.elements={target:a},this._id=S+"-"+c,this.timers={img:{}},this.options=b,this.plugins={},this.cache={event:{},target:d(),disabled:E,attr:e,onTooltip:E,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=E}function f(a){return a===F||"object"!==d.type(a)}function g(a){return!(d.isFunction(a)||a&&a.attr||a.length||"object"===d.type(a)&&(a.jquery||a.then))}function h(a){var b,c,e,h;return f(a)?E:(f(a.metadata)&&(a.metadata={type:a.metadata}),"content"in a&&(b=a.content,f(b)||b.jquery||b.done?b=a.content={text:c=g(b)?E:b}:c=b.text,"ajax"in b&&(e=b.ajax,h=e&&e.once!==E,delete b.ajax,b.text=function(a,b){var f=c||d(this).attr(b.options.content.attr)||"Loading...",g=d.ajax(d.extend({},e,{context:b})).then(e.success,F,e.error).then(function(a){return a&&h&&b.set("content.text",a),a},function(a,c,d){b.destroyed||0===a.status||b.set("content.text",c+": "+d)});return h?f:(b.set("content.text",f),g)}),"title"in b&&(d.isPlainObject(b.title)&&(b.button=b.title.button,b.title=b.title.text),g(b.title||E)&&(b.title=E))),"position"in a&&f(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&f(a.show)&&(a.show=a.show.jquery?{target:a.show}:a.show===D?{ready:D}:{event:a.show}),"hide"in a&&f(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&f(a.style)&&(a.style={classes:a.style}),d.each(R,function(){this.sanitize&&this.sanitize(a)}),a)}function i(a,b){for(var c,d=0,e=a,f=b.split(".");e=e[f[d++]];)d<f.length&&(c=e);return[c||a,f.pop()]}function j(a,b){var c,d,e;for(c in this.checks)for(d in this.checks[c])(e=new RegExp(d,"i").exec(a))&&(b.push(e),("builtin"===c||this.plugins[c])&&this.checks[c][d].apply(this.plugins[c]||this,b))}function k(a){return V.concat("").join(a?"-"+a+" ":" ")}function l(a,b){return b>0?setTimeout(d.proxy(a,this),b):void a.call(this)}function m(a){this.tooltip.hasClass(ab)||(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=l.call(this,function(){this.toggle(D,a)},this.options.show.delay))}function n(a){if(!this.tooltip.hasClass(ab)&&!this.destroyed){var b=d(a.relatedTarget),c=b.closest(W)[0]===this.tooltip[0],e=b[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==b[0]&&"mouse"===this.options.position.target&&c||this.options.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(c||e))try{a.preventDefault(),a.stopImmediatePropagation()}catch(f){}else this.timers.hide=l.call(this,function(){this.toggle(E,a)},this.options.hide.delay,this)}}function o(a){!this.tooltip.hasClass(ab)&&this.options.hide.inactive&&(clearTimeout(this.timers.inactive),this.timers.inactive=l.call(this,function(){this.hide(a)},this.options.hide.inactive))}function p(a){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(a)}function q(a,c,e){d(b.body).delegate(a,(c.split?c:c.join("."+S+" "))+"."+S,function(){var a=y.api[d.attr(this,U)];a&&!a.disabled&&e.apply(a,arguments)})}function r(a,c,f){var g,i,j,k,l,m=d(b.body),n=a[0]===b?m:a,o=a.metadata?a.metadata(f.metadata):F,p="html5"===f.metadata.type&&o?o[f.metadata.name]:F,q=a.data(f.metadata.name||"qtipopts");try{q="string"==typeof q?d.parseJSON(q):q}catch(r){}if(k=d.extend(D,{},y.defaults,f,"object"==typeof q?h(q):F,h(p||o)),i=k.position,k.id=c,"boolean"==typeof k.content.text){if(j=a.attr(k.content.attr),k.content.attr===E||!j)return E;k.content.text=j}if(i.container.length||(i.container=m),i.target===E&&(i.target=n),k.show.target===E&&(k.show.target=n),k.show.solo===D&&(k.show.solo=i.container.closest("body")),k.hide.target===E&&(k.hide.target=n),k.position.viewport===D&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new A(i.at,D),i.my=new A(i.my),a.data(S))if(k.overwrite)a.qtip("destroy",!0);else if(k.overwrite===E)return E;return a.attr(T,c),k.suppress&&(l=a.attr("title"))&&a.removeAttr("title").attr(cb,l).attr("title",""),g=new e(a,k,c,!!j),a.data(S,g),g}function s(a){return a.charAt(0).toUpperCase()+a.slice(1)}function t(a,b){var d,e,f=b.charAt(0).toUpperCase()+b.slice(1),g=(b+" "+rb.join(f+" ")+f).split(" "),h=0;if(qb[b])return a.css(qb[b]);for(;d=g[h++];)if((e=a.css(d))!==c)return qb[b]=d,e}function u(a,b){return Math.ceil(parseFloat(t(a,b)))}function v(a,b){this._ns="tip",this.options=b,this.offset=b.offset,this.size=[b.width,b.height],this.init(this.qtip=a)}function w(a,b){this.options=b,this._ns="-modal",this.init(this.qtip=a)}function x(a){this._ns="ie6",this.init(this.qtip=a)}var y,z,A,B,C,D=!0,E=!1,F=null,G="x",H="y",I="width",J="height",K="top",L="left",M="bottom",N="right",O="center",P="flipinvert",Q="shift",R={},S="qtip",T="data-hasqtip",U="data-qtip-id",V=["ui-widget","ui-tooltip"],W="."+S,X="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),Y=S+"-fixed",Z=S+"-default",$=S+"-focus",_=S+"-hover",ab=S+"-disabled",bb="_replacedByqTip",cb="oldtitle",db={ie:function(){for(var a=4,c=b.createElement("div");(c.innerHTML="<!--[if gt IE "+a+"]><i></i><![endif]-->")&&c.getElementsByTagName("i")[0];a+=1);return a>4?a:0/0}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||E};z=e.prototype,z._when=function(a){return d.when.apply(d,a)},z.render=function(a){if(this.rendered||this.destroyed)return this;var b,c=this,e=this.options,f=this.cache,g=this.elements,h=e.content.text,i=e.content.title,j=e.content.button,k=e.position,l=("."+this._id+" ",[]);return d.attr(this.target[0],"aria-describedby",this._id),f.posClass=this._createPosClass((this.position={my:k.my,at:k.at}).my),this.tooltip=g.tooltip=b=d("<div/>",{id:this._id,"class":[S,Z,e.style.classes,f.posClass].join(" "),width:e.style.width||"",height:e.style.height||"",tracking:"mouse"===k.target&&k.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":E,"aria-describedby":this._id+"-content","aria-hidden":D}).toggleClass(ab,this.disabled).attr(U,this.id).data(S,this).appendTo(k.container).append(g.content=d("<div />",{"class":S+"-content",id:this._id+"-content","aria-atomic":D})),this.rendered=-1,this.positioning=D,i&&(this._createTitle(),d.isFunction(i)||l.push(this._updateTitle(i,E))),j&&this._createButton(),d.isFunction(h)||l.push(this._updateContent(h,E)),this.rendered=D,this._setWidget(),d.each(R,function(a){var b;"render"===this.initialize&&(b=this(c))&&(c.plugins[a]=b)}),this._unassignEvents(),this._assignEvents(),this._when(l).then(function(){c._trigger("render"),c.positioning=E,c.hiddenDuringWait||!e.show.ready&&!a||c.toggle(D,f.event,E),c.hiddenDuringWait=E}),y.api[this.id]=this,this},z.destroy=function(a){function b(){if(!this.destroyed){this.destroyed=D;var a,b=this.target,c=b.attr(cb);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),d.each(this.plugins,function(){this.destroy&&this.destroy()});for(a in this.timers)clearTimeout(this.timers[a]);b.removeData(S).removeAttr(U).removeAttr(T).removeAttr("aria-describedby"),this.options.suppress&&c&&b.attr("title",c).removeAttr(cb),this._unassignEvents(),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=F,delete y.api[this.id]}}return this.destroyed?this.target:(a===D&&"hide"!==this.triggering||!this.rendered?b.call(this):(this.tooltip.one("tooltiphidden",d.proxy(b,this)),!this.triggering&&this.hide()),this.target)},B=z.checks={builtin:{"^id$":function(a,b,c,e){var f=c===D?y.nextid:c,g=S+"-"+f;f!==E&&f.length>0&&!d("#"+g).length?(this._id=g,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):a[b]=e},"^prerender":function(a,b,c){c&&!this.rendered&&this.render(this.options.show.ready)},"^content.text$":function(a,b,c){this._updateContent(c)},"^content.attr$":function(a,b,c,d){this.options.content.text===this.target.attr(d)&&this._updateContent(this.target.attr(c))},"^content.title$":function(a,b,c){return c?(c&&!this.elements.title&&this._createTitle(),void this._updateTitle(c)):this._removeTitle()},"^content.button$":function(a,b,c){this._updateButton(c)},"^content.title.(text|button)$":function(a,b,c){this.set("content."+b,c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(this.position[b]=a[b]=new A(c,"at"===b))},"^position.container$":function(a,b,c){this.rendered&&this.tooltip.appendTo(c)},"^show.ready$":function(a,b,c){c&&(!this.rendered&&this.render(D)||this.toggle(D))},"^style.classes$":function(a,b,c,d){this.rendered&&this.tooltip.removeClass(d).addClass(c)},"^style.(width|height)":function(a,b,c){this.rendered&&this.tooltip.css(b,c)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def":function(a,b,c){this.rendered&&this.tooltip.toggleClass(Z,!!c)},"^events.(render|show|move|hide|focus|blur)$":function(a,b,c){this.rendered&&this.tooltip[(d.isFunction(c)?"":"un")+"bind"]("tooltip"+b,c)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var a=this.options.position;this.tooltip.attr("tracking","mouse"===a.target&&a.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},z.get=function(a){if(this.destroyed)return this;var b=i(this.options,a.toLowerCase()),c=b[0][b[1]];return c.precedance?c.string():c};var eb=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,fb=/^prerender|show\.ready/i;z.set=function(a,b){if(this.destroyed)return this;{var c,e=this.rendered,f=E,g=this.options;this.checks}return"string"==typeof a?(c=a,a={},a[c]=b):a=d.extend({},a),d.each(a,function(b,c){if(e&&fb.test(b))return void delete a[b];var h,j=i(g,b.toLowerCase());h=j[0][j[1]],j[0][j[1]]=c&&c.nodeType?d(c):c,f=eb.test(b)||f,a[b]=[j[0],j[1],c,h]}),h(g),this.positioning=D,d.each(a,d.proxy(j,this)),this.positioning=E,this.rendered&&this.tooltip[0].offsetWidth>0&&f&&this.reposition("mouse"===g.position.target?F:this.cache.event),this},z._update=function(a,b){var c=this,e=this.cache;return this.rendered&&a?(d.isFunction(a)&&(a=a.call(this.elements.target,e.event,this)||""),d.isFunction(a.then)?(e.waiting=D,a.then(function(a){return e.waiting=E,c._update(a,b)},F,function(a){return c._update(a,b)})):a===E||!a&&""!==a?E:(a.jquery&&a.length>0?b.empty().append(a.css({display:"block",visibility:"visible"})):b.html(a),this._waitForContent(b).then(function(a){c.rendered&&c.tooltip[0].offsetWidth>0&&c.reposition(e.event,!a.length)}))):E},z._waitForContent=function(a){var b=this.cache;return b.waiting=D,(d.fn.imagesLoaded?a.imagesLoaded():d.Deferred().resolve([])).done(function(){b.waiting=E}).promise()},z._updateContent=function(a,b){this._update(a,this.elements.content,b)},z._updateTitle=function(a,b){this._update(a,this.elements.title,b)===E&&this._removeTitle(E)},z._createTitle=function(){var a=this.elements,b=this._id+"-title";a.titlebar&&this._removeTitle(),a.titlebar=d("<div />",{"class":S+"-titlebar "+(this.options.style.widget?k("header"):"")}).append(a.title=d("<div />",{id:b,"class":S+"-title","aria-atomic":D})).insertBefore(a.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(a){d(this).toggleClass("ui-state-active ui-state-focus","down"===a.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(a){d(this).toggleClass("ui-state-hover","mouseover"===a.type)}),this.options.content.button&&this._createButton()},z._removeTitle=function(a){var b=this.elements;b.title&&(b.titlebar.remove(),b.titlebar=b.title=b.button=F,a!==E&&this.reposition())},z._createPosClass=function(a){return S+"-pos-"+(a||this.options.position.my).abbrev()},z.reposition=function(c,e){if(!this.rendered||this.positioning||this.destroyed)return this;this.positioning=D;var f,g,h,i,j=this.cache,k=this.tooltip,l=this.options.position,m=l.target,n=l.my,o=l.at,p=l.viewport,q=l.container,r=l.adjust,s=r.method.split(" "),t=k.outerWidth(E),u=k.outerHeight(E),v=0,w=0,x=k.css("position"),y={left:0,top:0},z=k[0].offsetWidth>0,A=c&&"scroll"===c.type,B=d(a),C=q[0].ownerDocument,F=this.mouse;if(d.isArray(m)&&2===m.length)o={x:L,y:K},y={left:m[0],top:m[1]};else if("mouse"===m)o={x:L,y:K},(!r.mouse||this.options.hide.distance)&&j.origin&&j.origin.pageX?c=j.origin:!c||c&&("resize"===c.type||"scroll"===c.type)?c=j.event:F&&F.pageX&&(c=F),"static"!==x&&(y=q.offset()),C.body.offsetWidth!==(a.innerWidth||C.documentElement.clientWidth)&&(g=d(b.body).offset()),y={left:c.pageX-y.left+(g&&g.left||0),top:c.pageY-y.top+(g&&g.top||0)},r.mouse&&A&&F&&(y.left-=(F.scrollX||0)-B.scrollLeft(),y.top-=(F.scrollY||0)-B.scrollTop());else{if("event"===m?c&&c.target&&"scroll"!==c.type&&"resize"!==c.type?j.target=d(c.target):c.target||(j.target=this.elements.target):"event"!==m&&(j.target=d(m.jquery?m:this.elements.target)),m=j.target,m=d(m).eq(0),0===m.length)return this;m[0]===b||m[0]===a?(v=db.iOS?a.innerWidth:m.width(),w=db.iOS?a.innerHeight:m.height(),m[0]===a&&(y={top:(p||m).scrollTop(),left:(p||m).scrollLeft()})):R.imagemap&&m.is("area")?f=R.imagemap(this,m,o,R.viewport?s:E):R.svg&&m&&m[0].ownerSVGElement?f=R.svg(this,m,o,R.viewport?s:E):(v=m.outerWidth(E),w=m.outerHeight(E),y=m.offset()),f&&(v=f.width,w=f.height,g=f.offset,y=f.position),y=this.reposition.offset(m,y,q),(db.iOS>3.1&&db.iOS<4.1||db.iOS>=4.3&&db.iOS<4.33||!db.iOS&&"fixed"===x)&&(y.left-=B.scrollLeft(),y.top-=B.scrollTop()),(!f||f&&f.adjustable!==E)&&(y.left+=o.x===N?v:o.x===O?v/2:0,y.top+=o.y===M?w:o.y===O?w/2:0)}return y.left+=r.x+(n.x===N?-t:n.x===O?-t/2:0),y.top+=r.y+(n.y===M?-u:n.y===O?-u/2:0),R.viewport?(h=y.adjusted=R.viewport(this,y,l,v,w,t,u),g&&h.left&&(y.left+=g.left),g&&h.top&&(y.top+=g.top),h.my&&(this.position.my=h.my)):y.adjusted={left:0,top:0},j.posClass!==(i=this._createPosClass(this.position.my))&&k.removeClass(j.posClass).addClass(j.posClass=i),this._trigger("move",[y,p.elem||p],c)?(delete y.adjusted,e===E||!z||isNaN(y.left)||isNaN(y.top)||"mouse"===m||!d.isFunction(l.effect)?k.css(y):d.isFunction(l.effect)&&(l.effect.call(k,this,d.extend({},y)),k.queue(function(a){d(this).css({opacity:"",height:""}),db.ie&&this.style.removeAttribute("filter"),a()})),this.positioning=E,this):this},z.reposition.offset=function(a,c,e){function f(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}if(!e[0])return c;var g,h,i,j,k=d(a[0].ownerDocument),l=!!db.ie&&"CSS1Compat"!==b.compatMode,m=e[0];do"static"!==(h=d.css(m,"position"))&&("fixed"===h?(i=m.getBoundingClientRect(),f(k,-1)):(i=d(m).position(),i.left+=parseFloat(d.css(m,"borderLeftWidth"))||0,i.top+=parseFloat(d.css(m,"borderTopWidth"))||0),c.left-=i.left+(parseFloat(d.css(m,"marginLeft"))||0),c.top-=i.top+(parseFloat(d.css(m,"marginTop"))||0),g||"hidden"===(j=d.css(m,"overflow"))||"visible"===j||(g=d(m)));while(m=m.offsetParent);return g&&(g[0]!==k[0]||l)&&f(g,1),c};var gb=(A=z.reposition.Corner=function(a,b){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,O).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!b;var c=a.charAt(0);this.precedance="t"===c||"b"===c?H:G}).prototype;gb.invert=function(a,b){this[a]=this[a]===L?N:this[a]===N?L:b||this[a]},gb.string=function(a){var b=this.x,c=this.y,d=b!==c?"center"===b||"center"!==c&&(this.precedance===H||this.forceY)?[c,b]:[b,c]:[b];return a!==!1?d.join(" "):d},gb.abbrev=function(){var a=this.string(!1);return a[0].charAt(0)+(a[1]&&a[1].charAt(0)||"")},gb.clone=function(){return new A(this.string(),this.forceY)},z.toggle=function(a,c){var e=this.cache,f=this.options,g=this.tooltip;if(c){if(/over|enter/.test(c.type)&&e.event&&/out|leave/.test(e.event.type)&&f.show.target.add(c.target).length===f.show.target.length&&g.has(c.relatedTarget).length)return this;e.event=d.event.fix(c)}if(this.waiting&&!a&&(this.hiddenDuringWait=D),!this.rendered)return a?this.render(1):this;if(this.destroyed||this.disabled)return this;var h,i,j,k=a?"show":"hide",l=this.options[k],m=(this.options[a?"hide":"show"],this.options.position),n=this.options.content,o=this.tooltip.css("width"),p=this.tooltip.is(":visible"),q=a||1===l.target.length,r=!c||l.target.length<2||e.target[0]===c.target;return(typeof a).search("boolean|number")&&(a=!p),h=!g.is(":animated")&&p===a&&r,i=h?F:!!this._trigger(k,[90]),this.destroyed?this:(i!==E&&a&&this.focus(c),!i||h?this:(d.attr(g[0],"aria-hidden",!a),a?(this.mouse&&(e.origin=d.event.fix(this.mouse)),d.isFunction(n.text)&&this._updateContent(n.text,E),d.isFunction(n.title)&&this._updateTitle(n.title,E),!C&&"mouse"===m.target&&m.adjust.mouse&&(d(b).bind("mousemove."+S,this._storeMouse),C=D),o||g.css("width",g.outerWidth(E)),this.reposition(c,arguments[2]),o||g.css("width",""),l.solo&&("string"==typeof l.solo?d(l.solo):d(W,l.solo)).not(g).not(l.target).qtip("hide",d.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete e.origin,C&&!d(W+'[tracking="true"]:visible',l.solo).not(g).length&&(d(b).unbind("mousemove."+S),C=E),this.blur(c)),j=d.proxy(function(){a?(db.ie&&g[0].style.removeAttribute("filter"),g.css("overflow",""),"string"==typeof l.autofocus&&d(this.options.show.autofocus,g).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):g.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(a?"visible":"hidden")},this),l.effect===E||q===E?(g[k](),j()):d.isFunction(l.effect)?(g.stop(1,1),l.effect.call(g,this),g.queue("fx",function(a){j(),a()})):g.fadeTo(90,a?1:0,j),a&&l.target.trigger("qtip-"+this.id+"-inactive"),this))},z.show=function(a){return this.toggle(D,a)},z.hide=function(a){return this.toggle(E,a)},z.focus=function(a){if(!this.rendered||this.destroyed)return this;var b=d(W),c=this.tooltip,e=parseInt(c[0].style.zIndex,10),f=y.zindex+b.length;return c.hasClass($)||this._trigger("focus",[f],a)&&(e!==f&&(b.each(function(){this.style.zIndex>e&&(this.style.zIndex=this.style.zIndex-1)}),b.filter("."+$).qtip("blur",a)),c.addClass($)[0].style.zIndex=f),this},z.blur=function(a){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass($),this._trigger("blur",[this.tooltip.css("zIndex")],a),this)},z.disable=function(a){return this.destroyed?this:("toggle"===a?a=!(this.rendered?this.tooltip.hasClass(ab):this.disabled):"boolean"!=typeof a&&(a=D),this.rendered&&this.tooltip.toggleClass(ab,a).attr("aria-disabled",a),this.disabled=!!a,this)},z.enable=function(){return this.disable(E)},z._createButton=function(){var a=this,b=this.elements,c=b.tooltip,e=this.options.content.button,f="string"==typeof e,g=f?e:"Close tooltip";b.button&&b.button.remove(),b.button=e.jquery?e:d("<a />",{"class":"qtip-close "+(this.options.style.widget?"":S+"-icon"),title:g,"aria-label":g}).prepend(d("<span />",{"class":"ui-icon ui-icon-close",html:"×"})),b.button.appendTo(b.titlebar||c).attr("role","button").click(function(b){return c.hasClass(ab)||a.hide(b),E})},z._updateButton=function(a){if(!this.rendered)return E;var b=this.elements.button;a?this._createButton():b.remove()},z._setWidget=function(){var a=this.options.style.widget,b=this.elements,c=b.tooltip,d=c.hasClass(ab);c.removeClass(ab),ab=a?"ui-state-disabled":"qtip-disabled",c.toggleClass(ab,d),c.toggleClass("ui-helper-reset "+k(),a).toggleClass(Z,this.options.style.def&&!a),b.content&&b.content.toggleClass(k("content"),a),b.titlebar&&b.titlebar.toggleClass(k("header"),a),b.button&&b.button.toggleClass(S+"-icon",!a)},z._storeMouse=function(a){return(this.mouse=d.event.fix(a)).type="mousemove",this},z._bind=function(a,b,c,e,f){if(a&&c&&b.length){var g="."+this._id+(e?"-"+e:"");return d(a).bind((b.split?b:b.join(g+" "))+g,d.proxy(c,f||this)),this}},z._unbind=function(a,b){return a&&d(a).unbind("."+this._id+(b?"-"+b:"")),this},z._trigger=function(a,b,c){var e=d.Event("tooltip"+a);return e.originalEvent=c&&d.extend({},c)||this.cache.event||F,this.triggering=a,this.tooltip.trigger(e,[this].concat(b||[])),this.triggering=E,!e.isDefaultPrevented()},z._bindEvents=function(a,b,c,e,f,g){var h=c.filter(e).add(e.filter(c)),i=[];h.length&&(d.each(b,function(b,c){var e=d.inArray(c,a);e>-1&&i.push(a.splice(e,1)[0])}),i.length&&(this._bind(h,i,function(a){var b=this.rendered?this.tooltip[0].offsetWidth>0:!1;(b?g:f).call(this,a)}),c=c.not(h),e=e.not(h))),this._bind(c,a,f),this._bind(e,b,g)},z._assignInitialEvents=function(a){function b(a){return this.disabled||this.destroyed?E:(this.cache.event=a&&d.event.fix(a),this.cache.target=a&&d(a.target),clearTimeout(this.timers.show),void(this.timers.show=l.call(this,function(){this.render("object"==typeof a||c.show.ready)},c.prerender?0:c.show.delay)))}var c=this.options,e=c.show.target,f=c.hide.target,g=c.show.event?d.trim(""+c.show.event).split(" "):[],h=c.hide.event?d.trim(""+c.hide.event).split(" "):[];this._bind(this.elements.target,["remove","removeqtip"],function(){this.destroy(!0)},"destroy"),/mouse(over|enter)/i.test(c.show.event)&&!/mouse(out|leave)/i.test(c.hide.event)&&h.push("mouseleave"),this._bind(e,"mousemove",function(a){this._storeMouse(a),this.cache.onTarget=D}),this._bindEvents(g,h,e,f,b,function(){return this.timers?void clearTimeout(this.timers.show):E}),(c.show.ready||c.prerender)&&b.call(this,a)},z._assignEvents=function(){var c=this,e=this.options,f=e.position,g=this.tooltip,h=e.show.target,i=e.hide.target,j=f.container,k=f.viewport,l=d(b),q=(d(b.body),d(a)),r=e.show.event?d.trim(""+e.show.event).split(" "):[],s=e.hide.event?d.trim(""+e.hide.event).split(" "):[];d.each(e.events,function(a,b){c._bind(g,"toggle"===a?["tooltipshow","tooltiphide"]:["tooltip"+a],b,null,g)}),/mouse(out|leave)/i.test(e.hide.event)&&"window"===e.hide.leave&&this._bind(l,["mouseout","blur"],function(a){/select|option/.test(a.target.nodeName)||a.relatedTarget||this.hide(a)}),e.hide.fixed?i=i.add(g.addClass(Y)):/mouse(over|enter)/i.test(e.show.event)&&this._bind(i,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+e.hide.event).indexOf("unfocus")>-1&&this._bind(j.closest("html"),["mousedown","touchstart"],function(a){var b=d(a.target),c=this.rendered&&!this.tooltip.hasClass(ab)&&this.tooltip[0].offsetWidth>0,e=b.parents(W).filter(this.tooltip[0]).length>0;b[0]===this.target[0]||b[0]===this.tooltip[0]||e||this.target.has(b[0]).length||!c||this.hide(a)}),"number"==typeof e.hide.inactive&&(this._bind(h,"qtip-"+this.id+"-inactive",o,"inactive"),this._bind(i.add(g),y.inactiveEvents,o)),this._bindEvents(r,s,h,i,m,n),this._bind(h.add(g),"mousemove",function(a){if("number"==typeof e.hide.distance){var b=this.cache.origin||{},c=this.options.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&this.hide(a)}this._storeMouse(a)}),"mouse"===f.target&&f.adjust.mouse&&(e.hide.event&&this._bind(h,["mouseenter","mouseleave"],function(a){return this.cache?void(this.cache.onTarget="mouseenter"===a.type):E}),this._bind(l,"mousemove",function(a){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(ab)&&this.tooltip[0].offsetWidth>0&&this.reposition(a)})),(f.adjust.resize||k.length)&&this._bind(d.event.special.resize?k:q,"resize",p),f.adjust.scroll&&this._bind(q.add(f.container),"scroll",p)},z._unassignEvents=function(){var c=this.options,e=c.show.target,f=c.hide.target,g=d.grep([this.elements.target[0],this.rendered&&this.tooltip[0],c.position.container[0],c.position.viewport[0],c.position.container.closest("html")[0],a,b],function(a){return"object"==typeof a});e&&e.toArray&&(g=g.concat(e.toArray())),f&&f.toArray&&(g=g.concat(f.toArray())),this._unbind(g)._unbind(g,"destroy")._unbind(g,"inactive")},d(function(){q(W,["mouseenter","mouseleave"],function(a){var b="mouseenter"===a.type,c=d(a.currentTarget),e=d(a.relatedTarget||a.target),f=this.options;b?(this.focus(a),c.hasClass(Y)&&!c.hasClass(ab)&&clearTimeout(this.timers.hide)):"mouse"===f.position.target&&f.position.adjust.mouse&&f.hide.event&&f.show.target&&!e.closest(f.show.target[0]).length&&this.hide(a),c.toggleClass(_,b)}),q("["+U+"]",X,o)}),y=d.fn.qtip=function(a,b,e){var f=(""+a).toLowerCase(),g=F,i=d.makeArray(arguments).slice(1),j=i[i.length-1],k=this[0]?d.data(this[0],S):F;return!arguments.length&&k||"api"===f?k:"string"==typeof a?(this.each(function(){var a=d.data(this,S);if(!a)return D;if(j&&j.timeStamp&&(a.cache.event=j),!b||"option"!==f&&"options"!==f)a[f]&&a[f].apply(a,i);else{if(e===c&&!d.isPlainObject(b))return g=a.get(b),E;a.set(b,e)}}),g!==F?g:this):"object"!=typeof a&&arguments.length?void 0:(k=h(d.extend(D,{},a)),this.each(function(a){var b,c;return c=d.isArray(k.id)?k.id[a]:k.id,c=!c||c===E||c.length<1||y.api[c]?y.nextid++:c,b=r(d(this),c,k),b===E?D:(y.api[c]=b,d.each(R,function(){"initialize"===this.initialize&&this(b)}),void b._assignInitialEvents(j))}))},d.qtip=e,y.api={},d.each({attr:function(a,b){if(this.length){var c=this[0],e="title",f=d.data(c,"qtip");if(a===e&&f&&"object"==typeof f&&f.options.suppress)return arguments.length<2?d.attr(c,cb):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",b),this.attr(cb,b))}return d.fn["attr"+bb].apply(this,arguments)},clone:function(a){var b=(d([]),d.fn["clone"+bb].apply(this,arguments));return a||b.filter("["+cb+"]").attr("title",function(){return d.attr(this,cb)}).removeAttr(cb),b}},function(a,b){if(!b||d.fn[a+bb])return D;var c=d.fn[a+bb]=d.fn[a];d.fn[a]=function(){return b.apply(this,arguments)||c.apply(this,arguments)}}),d.ui||(d["cleanData"+bb]=d.cleanData,d.cleanData=function(a){for(var b,c=0;(b=d(a[c])).length;c++)if(b.attr(T))try{b.triggerHandler("removeqtip")}catch(e){}d["cleanData"+bb].apply(this,arguments)}),y.version="2.2.1",y.nextid=0,y.inactiveEvents=X,y.zindex=15e3,y.defaults={prerender:E,id:E,overwrite:D,suppress:D,content:{text:D,attr:"title",title:E,button:E},position:{my:"top left",at:"bottom right",target:E,container:E,viewport:E,adjust:{x:0,y:0,mouse:D,scroll:D,resize:D,method:"flipinvert flipinvert"},effect:function(a,b){d(this).animate(b,{duration:200,queue:E})}},show:{target:E,event:"mouseenter",effect:D,delay:90,solo:E,ready:E,autofocus:E},hide:{target:E,event:"mouseleave",effect:D,delay:0,fixed:E,inactive:E,leave:"window",distance:E},style:{classes:"",widget:E,width:E,height:E,def:D},events:{render:F,move:F,show:F,hide:F,toggle:F,visible:F,hidden:F,focus:F,blur:F}};var hb,ib="margin",jb="border",kb="color",lb="background-color",mb="transparent",nb=" !important",ob=!!b.createElement("canvas").getContext,pb=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,qb={},rb=["Webkit","O","Moz","ms"];if(ob)var sb=a.devicePixelRatio||1,tb=function(){var a=b.createElement("canvas").getContext("2d");return a.backingStorePixelRatio||a.webkitBackingStorePixelRatio||a.mozBackingStorePixelRatio||a.msBackingStorePixelRatio||a.oBackingStorePixelRatio||1}(),ub=sb/tb;else var vb=function(a,b,c){return"<qtipvml:"+a+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(b||"")+' style="behavior: url(#default#VML); '+(c||"")+'" />'};d.extend(v.prototype,{init:function(a){var b,c;c=this.element=a.elements.tip=d("<div />",{"class":S+"-tip"}).prependTo(a.tooltip),ob?(b=d("<canvas />").appendTo(this.element)[0].getContext("2d"),b.lineJoin="miter",b.miterLimit=1e5,b.save()):(b=vb("shape",'coordorigin="0,0"',"position:absolute;"),this.element.html(b+b),a._bind(d("*",c).add(c),["click","mousedown"],function(a){a.stopPropagation()},this._ns)),a._bind(a.tooltip,"tooltipmove",this.reposition,this._ns,this),this.create()},_swapDimensions:function(){this.size[0]=this.options.height,this.size[1]=this.options.width},_resetDimensions:function(){this.size[0]=this.options.width,this.size[1]=this.options.height},_useTitle:function(a){var b=this.qtip.elements.titlebar;return b&&(a.y===K||a.y===O&&this.element.position().top+this.size[1]/2+this.options.offset<b.outerHeight(D))},_parseCorner:function(a){var b=this.qtip.options.position.my;return a===E||b===E?a=E:a===D?a=new A(b.string()):a.string||(a=new A(a),a.fixed=D),a},_parseWidth:function(a,b,c){var d=this.qtip.elements,e=jb+s(b)+"Width";return(c?u(c,e):u(d.content,e)||u(this._useTitle(a)&&d.titlebar||d.content,e)||u(d.tooltip,e))||0},_parseRadius:function(a){var b=this.qtip.elements,c=jb+s(a.y)+s(a.x)+"Radius";return db.ie<9?0:u(this._useTitle(a)&&b.titlebar||b.content,c)||u(b.tooltip,c)||0},_invalidColour:function(a,b,c){var d=a.css(b);return!d||c&&d===a.css(c)||pb.test(d)?E:d},_parseColours:function(a){var b=this.qtip.elements,c=this.element.css("cssText",""),e=jb+s(a[a.precedance])+s(kb),f=this._useTitle(a)&&b.titlebar||b.content,g=this._invalidColour,h=[];return h[0]=g(c,lb)||g(f,lb)||g(b.content,lb)||g(b.tooltip,lb)||c.css(lb),h[1]=g(c,e,kb)||g(f,e,kb)||g(b.content,e,kb)||g(b.tooltip,e,kb)||b.tooltip.css(e),d("*",c).add(c).css("cssText",lb+":"+mb+nb+";"+jb+":0"+nb+";"),h},_calculateSize:function(a){var b,c,d,e=a.precedance===H,f=this.options.width,g=this.options.height,h="c"===a.abbrev(),i=(e?f:g)*(h?.5:1),j=Math.pow,k=Math.round,l=Math.sqrt(j(i,2)+j(g,2)),m=[this.border/i*l,this.border/g*l];return m[2]=Math.sqrt(j(m[0],2)-j(this.border,2)),m[3]=Math.sqrt(j(m[1],2)-j(this.border,2)),b=l+m[2]+m[3]+(h?0:m[0]),c=b/l,d=[k(c*f),k(c*g)],e?d:d.reverse()},_calculateTip:function(a,b,c){c=c||1,b=b||this.size;var d=b[0]*c,e=b[1]*c,f=Math.ceil(d/2),g=Math.ceil(e/2),h={br:[0,0,d,e,d,0],bl:[0,0,d,0,0,e],tr:[0,e,d,0,d,e],tl:[0,0,0,e,d,e],tc:[0,e,f,0,d,e],bc:[0,0,d,0,f,e],rc:[0,0,d,g,0,e],lc:[d,0,d,e,0,g]};return h.lt=h.br,h.rt=h.bl,h.lb=h.tr,h.rb=h.tl,h[a.abbrev()]},_drawCoords:function(a,b){a.beginPath(),a.moveTo(b[0],b[1]),a.lineTo(b[2],b[3]),a.lineTo(b[4],b[5]),a.closePath()},create:function(){var a=this.corner=(ob||db.ie)&&this._parseCorner(this.options.corner);return(this.enabled=!!this.corner&&"c"!==this.corner.abbrev())&&(this.qtip.cache.corner=a.clone(),this.update()),this.element.toggle(this.enabled),this.corner},update:function(b,c){if(!this.enabled)return this;var e,f,g,h,i,j,k,l,m=this.qtip.elements,n=this.element,o=n.children(),p=this.options,q=this.size,r=p.mimic,s=Math.round;b||(b=this.qtip.cache.corner||this.corner),r===E?r=b:(r=new A(r),r.precedance=b.precedance,"inherit"===r.x?r.x=b.x:"inherit"===r.y?r.y=b.y:r.x===r.y&&(r[b.precedance]=b[b.precedance])),f=r.precedance,b.precedance===G?this._swapDimensions():this._resetDimensions(),e=this.color=this._parseColours(b),e[1]!==mb?(l=this.border=this._parseWidth(b,b[b.precedance]),p.border&&1>l&&!pb.test(e[1])&&(e[0]=e[1]),this.border=l=p.border!==D?p.border:l):this.border=l=0,k=this.size=this._calculateSize(b),n.css({width:k[0],height:k[1],lineHeight:k[1]+"px"}),j=b.precedance===H?[s(r.x===L?l:r.x===N?k[0]-q[0]-l:(k[0]-q[0])/2),s(r.y===K?k[1]-q[1]:0)]:[s(r.x===L?k[0]-q[0]:0),s(r.y===K?l:r.y===M?k[1]-q[1]-l:(k[1]-q[1])/2)],ob?(g=o[0].getContext("2d"),g.restore(),g.save(),g.clearRect(0,0,6e3,6e3),h=this._calculateTip(r,q,ub),i=this._calculateTip(r,this.size,ub),o.attr(I,k[0]*ub).attr(J,k[1]*ub),o.css(I,k[0]).css(J,k[1]),this._drawCoords(g,i),g.fillStyle=e[1],g.fill(),g.translate(j[0]*ub,j[1]*ub),this._drawCoords(g,h),g.fillStyle=e[0],g.fill()):(h=this._calculateTip(r),h="m"+h[0]+","+h[1]+" l"+h[2]+","+h[3]+" "+h[4]+","+h[5]+" xe",j[2]=l&&/^(r|b)/i.test(b.string())?8===db.ie?2:1:0,o.css({coordsize:k[0]+l+" "+(k[1]+l),antialias:""+(r.string().indexOf(O)>-1),left:j[0]-j[2]*Number(f===G),top:j[1]-j[2]*Number(f===H),width:k[0]+l,height:k[1]+l}).each(function(a){var b=d(this);b[b.prop?"prop":"attr"]({coordsize:k[0]+l+" "+(k[1]+l),path:h,fillcolor:e[0],filled:!!a,stroked:!a}).toggle(!(!l&&!a)),!a&&b.html(vb("stroke",'weight="'+2*l+'px" color="'+e[1]+'" miterlimit="1000" joinstyle="miter"'))})),a.opera&&setTimeout(function(){m.tip.css({display:"inline-block",visibility:"visible"})},1),c!==E&&this.calculate(b,k)},calculate:function(a,b){if(!this.enabled)return E;var c,e,f=this,g=this.qtip.elements,h=this.element,i=this.options.offset,j=(g.tooltip.hasClass("ui-widget"),{});return a=a||this.corner,c=a.precedance,b=b||this._calculateSize(a),e=[a.x,a.y],c===G&&e.reverse(),d.each(e,function(d,e){var h,k,l;
|
188 |
e===O?(h=c===H?L:K,j[h]="50%",j[ib+"-"+h]=-Math.round(b[c===H?0:1]/2)+i):(h=f._parseWidth(a,e,g.tooltip),k=f._parseWidth(a,e,g.content),l=f._parseRadius(a),j[e]=Math.max(-f.border,d?k:i+(l>h?l:-h)))}),j[a[c]]-=b[c===G?0:1],h.css({margin:"",top:"",bottom:"",left:"",right:""}).css(j),j},reposition:function(a,b,d){function e(a,b,c,d,e){a===Q&&j.precedance===b&&k[d]&&j[c]!==O?j.precedance=j.precedance===G?H:G:a!==Q&&k[d]&&(j[b]=j[b]===O?k[d]>0?d:e:j[b]===d?e:d)}function f(a,b,e){j[a]===O?p[ib+"-"+b]=o[a]=g[ib+"-"+b]-k[b]:(h=g[e]!==c?[k[b],-g[b]]:[-k[b],g[b]],(o[a]=Math.max(h[0],h[1]))>h[0]&&(d[b]-=k[b],o[b]=E),p[g[e]!==c?e:b]=o[a])}if(this.enabled){var g,h,i=b.cache,j=this.corner.clone(),k=d.adjusted,l=b.options.position.adjust.method.split(" "),m=l[0],n=l[1]||l[0],o={left:E,top:E,x:0,y:0},p={};this.corner.fixed!==D&&(e(m,G,H,L,N),e(n,H,G,K,M),(j.string()!==i.corner.string()||i.cornerTop!==k.top||i.cornerLeft!==k.left)&&this.update(j,E)),g=this.calculate(j),g.right!==c&&(g.left=-g.right),g.bottom!==c&&(g.top=-g.bottom),g.user=this.offset,(o.left=m===Q&&!!k.left)&&f(G,L,N),(o.top=n===Q&&!!k.top)&&f(H,K,M),this.element.css(p).toggle(!(o.x&&o.y||j.x===O&&o.y||j.y===O&&o.x)),d.left-=g.left.charAt?g.user:m!==Q||o.top||!o.left&&!o.top?g.left+this.border:0,d.top-=g.top.charAt?g.user:n!==Q||o.left||!o.left&&!o.top?g.top+this.border:0,i.cornerLeft=k.left,i.cornerTop=k.top,i.corner=j.clone()}},destroy:function(){this.qtip._unbind(this.qtip.tooltip,this._ns),this.qtip.elements.tip&&this.qtip.elements.tip.find("*").remove().end().remove()}}),hb=R.tip=function(a){return new v(a,a.options.style.tip)},hb.initialize="render",hb.sanitize=function(a){if(a.style&&"tip"in a.style){var b=a.style.tip;"object"!=typeof b&&(b=a.style.tip={corner:b}),/string|boolean/i.test(typeof b.corner)||(b.corner=D)}},B.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){this.create(),this.qtip.reposition()},"^style.tip.(height|width)$":function(a){this.size=[a.width,a.height],this.update(),this.qtip.reposition()},"^content.title|style.(classes|widget)$":function(){this.update()}},d.extend(D,y.defaults,{style:{tip:{corner:D,mimic:E,width:6,height:6,border:D,offset:0}}});var wb,xb,yb="qtip-modal",zb="."+yb;xb=function(){function a(a){if(d.expr[":"].focusable)return d.expr[":"].focusable;var b,c,e,f=!isNaN(d.attr(a,"tabindex")),g=a.nodeName&&a.nodeName.toLowerCase();return"area"===g?(b=a.parentNode,c=b.name,a.href&&c&&"map"===b.nodeName.toLowerCase()?(e=d("img[usemap=#"+c+"]")[0],!!e&&e.is(":visible")):!1):/input|select|textarea|button|object/.test(g)?!a.disabled:"a"===g?a.href||f:f}function c(a){k.length<1&&a.length?a.not("body").blur():k.first().focus()}function e(a){if(i.is(":visible")){var b,e=d(a.target),h=f.tooltip,j=e.closest(W);b=j.length<1?E:parseInt(j[0].style.zIndex,10)>parseInt(h[0].style.zIndex,10),b||e.closest(W)[0]===h[0]||c(e),g=a.target===k[k.length-1]}}var f,g,h,i,j=this,k={};d.extend(j,{init:function(){return i=j.elem=d("<div />",{id:"qtip-overlay",html:"<div></div>",mousedown:function(){return E}}).hide(),d(b.body).bind("focusin"+zb,e),d(b).bind("keydown"+zb,function(a){f&&f.options.show.modal.escape&&27===a.keyCode&&f.hide(a)}),i.bind("click"+zb,function(a){f&&f.options.show.modal.blur&&f.hide(a)}),j},update:function(b){f=b,k=b.options.show.modal.stealfocus!==E?b.tooltip.find("*").filter(function(){return a(this)}):[]},toggle:function(a,e,g){var k=(d(b.body),a.tooltip),l=a.options.show.modal,m=l.effect,n=e?"show":"hide",o=i.is(":visible"),p=d(zb).filter(":visible:not(:animated)").not(k);return j.update(a),e&&l.stealfocus!==E&&c(d(":focus")),i.toggleClass("blurs",l.blur),e&&i.appendTo(b.body),i.is(":animated")&&o===e&&h!==E||!e&&p.length?j:(i.stop(D,E),d.isFunction(m)?m.call(i,e):m===E?i[n]():i.fadeTo(parseInt(g,10)||90,e?1:0,function(){e||i.hide()}),e||i.queue(function(a){i.css({left:"",top:""}),d(zb).length||i.detach(),a()}),h=e,f.destroyed&&(f=F),j)}}),j.init()},xb=new xb,d.extend(w.prototype,{init:function(a){var b=a.tooltip;return this.options.on?(a.elements.overlay=xb.elem,b.addClass(yb).css("z-index",y.modal_zindex+d(zb).length),a._bind(b,["tooltipshow","tooltiphide"],function(a,c,e){var f=a.originalEvent;if(a.target===b[0])if(f&&"tooltiphide"===a.type&&/mouse(leave|enter)/.test(f.type)&&d(f.relatedTarget).closest(xb.elem[0]).length)try{a.preventDefault()}catch(g){}else(!f||f&&"tooltipsolo"!==f.type)&&this.toggle(a,"tooltipshow"===a.type,e)},this._ns,this),a._bind(b,"tooltipfocus",function(a,c){if(!a.isDefaultPrevented()&&a.target===b[0]){var e=d(zb),f=y.modal_zindex+e.length,g=parseInt(b[0].style.zIndex,10);xb.elem[0].style.zIndex=f-1,e.each(function(){this.style.zIndex>g&&(this.style.zIndex-=1)}),e.filter("."+$).qtip("blur",a.originalEvent),b.addClass($)[0].style.zIndex=f,xb.update(c);try{a.preventDefault()}catch(h){}}},this._ns,this),void a._bind(b,"tooltiphide",function(a){a.target===b[0]&&d(zb).filter(":visible").not(b).last().qtip("focus",a)},this._ns,this)):this},toggle:function(a,b,c){return a&&a.isDefaultPrevented()?this:void xb.toggle(this.qtip,!!b,c)},destroy:function(){this.qtip.tooltip.removeClass(yb),this.qtip._unbind(this.qtip.tooltip,this._ns),xb.toggle(this.qtip,E),delete this.qtip.elements.overlay}}),wb=R.modal=function(a){return new w(a,a.options.show.modal)},wb.sanitize=function(a){a.show&&("object"!=typeof a.show.modal?a.show.modal={on:!!a.show.modal}:"undefined"==typeof a.show.modal.on&&(a.show.modal.on=D))},y.modal_zindex=y.zindex-200,wb.initialize="render",B.modal={"^show.modal.(on|blur)$":function(){this.destroy(),this.init(),this.qtip.elems.overlay.toggle(this.qtip.tooltip[0].offsetWidth>0)}},d.extend(D,y.defaults,{show:{modal:{on:E,effect:D,blur:D,stealfocus:D,escape:D}}}),R.viewport=function(c,d,e,f,g,h,i){function j(a,b,c,e,f,g,h,i,j){var k=d[f],s=u[a],t=v[a],w=c===Q,x=s===f?j:s===g?-j:-j/2,y=t===f?i:t===g?-i:-i/2,z=q[f]+r[f]-(n?0:m[f]),A=z-k,B=k+j-(h===I?o:p)-z,C=x-(u.precedance===a||s===u[b]?y:0)-(t===O?i/2:0);return w?(C=(s===f?1:-1)*x,d[f]+=A>0?A:B>0?-B:0,d[f]=Math.max(-m[f]+r[f],k-C,Math.min(Math.max(-m[f]+r[f]+(h===I?o:p),k+C),d[f],"center"===s?k-x:1e9))):(e*=c===P?2:0,A>0&&(s!==f||B>0)?(d[f]-=C+e,l.invert(a,f)):B>0&&(s!==g||A>0)&&(d[f]-=(s===O?-C:C)+e,l.invert(a,g)),d[f]<q&&-d[f]>B&&(d[f]=k,l=u.clone())),d[f]-k}var k,l,m,n,o,p,q,r,s=e.target,t=c.elements.tooltip,u=e.my,v=e.at,w=e.adjust,x=w.method.split(" "),y=x[0],z=x[1]||x[0],A=e.viewport,B=e.container,C=(c.cache,{left:0,top:0});return A.jquery&&s[0]!==a&&s[0]!==b.body&&"none"!==w.method?(m=B.offset()||C,n="static"===B.css("position"),k="fixed"===t.css("position"),o=A[0]===a?A.width():A.outerWidth(E),p=A[0]===a?A.height():A.outerHeight(E),q={left:k?0:A.scrollLeft(),top:k?0:A.scrollTop()},r=A.offset()||C,("shift"!==y||"shift"!==z)&&(l=u.clone()),C={left:"none"!==y?j(G,H,y,w.x,L,N,I,f,h):0,top:"none"!==z?j(H,G,z,w.y,K,M,J,g,i):0,my:l}):C},R.polys={polygon:function(a,b){var c,d,e,f={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10},adjustable:E},g=0,h=[],i=1,j=1,k=0,l=0;for(g=a.length;g--;)c=[parseInt(a[--g],10),parseInt(a[g+1],10)],c[0]>f.position.right&&(f.position.right=c[0]),c[0]<f.position.left&&(f.position.left=c[0]),c[1]>f.position.bottom&&(f.position.bottom=c[1]),c[1]<f.position.top&&(f.position.top=c[1]),h.push(c);if(d=f.width=Math.abs(f.position.right-f.position.left),e=f.height=Math.abs(f.position.bottom-f.position.top),"c"===b.abbrev())f.position={left:f.position.left+f.width/2,top:f.position.top+f.height/2};else{for(;d>0&&e>0&&i>0&&j>0;)for(d=Math.floor(d/2),e=Math.floor(e/2),b.x===L?i=d:b.x===N?i=f.width-d:i+=Math.floor(d/2),b.y===K?j=e:b.y===M?j=f.height-e:j+=Math.floor(e/2),g=h.length;g--&&!(h.length<2);)k=h[g][0]-f.position.left,l=h[g][1]-f.position.top,(b.x===L&&k>=i||b.x===N&&i>=k||b.x===O&&(i>k||k>f.width-i)||b.y===K&&l>=j||b.y===M&&j>=l||b.y===O&&(j>l||l>f.height-j))&&h.splice(g,1);f.position={left:h[0][0],top:h[0][1]}}return f},rect:function(a,b,c,d){return{width:Math.abs(c-a),height:Math.abs(d-b),position:{left:Math.min(a,c),top:Math.min(b,d)}}},_angles:{tc:1.5,tr:7/4,tl:5/4,bc:.5,br:.25,bl:.75,rc:2,lc:1,c:0},ellipse:function(a,b,c,d,e){var f=R.polys._angles[e.abbrev()],g=0===f?0:c*Math.cos(f*Math.PI),h=d*Math.sin(f*Math.PI);return{width:2*c-Math.abs(g),height:2*d-Math.abs(h),position:{left:a+g,top:b+h},adjustable:E}},circle:function(a,b,c,d){return R.polys.ellipse(a,b,c,c,d)}},R.svg=function(a,c,e){for(var f,g,h,i,j,k,l,m,n,o=(d(b),c[0]),p=d(o.ownerSVGElement),q=o.ownerDocument,r=(parseInt(c.css("stroke-width"),10)||0)/2;!o.getBBox;)o=o.parentNode;if(!o.getBBox||!o.parentNode)return E;switch(o.nodeName){case"ellipse":case"circle":m=R.polys.ellipse(o.cx.baseVal.value,o.cy.baseVal.value,(o.rx||o.r).baseVal.value+r,(o.ry||o.r).baseVal.value+r,e);break;case"line":case"polygon":case"polyline":for(l=o.points||[{x:o.x1.baseVal.value,y:o.y1.baseVal.value},{x:o.x2.baseVal.value,y:o.y2.baseVal.value}],m=[],k=-1,i=l.numberOfItems||l.length;++k<i;)j=l.getItem?l.getItem(k):l[k],m.push.apply(m,[j.x,j.y]);m=R.polys.polygon(m,e);break;default:m=o.getBBox(),m={width:m.width,height:m.height,position:{left:m.x,top:m.y}}}return n=m.position,p=p[0],p.createSVGPoint&&(g=o.getScreenCTM(),l=p.createSVGPoint(),l.x=n.left,l.y=n.top,h=l.matrixTransform(g),n.left=h.x,n.top=h.y),q!==b&&"mouse"!==a.position.target&&(f=d((q.defaultView||q.parentWindow).frameElement).offset(),f&&(n.left+=f.left,n.top+=f.top)),q=d(q),n.left+=q.scrollLeft(),n.top+=q.scrollTop(),m},R.imagemap=function(a,b,c){b.jquery||(b=d(b));var e,f,g,h,i,j=(b.attr("shape")||"rect").toLowerCase().replace("poly","polygon"),k=d('img[usemap="#'+b.parent("map").attr("name")+'"]'),l=d.trim(b.attr("coords")),m=l.replace(/,$/,"").split(",");if(!k.length)return E;if("polygon"===j)h=R.polys.polygon(m,c);else{if(!R.polys[j])return E;for(g=-1,i=m.length,f=[];++g<i;)f.push(parseInt(m[g],10));h=R.polys[j].apply(this,f.concat(c))}return e=k.offset(),e.left+=Math.ceil((k.outerWidth(E)-k.width())/2),e.top+=Math.ceil((k.outerHeight(E)-k.height())/2),h.position.left+=e.left,h.position.top+=e.top,h};var Ab,Bb='<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>';d.extend(x.prototype,{_scroll:function(){var b=this.qtip.elements.overlay;b&&(b[0].style.top=d(a).scrollTop()+"px")},init:function(c){var e=c.tooltip;d("select, object").length<1&&(this.bgiframe=c.elements.bgiframe=d(Bb).appendTo(e),c._bind(e,"tooltipmove",this.adjustBGIFrame,this._ns,this)),this.redrawContainer=d("<div/>",{id:S+"-rcontainer"}).appendTo(b.body),c.elements.overlay&&c.elements.overlay.addClass("qtipmodal-ie6fix")&&(c._bind(a,["scroll","resize"],this._scroll,this._ns,this),c._bind(e,["tooltipshow"],this._scroll,this._ns,this)),this.redraw()},adjustBGIFrame:function(){var a,b,c=this.qtip.tooltip,d={height:c.outerHeight(E),width:c.outerWidth(E)},e=this.qtip.plugins.tip,f=this.qtip.elements.tip;b=parseInt(c.css("borderLeftWidth"),10)||0,b={left:-b,top:-b},e&&f&&(a="x"===e.corner.precedance?[I,L]:[J,K],b[a[1]]-=f[a[0]]()),this.bgiframe.css(b).css(d)},redraw:function(){if(this.qtip.rendered<1||this.drawing)return this;var a,b,c,d,e=this.qtip.tooltip,f=this.qtip.options.style,g=this.qtip.options.position.container;return this.qtip.drawing=1,f.height&&e.css(J,f.height),f.width?e.css(I,f.width):(e.css(I,"").appendTo(this.redrawContainer),b=e.width(),1>b%2&&(b+=1),c=e.css("maxWidth")||"",d=e.css("minWidth")||"",a=(c+d).indexOf("%")>-1?g.width()/100:0,c=(c.indexOf("%")>-1?a:1)*parseInt(c,10)||b,d=(d.indexOf("%")>-1?a:1)*parseInt(d,10)||0,b=c+d?Math.min(Math.max(b,d),c):b,e.css(I,Math.round(b)).appendTo(g)),this.drawing=0,this},destroy:function(){this.bgiframe&&this.bgiframe.remove(),this.qtip._unbind([a,this.qtip.tooltip],this._ns)}}),Ab=R.ie6=function(a){return 6===db.ie?new x(a):E},Ab.initialize="render",B.ie6={"^content|style$":function(){this.redraw()}}})}(window,document);
|
189 |
-
//# sourceMappingURL=jquery.qtip.min.js.map
|
190 |
</script>
|
166 |
*/
|
167 |
function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t<e.length;t++)i[t]=e[t];return i}return Array.from(e)}var _slice=Array.prototype.slice;!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],t):e.parsley=t(e.jQuery)}(this,function(e){"use strict";function t(e,t){return e.parsleyAdaptedCallback||(e.parsleyAdaptedCallback=function(){var i=Array.prototype.slice.call(arguments,0);i.unshift(this),e.apply(t||A,i)}),e.parsleyAdaptedCallback}function i(e){return 0===e.lastIndexOf(D,0)?e.substr(D.length):e}var n=1,r={},s={attr:function(e,t,i){var n,r,s,a=new RegExp("^"+t,"i");if("undefined"==typeof i)i={};else for(n in i)i.hasOwnProperty(n)&&delete i[n];if("undefined"==typeof e||"undefined"==typeof e[0])return i;for(s=e[0].attributes,n=s.length;n--;)r=s[n],r&&r.specified&&a.test(r.name)&&(i[this.camelize(r.name.slice(t.length))]=this.deserializeValue(r.value));return i},checkAttr:function(e,t,i){return e.is("["+t+i+"]")},setAttr:function(e,t,i,n){e[0].setAttribute(this.dasherize(t+i),String(n))},generateID:function(){return""+n++},deserializeValue:function(t){var i;try{return t?"true"==t||("false"==t?!1:"null"==t?null:isNaN(i=Number(t))?/^[\[\{]/.test(t)?e.parseJSON(t):t:i):t}catch(n){return t}},camelize:function(e){return e.replace(/-+(.)?/g,function(e,t){return t?t.toUpperCase():""})},dasherize:function(e){return e.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()},warn:function(){var e;window.console&&"function"==typeof window.console.warn&&(e=window.console).warn.apply(e,arguments)},warnOnce:function(e){r[e]||(r[e]=!0,this.warn.apply(this,arguments))},_resetWarnings:function(){r={}},trimString:function(e){return e.replace(/^\s+|\s+$/g,"")},namespaceEvents:function(t,i){return t=this.trimString(t||"").split(/\s+/),t[0]?e.map(t,function(e){return e+"."+i}).join(" "):""},objectCreate:Object.create||function(){var e=function(){};return function(t){if(arguments.length>1)throw Error("Second argument not supported");if("object"!=typeof t)throw TypeError("Argument must be an object");e.prototype=t;var i=new e;return e.prototype=null,i}}()},a=s,o={namespace:"data-parsley-",inputs:"input, textarea, select",excluded:"input[type=button], input[type=submit], input[type=reset], input[type=hidden]",priorityEnabled:!0,multiple:null,group:null,uiEnabled:!0,validationThreshold:3,focus:"first",trigger:!1,triggerAfterFailure:"input",errorClass:"parsley-error",successClass:"parsley-success",classHandler:function(e){},errorsContainer:function(e){},errorsWrapper:'<ul class="parsley-errors-list"></ul>',errorTemplate:"<li></li>"},l=function(){};l.prototype={asyncSupport:!0,actualizeOptions:function(){return a.attr(this.$element,this.options.namespace,this.domOptions),this.parent&&this.parent.actualizeOptions&&this.parent.actualizeOptions(),this},_resetOptions:function(e){this.domOptions=a.objectCreate(this.parent.options),this.options=a.objectCreate(this.domOptions);for(var t in e)e.hasOwnProperty(t)&&(this.options[t]=e[t]);this.actualizeOptions()},_listeners:null,on:function(e,t){this._listeners=this._listeners||{};var i=this._listeners[e]=this._listeners[e]||[];return i.push(t),this},subscribe:function(t,i){e.listenTo(this,t.toLowerCase(),i)},off:function(e,t){var i=this._listeners&&this._listeners[e];if(i)if(t)for(var n=i.length;n--;)i[n]===t&&i.splice(n,1);else delete this._listeners[e];return this},unsubscribe:function(t,i){e.unsubscribeTo(this,t.toLowerCase())},trigger:function(e,t,i){t=t||this;var n,r=this._listeners&&this._listeners[e];if(r)for(var s=r.length;s--;)if(n=r[s].call(t,t,i),n===!1)return n;return this.parent?this.parent.trigger(e,t,i):!0},reset:function(){if("ParsleyForm"!==this.__class__)return this._resetUI(),this._trigger("reset");for(var e=0;e<this.fields.length;e++)this.fields[e].reset();this._trigger("reset")},destroy:function(){if(this._destroyUI(),"ParsleyForm"!==this.__class__)return this.$element.removeData("Parsley"),this.$element.removeData("ParsleyFieldMultiple"),void this._trigger("destroy");for(var e=0;e<this.fields.length;e++)this.fields[e].destroy();this.$element.removeData("Parsley"),this._trigger("destroy")},asyncIsValid:function(e,t){return a.warnOnce("asyncIsValid is deprecated; please use whenValid instead"),this.whenValid({group:e,force:t})},_findRelated:function(){return this.options.multiple?this.parent.$element.find("["+this.options.namespace+'multiple="'+this.options.multiple+'"]'):this.$element}};var u={string:function(e){return e},integer:function(e){if(isNaN(e))throw'Requirement is not an integer: "'+e+'"';return parseInt(e,10)},number:function(e){if(isNaN(e))throw'Requirement is not a number: "'+e+'"';return parseFloat(e)},reference:function(t){var i=e(t);if(0===i.length)throw'No such reference: "'+t+'"';return i},"boolean":function(e){return"false"!==e},object:function(e){return a.deserializeValue(e)},regexp:function(e){var t="";return/^\/.*\/(?:[gimy]*)$/.test(e)?(t=e.replace(/.*\/([gimy]*)$/,"$1"),e=e.replace(new RegExp("^/(.*?)/"+t+"$"),"$1")):e="^"+e+"$",new RegExp(e,t)}},d=function(e,t){var i=e.match(/^\s*\[(.*)\]\s*$/);if(!i)throw'Requirement is not an array: "'+e+'"';var n=i[1].split(",").map(a.trimString);if(n.length!==t)throw"Requirement has "+n.length+" values when "+t+" are needed";return n},h=function(e,t){var i=u[e||"string"];if(!i)throw'Unknown requirement specification: "'+e+'"';return i(t)},p=function(e,t,i){var n=null,r={};for(var s in e)if(s){var a=i(s);"string"==typeof a&&(a=h(e[s],a)),r[s]=a}else n=h(e[s],t);return[n,r]},f=function(t){e.extend(!0,this,t)};f.prototype={validate:function(t,i){if(this.fn)return arguments.length>3&&(i=[].slice.call(arguments,1,-1)),this.fn.call(this,t,i);if(e.isArray(t)){if(!this.validateMultiple)throw"Validator `"+this.name+"` does not handle multiple values";return this.validateMultiple.apply(this,arguments)}if(this.validateNumber)return isNaN(t)?!1:(arguments[0]=parseFloat(arguments[0]),this.validateNumber.apply(this,arguments));if(this.validateString)return this.validateString.apply(this,arguments);throw"Validator `"+this.name+"` only handles multiple values"},parseRequirements:function(t,i){if("string"!=typeof t)return e.isArray(t)?t:[t];var n=this.requirementType;if(e.isArray(n)){for(var r=d(t,n.length),s=0;s<r.length;s++)r[s]=h(n[s],r[s]);return r}return e.isPlainObject(n)?p(n,t,i):[h(n,t)]},requirementType:"string",priority:2};var c=function(e,t){this.__class__="ParsleyValidatorRegistry",this.locale="en",this.init(e||{},t||{})},m={email:/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,number:/^-?(\d*\.)?\d+(e[-+]?\d+)?$/i,integer:/^-?\d+$/,digits:/^\d+$/,alphanum:/^\w+$/i,url:new RegExp("^(?:(?:https?|ftp)://)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/\\S*)?$","i")};m.range=m.number;var g=function(e){var t=(""+e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return t?Math.max(0,(t[1]?t[1].length:0)-(t[2]?+t[2]:0)):0};c.prototype={init:function(t,i){this.catalog=i,this.validators=e.extend({},this.validators);for(var n in t)this.addValidator(n,t[n].fn,t[n].priority);window.Parsley.trigger("parsley:validator:init")},setLocale:function(e){if("undefined"==typeof this.catalog[e])throw new Error(e+" is not available in the catalog");return this.locale=e,this},addCatalog:function(e,t,i){return"object"==typeof t&&(this.catalog[e]=t),!0===i?this.setLocale(e):this},addMessage:function(e,t,i){return"undefined"==typeof this.catalog[e]&&(this.catalog[e]={}),this.catalog[e][t]=i,this},addMessages:function(e,t){for(var i in t)this.addMessage(e,i,t[i]);return this},addValidator:function(e,t,i){if(this.validators[e])a.warn('Validator "'+e+'" is already defined.');else if(o.hasOwnProperty(e))return void a.warn('"'+e+'" is a restricted keyword and is not a valid validator name.');return this._setValidator.apply(this,arguments)},updateValidator:function(e,t,i){return this.validators[e]?this._setValidator(this,arguments):(a.warn('Validator "'+e+'" is not already defined.'),this.addValidator.apply(this,arguments))},removeValidator:function(e){return this.validators[e]||a.warn('Validator "'+e+'" is not defined.'),delete this.validators[e],this},_setValidator:function(e,t,i){"object"!=typeof t&&(t={fn:t,priority:i}),t.validate||(t=new f(t)),this.validators[e]=t;for(var n in t.messages||{})this.addMessage(n,e,t.messages[n]);return this},getErrorMessage:function(e){var t;if("type"===e.name){var i=this.catalog[this.locale][e.name]||{};t=i[e.requirements]}else t=this.formatMessage(this.catalog[this.locale][e.name],e.requirements);return t||this.catalog[this.locale].defaultMessage||this.catalog.en.defaultMessage},formatMessage:function(e,t){if("object"==typeof t){for(var i in t)e=this.formatMessage(e,t[i]);return e}return"string"==typeof e?e.replace(/%s/i,t):""},validators:{notblank:{validateString:function(e){return/\S/.test(e)},priority:2},required:{validateMultiple:function(e){return e.length>0},validateString:function(e){return/\S/.test(e)},priority:512},type:{validateString:function(e,t){var i=arguments.length<=2||void 0===arguments[2]?{}:arguments[2],n=i.step,r=void 0===n?"1":n,s=i.base,a=void 0===s?0:s,o=m[t];if(!o)throw new Error("validator type `"+t+"` is not supported");if(!o.test(e))return!1;if("number"===t&&!/^any$/i.test(r||"")){var l=Number(e),u=Math.max(g(r),g(a));if(g(l)>u)return!1;var d=function(e){return Math.round(e*Math.pow(10,u))};if((d(l)-d(a))%d(r)!=0)return!1}return!0},requirementType:{"":"string",step:"string",base:"number"},priority:256},pattern:{validateString:function(e,t){return t.test(e)},requirementType:"regexp",priority:64},minlength:{validateString:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxlength:{validateString:function(e,t){return e.length<=t},requirementType:"integer",priority:30},length:{validateString:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},mincheck:{validateMultiple:function(e,t){return e.length>=t},requirementType:"integer",priority:30},maxcheck:{validateMultiple:function(e,t){return e.length<=t},requirementType:"integer",priority:30},check:{validateMultiple:function(e,t,i){return e.length>=t&&e.length<=i},requirementType:["integer","integer"],priority:30},min:{validateNumber:function(e,t){return e>=t},requirementType:"number",priority:30},max:{validateNumber:function(e,t){return t>=e},requirementType:"number",priority:30},range:{validateNumber:function(e,t,i){return e>=t&&i>=e},requirementType:["number","number"],priority:30},equalto:{validateString:function(t,i){var n=e(i);return n.length?t===n.val():t===i},priority:256}}};var y={},v=function T(e,t,i){for(var n=[],r=[],s=0;s<e.length;s++){for(var a=!1,o=0;o<t.length;o++)if(e[s].assert.name===t[o].assert.name){a=!0;break}a?r.push(e[s]):n.push(e[s])}return{kept:r,added:n,removed:i?[]:T(t,e,!0).added}};y.Form={_actualizeTriggers:function(){var e=this;this.$element.on("submit.Parsley",function(t){e.onSubmitValidate(t)}),this.$element.on("click.Parsley",'input[type="submit"], button[type="submit"]',function(t){e.onSubmitButton(t)}),!1!==this.options.uiEnabled&&this.$element.attr("novalidate","")},focus:function(){if(this._focusedField=null,!0===this.validationResult||"none"===this.options.focus)return null;for(var e=0;e<this.fields.length;e++){var t=this.fields[e];if(!0!==t.validationResult&&t.validationResult.length>0&&"undefined"==typeof t.options.noFocus&&(this._focusedField=t.$element,"first"===this.options.focus))break}return null===this._focusedField?null:this._focusedField.focus()},_destroyUI:function(){this.$element.off(".Parsley")}},y.Field={_reflowUI:function(){if(this._buildUI(),this._ui){var e=v(this.validationResult,this._ui.lastValidationResult);this._ui.lastValidationResult=this.validationResult,this._manageStatusClass(),this._manageErrorsMessages(e),this._actualizeTriggers(),!e.kept.length&&!e.added.length||this._failedOnce||(this._failedOnce=!0,this._actualizeTriggers())}},getErrorsMessages:function(){if(!0===this.validationResult)return[];for(var e=[],t=0;t<this.validationResult.length;t++)e.push(this.validationResult[t].errorMessage||this._getErrorMessage(this.validationResult[t].assert));return e},addError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r?!0:r;this._buildUI(),this._addError(e,{message:i,assert:n}),s&&this._errorClass()},updateError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.message,n=t.assert,r=t.updateClass,s=void 0===r?!0:r;this._buildUI(),this._updateError(e,{message:i,assert:n}),s&&this._errorClass()},removeError:function(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],i=t.updateClass,n=void 0===i?!0:i;this._buildUI(),this._removeError(e),n&&this._manageStatusClass()},_manageStatusClass:function(){this.hasConstraints()&&this.needsValidation()&&!0===this.validationResult?this._successClass():this.validationResult.length>0?this._errorClass():this._resetClass()},_manageErrorsMessages:function(t){if("undefined"==typeof this.options.errorsMessagesDisabled){if("undefined"!=typeof this.options.errorMessage)return t.added.length||t.kept.length?(this._insertErrorWrapper(),0===this._ui.$errorsWrapper.find(".parsley-custom-error-message").length&&this._ui.$errorsWrapper.append(e(this.options.errorTemplate).addClass("parsley-custom-error-message")),this._ui.$errorsWrapper.addClass("filled").find(".parsley-custom-error-message").html(this.options.errorMessage)):this._ui.$errorsWrapper.removeClass("filled").find(".parsley-custom-error-message").remove();for(var i=0;i<t.removed.length;i++)this._removeError(t.removed[i].assert.name);for(i=0;i<t.added.length;i++)this._addError(t.added[i].assert.name,{message:t.added[i].errorMessage,assert:t.added[i].assert});for(i=0;i<t.kept.length;i++)this._updateError(t.kept[i].assert.name,{message:t.kept[i].errorMessage,assert:t.kept[i].assert})}},_addError:function(t,i){var n=i.message,r=i.assert;this._insertErrorWrapper(),this._ui.$errorsWrapper.addClass("filled").append(e(this.options.errorTemplate).addClass("parsley-"+t).html(n||this._getErrorMessage(r)))},_updateError:function(e,t){var i=t.message,n=t.assert;this._ui.$errorsWrapper.addClass("filled").find(".parsley-"+e).html(i||this._getErrorMessage(n))},_removeError:function(e){this._ui.$errorsWrapper.removeClass("filled").find(".parsley-"+e).remove()},_getErrorMessage:function(e){var t=e.name+"Message";return"undefined"!=typeof this.options[t]?window.Parsley.formatMessage(this.options[t],e.requirements):window.Parsley.getErrorMessage(e)},_buildUI:function(){if(!this._ui&&!1!==this.options.uiEnabled){var t={};this.$element.attr(this.options.namespace+"id",this.__id__),t.$errorClassHandler=this._manageClassHandler(),t.errorsWrapperId="parsley-id-"+(this.options.multiple?"multiple-"+this.options.multiple:this.__id__),t.$errorsWrapper=e(this.options.errorsWrapper).attr("id",t.errorsWrapperId),t.lastValidationResult=[],t.validationInformationVisible=!1,this._ui=t}},_manageClassHandler:function(){if("string"==typeof this.options.classHandler&&e(this.options.classHandler).length)return e(this.options.classHandler);var t=this.options.classHandler.call(this,this);return"undefined"!=typeof t&&t.length?t:!this.options.multiple||this.$element.is("select")?this.$element:this.$element.parent()},_insertErrorWrapper:function(){var t;if(0!==this._ui.$errorsWrapper.parent().length)return this._ui.$errorsWrapper.parent();if("string"==typeof this.options.errorsContainer){if(e(this.options.errorsContainer).length)return e(this.options.errorsContainer).append(this._ui.$errorsWrapper);a.warn("The errors container `"+this.options.errorsContainer+"` does not exist in DOM")}else"function"==typeof this.options.errorsContainer&&(t=this.options.errorsContainer.call(this,this));if("undefined"!=typeof t&&t.length)return t.append(this._ui.$errorsWrapper);var i=this.$element;return this.options.multiple&&(i=i.parent()),i.after(this._ui.$errorsWrapper)},_actualizeTriggers:function(){var e=this,t=this._findRelated();t.off(".Parsley"),this._failedOnce?t.on(a.namespaceEvents(this.options.triggerAfterFailure,"Parsley"),function(){e.validate()}):t.on(a.namespaceEvents(this.options.trigger,"Parsley"),function(t){e._eventValidate(t)})},_eventValidate:function(e){(!/key|input/.test(e.type)||this._ui&&this._ui.validationInformationVisible||!(this.getValue().length<=this.options.validationThreshold))&&this.validate()},_resetUI:function(){this._failedOnce=!1,this._actualizeTriggers(),"undefined"!=typeof this._ui&&(this._ui.$errorsWrapper.removeClass("filled").children().remove(),this._resetClass(),this._ui.lastValidationResult=[],this._ui.validationInformationVisible=!1)},_destroyUI:function(){this._resetUI(),"undefined"!=typeof this._ui&&this._ui.$errorsWrapper.remove(),delete this._ui},_successClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.errorClass).addClass(this.options.successClass)},_errorClass:function(){this._ui.validationInformationVisible=!0,this._ui.$errorClassHandler.removeClass(this.options.successClass).addClass(this.options.errorClass)},_resetClass:function(){this._ui.$errorClassHandler.removeClass(this.options.successClass).removeClass(this.options.errorClass)}};var _=function(t,i,n){this.__class__="ParsleyForm",this.__id__=a.generateID(),this.$element=e(t),this.domOptions=i,this.options=n,this.parent=window.Parsley,this.fields=[],this.validationResult=null},w={pending:null,resolved:!0,rejected:!1};_.prototype={onSubmitValidate:function(e){var t=this;if(!0!==e.parsley){var i=this._$submitSource||this.$element.find('input[type="submit"], button[type="submit"]').first();if(this._$submitSource=null,this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!0),!i.is("[formnovalidate]")){var n=this.whenValidate({event:e});"resolved"===n.state()&&!1!==this._trigger("submit")||(e.stopImmediatePropagation(),e.preventDefault(),"pending"===n.state()&&n.done(function(){t._submit(i)}))}}},onSubmitButton:function(t){this._$submitSource=e(t.target)},_submit:function(t){if(!1!==this._trigger("submit")){if(t){var i=this.$element.find(".parsley-synthetic-submit-button").prop("disabled",!1);0===i.length&&(i=e('<input class="parsley-synthetic-submit-button" type="hidden">').appendTo(this.$element)),i.attr({name:t.attr("name"),value:t.attr("value")})}this.$element.trigger(e.extend(e.Event("submit"),{parsley:!0}))}},validate:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling validate on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1],s=i[2];t={group:n,force:r,event:s}}return w[this.whenValidate(t).state()]},whenValidate:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force,s=i.event;this.submitEvent=s,s&&(this.submitEvent=e.extend({},s,{preventDefault:function(){a.warnOnce("Using `this.submitEvent.preventDefault()` is deprecated; instead, call `this.validationResult = false`"),t.validationResult=!1}})),this.validationResult=!0,this._trigger("validate"),this._refreshFields();var o=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValidate({force:r,group:n})})}),l=function(){var i=e.Deferred();return!1===t.validationResult&&i.reject(),i.resolve().promise()};return e.when.apply(e,_toConsumableArray(o)).done(function(){t._trigger("success")}).fail(function(){t.validationResult=!1,t.focus(),t._trigger("error")}).always(function(){t._trigger("validated")}).pipe(l,l)},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley form without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={group:n,force:r}}return w[this.whenValid(t).state()]},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.group,r=i.force;this._refreshFields();var s=this._withoutReactualizingFormOptions(function(){return e.map(t.fields,function(e){return e.whenValid({group:n,force:r})})});return e.when.apply(e,_toConsumableArray(s))},_refreshFields:function(){return this.actualizeOptions()._bindFields()},_bindFields:function(){var t=this,i=this.fields;return this.fields=[],this.fieldsMappedById={},this._withoutReactualizingFormOptions(function(){t.$element.find(t.options.inputs).not(t.options.excluded).each(function(e,i){var n=new window.Parsley.Factory(i,{},t);"ParsleyField"!==n.__class__&&"ParsleyFieldMultiple"!==n.__class__||!0===n.options.excluded||"undefined"==typeof t.fieldsMappedById[n.__class__+"-"+n.__id__]&&(t.fieldsMappedById[n.__class__+"-"+n.__id__]=n,t.fields.push(n))}),e(i).not(t.fields).each(function(e,t){t._trigger("reset")})}),this},_withoutReactualizingFormOptions:function(e){var t=this.actualizeOptions;this.actualizeOptions=function(){return this};var i=e();return this.actualizeOptions=t,i},_trigger:function(e){return this.trigger("form:"+e)}};var b=function(t,i,n,r,s){if(!/ParsleyField/.test(t.__class__))throw new Error("ParsleyField or ParsleyFieldMultiple instance expected");var a=window.Parsley._validatorRegistry.validators[i],o=new f(a);e.extend(this,{validator:o,name:i,requirements:n,priority:r||t.options[i+"Priority"]||o.priority,isDomConstraint:!0===s}),this._parseRequirements(t.options)},F=function(e){var t=e[0].toUpperCase();return t+e.slice(1)};b.prototype={validate:function(e,t){var i=this.requirementList.slice(0);return i.unshift(e),i.push(t),this.validator.validate.apply(this.validator,i)},_parseRequirements:function(e){var t=this;this.requirementList=this.validator.parseRequirements(this.requirements,function(i){return e[t.name+F(i)]})}};var C=function(t,i,n,r){this.__class__="ParsleyField",this.__id__=a.generateID(),this.$element=e(t),"undefined"!=typeof r&&(this.parent=r),this.options=n,this.domOptions=i,this.constraints=[],this.constraintsByName={},this.validationResult=[],this._bindConstraints()},$={pending:null,resolved:!0,rejected:!1};C.prototype={validate:function(t){arguments.length>=1&&!e.isPlainObject(t)&&(a.warnOnce("Calling validate on a parsley field without passing arguments as an object is deprecated."),t={options:t});var i=this.whenValidate(t);if(!i)return!0;switch(i.state()){case"pending":return null;case"resolved":return!0;case"rejected":return this.validationResult}},whenValidate:function(){var e=this,t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],i=t.force,n=t.group;return this.refreshConstraints(),!n||this._isInGroup(n)?(this.value=this.getValue(),this._trigger("validate"),this.whenValid({force:i,value:this.value,_refreshed:!0}).always(function(){e._reflowUI()}).done(function(){e._trigger("success")}).fail(function(){e._trigger("error")}).always(function(){e._trigger("validated")})):void 0},hasConstraints:function(){return 0!==this.constraints.length},needsValidation:function(e){return"undefined"==typeof e&&(e=this.getValue()),e.length||this._isRequired()||"undefined"!=typeof this.options.validateIfEmpty?!0:!1},_isInGroup:function(t){return e.isArray(this.options.group)?-1!==e.inArray(t,this.options.group):this.options.group===t},isValid:function(t){if(arguments.length>=1&&!e.isPlainObject(t)){a.warnOnce("Calling isValid on a parsley field without passing arguments as an object is deprecated.");var i=_slice.call(arguments),n=i[0],r=i[1];t={force:n,value:r}}var s=this.whenValid(t);return s?$[s.state()]:!0},whenValid:function(){var t=this,i=arguments.length<=0||void 0===arguments[0]?{}:arguments[0],n=i.force,r=void 0===n?!1:n,s=i.value,a=i.group,o=i._refreshed;if(o||this.refreshConstraints(),!a||this._isInGroup(a)){if(this.validationResult=!0,!this.hasConstraints())return e.when();if(("undefined"==typeof s||null===s)&&(s=this.getValue()),!this.needsValidation(s)&&!0!==r)return e.when();var l=this._getGroupedConstraints(),u=[];return e.each(l,function(i,n){var r=e.when.apply(e,_toConsumableArray(e.map(n,function(e){return t._validateConstraint(s,e)})));return u.push(r),"rejected"===r.state()?!1:void 0}),e.when.apply(e,u)}},_validateConstraint:function(t,i){var n=this,r=i.validate(t,this);return!1===r&&(r=e.Deferred().reject()),e.when(r).fail(function(e){!0===n.validationResult&&(n.validationResult=[]),n.validationResult.push({assert:i,errorMessage:"string"==typeof e&&e})})},getValue:function(){var e;return e="function"==typeof this.options.value?this.options.value(this):"undefined"!=typeof this.options.value?this.options.value:this.$element.val(),"undefined"==typeof e||null===e?"":this._handleWhitespace(e)},refreshConstraints:function(){return this.actualizeOptions()._bindConstraints()},addConstraint:function(e,t,i,n){if(window.Parsley._validatorRegistry.validators[e]){var r=new b(this,e,t,i,n);"undefined"!==this.constraintsByName[r.name]&&this.removeConstraint(r.name),this.constraints.push(r),this.constraintsByName[r.name]=r}return this},removeConstraint:function(e){for(var t=0;t<this.constraints.length;t++)if(e===this.constraints[t].name){this.constraints.splice(t,1);break}return delete this.constraintsByName[e],this},updateConstraint:function(e,t,i){return this.removeConstraint(e).addConstraint(e,t,i)},_bindConstraints:function(){for(var e=[],t={},i=0;i<this.constraints.length;i++)!1===this.constraints[i].isDomConstraint&&(e.push(this.constraints[i]),t[this.constraints[i].name]=this.constraints[i]);this.constraints=e,this.constraintsByName=t;for(var n in this.options)this.addConstraint(n,this.options[n],void 0,!0);return this._bindHtml5Constraints()},_bindHtml5Constraints:function(){(this.$element.hasClass("required")||this.$element.attr("required"))&&this.addConstraint("required",!0,void 0,!0),"string"==typeof this.$element.attr("pattern")&&this.addConstraint("pattern",this.$element.attr("pattern"),void 0,!0),"undefined"!=typeof this.$element.attr("min")&&"undefined"!=typeof this.$element.attr("max")?this.addConstraint("range",[this.$element.attr("min"),this.$element.attr("max")],void 0,!0):"undefined"!=typeof this.$element.attr("min")?this.addConstraint("min",this.$element.attr("min"),void 0,!0):"undefined"!=typeof this.$element.attr("max")&&this.addConstraint("max",this.$element.attr("max"),void 0,!0),"undefined"!=typeof this.$element.attr("minlength")&&"undefined"!=typeof this.$element.attr("maxlength")?this.addConstraint("length",[this.$element.attr("minlength"),this.$element.attr("maxlength")],void 0,!0):"undefined"!=typeof this.$element.attr("minlength")?this.addConstraint("minlength",this.$element.attr("minlength"),void 0,!0):"undefined"!=typeof this.$element.attr("maxlength")&&this.addConstraint("maxlength",this.$element.attr("maxlength"),void 0,!0);var e=this.$element.attr("type");return"undefined"==typeof e?this:"number"===e?this.addConstraint("type",["number",{step:this.$element.attr("step"),base:this.$element.attr("min")||this.$element.attr("value")}],void 0,!0):/^(email|url|range)$/i.test(e)?this.addConstraint("type",e,void 0,!0):this},_isRequired:function(){return"undefined"==typeof this.constraintsByName.required?!1:!1!==this.constraintsByName.required.requirements},_trigger:function(e){return this.trigger("field:"+e)},_handleWhitespace:function(e){return!0===this.options.trimValue&&a.warnOnce('data-parsley-trim-value="true" is deprecated, please use data-parsley-whitespace="trim"'),"squish"===this.options.whitespace&&(e=e.replace(/\s{2,}/g," ")),("trim"===this.options.whitespace||"squish"===this.options.whitespace||!0===this.options.trimValue)&&(e=a.trimString(e)),e},_getGroupedConstraints:function(){if(!1===this.options.priorityEnabled)return[this.constraints];for(var e=[],t={},i=0;i<this.constraints.length;i++){var n=this.constraints[i].priority;t[n]||e.push(t[n]=[]),t[n].push(this.constraints[i])}return e.sort(function(e,t){return t[0].priority-e[0].priority}),e}};var x=C,P=function(){this.__class__="ParsleyFieldMultiple"};P.prototype={addElement:function(e){return this.$elements.push(e),this},refreshConstraints:function(){var t;if(this.constraints=[],this.$element.is("select"))return this.actualizeOptions()._bindConstraints(),this;for(var i=0;i<this.$elements.length;i++)if(e("html").has(this.$elements[i]).length){t=this.$elements[i].data("ParsleyFieldMultiple").refreshConstraints().constraints;for(var n=0;n<t.length;n++)this.addConstraint(t[n].name,t[n].requirements,t[n].priority,t[n].isDomConstraint)}else this.$elements.splice(i,1);return this},getValue:function(){if("function"==typeof this.options.value)value=this.options.value(this);else if("undefined"!=typeof this.options.value)return this.options.value;if(this.$element.is("input[type=radio]"))return this._findRelated().filter(":checked").val()||"";if(this.$element.is("input[type=checkbox]")){var t=[];return this._findRelated().filter(":checked").each(function(){t.push(e(this).val())}),t}return this.$element.is("select")&&null===this.$element.val()?[]:this.$element.val()},_init:function(){return this.$elements=[this.$element],this}};var E=function(t,i,n){this.$element=e(t);var r=this.$element.data("Parsley");if(r)return"undefined"!=typeof n&&r.parent===window.Parsley&&(r.parent=n,r._resetOptions(r.options)),r;if(!this.$element.length)throw new Error("You must bind Parsley on an existing element.");if("undefined"!=typeof n&&"ParsleyForm"!==n.__class__)throw new Error("Parent instance must be a ParsleyForm instance");return this.parent=n||window.Parsley,this.init(i)};E.prototype={init:function(e){return this.__class__="Parsley",this.__version__="2.3.5",this.__id__=a.generateID(),this._resetOptions(e),this.$element.is("form")||a.checkAttr(this.$element,this.options.namespace,"validate")&&!this.$element.is(this.options.inputs)?this.bind("parsleyForm"):this.isMultiple()?this.handleMultiple():this.bind("parsleyField")},isMultiple:function(){return this.$element.is("input[type=radio], input[type=checkbox]")||this.$element.is("select")&&"undefined"!=typeof this.$element.attr("multiple")},handleMultiple:function(){var t,i,n=this;if(this.options.multiple||("undefined"!=typeof this.$element.attr("name")&&this.$element.attr("name").length?this.options.multiple=t=this.$element.attr("name"):"undefined"!=typeof this.$element.attr("id")&&this.$element.attr("id").length&&(this.options.multiple=this.$element.attr("id"))),this.$element.is("select")&&"undefined"!=typeof this.$element.attr("multiple"))return this.options.multiple=this.options.multiple||this.__id__,this.bind("parsleyFieldMultiple");if(!this.options.multiple)return a.warn("To be bound by Parsley, a radio, a checkbox and a multiple select input must have either a name or a multiple option.",this.$element),this;this.options.multiple=this.options.multiple.replace(/(:|\.|\[|\]|\{|\}|\$)/g,""),
|
168 |
"undefined"!=typeof t&&e('input[name="'+t+'"]').each(function(t,i){e(i).is("input[type=radio], input[type=checkbox]")&&e(i).attr(n.options.namespace+"multiple",n.options.multiple)});for(var r=this._findRelated(),s=0;s<r.length;s++)if(i=e(r.get(s)).data("Parsley"),"undefined"!=typeof i){this.$element.data("ParsleyFieldMultiple")||i.addElement(this.$element);break}return this.bind("parsleyField",!0),i||this.bind("parsleyFieldMultiple")},bind:function(t,i){var n;switch(t){case"parsleyForm":n=e.extend(new _(this.$element,this.domOptions,this.options),window.ParsleyExtend)._bindFields();break;case"parsleyField":n=e.extend(new x(this.$element,this.domOptions,this.options,this.parent),window.ParsleyExtend);break;case"parsleyFieldMultiple":n=e.extend(new x(this.$element,this.domOptions,this.options,this.parent),new P,window.ParsleyExtend)._init();break;default:throw new Error(t+"is not a supported Parsley type")}return this.options.multiple&&a.setAttr(this.$element,this.options.namespace,"multiple",this.options.multiple),"undefined"!=typeof i?(this.$element.data("ParsleyFieldMultiple",n),n):(this.$element.data("Parsley",n),n._actualizeTriggers(),n._trigger("init"),n)}};var V=e.fn.jquery.split(".");if(parseInt(V[0])<=1&&parseInt(V[1])<8)throw"The loaded version of jQuery is too old. Please upgrade to 1.8.x or better.";V.forEach||a.warn("Parsley requires ES5 to run properly. Please include https://github.com/es-shims/es5-shim");var M=e.extend(new l,{$element:e(document),actualizeOptions:null,_resetOptions:null,Factory:E,version:"2.3.5"});e.extend(x.prototype,y.Field,l.prototype),e.extend(_.prototype,y.Form,l.prototype),e.extend(E.prototype,l.prototype),e.fn.parsley=e.fn.psly=function(t){if(this.length>1){var i=[];return this.each(function(){i.push(e(this).parsley(t))}),i}return e(this).length?new E(this,t):void a.warn("You must bind Parsley on an existing element.")},"undefined"==typeof window.ParsleyExtend&&(window.ParsleyExtend={}),M.options=e.extend(a.objectCreate(o),window.ParsleyConfig),window.ParsleyConfig=M.options,window.Parsley=window.psly=M,window.ParsleyUtils=a;var O=window.Parsley._validatorRegistry=new c(window.ParsleyConfig.validators,window.ParsleyConfig.i18n);window.ParsleyValidator={},e.each("setLocale addCatalog addMessage addMessages getErrorMessage formatMessage addValidator updateValidator removeValidator".split(" "),function(t,i){window.Parsley[i]=e.proxy(O,i),window.ParsleyValidator[i]=function(){var e;return a.warnOnce("Accessing the method '"+i+"' through ParsleyValidator is deprecated. Simply call 'window.Parsley."+i+"(...)'"),(e=window.Parsley)[i].apply(e,arguments)}}),window.Parsley.UI=y,window.ParsleyUI={removeError:function(e,t,i){var n=!0!==i;return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'removeError' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e.removeError(t,{updateClass:n})},getErrorsMessages:function(e){return a.warnOnce("Accessing ParsleyUI is deprecated. Call 'getErrorsMessages' on the instance directly."),e.getErrorsMessages()}},e.each("addError updateError".split(" "),function(e,t){window.ParsleyUI[t]=function(e,i,n,r,s){var o=!0!==s;return a.warnOnce("Accessing ParsleyUI is deprecated. Call '"+t+"' on the instance directly. Please comment in issue 1073 as to your need to call this method."),e[t](i,{message:n,assert:r,updateClass:o})}}),/firefox/i.test(navigator.userAgent)&&e(document).on("change","select",function(t){e(t.target).trigger("input")}),!1!==window.ParsleyConfig.autoBind&&e(function(){e("[data-parsley-validate]").length&&e("[data-parsley-validate]").parsley()});var A=e({}),R=function(){a.warnOnce("Parsley's pubsub module is deprecated; use the 'on' and 'off' methods on parsley instances or window.Parsley")},D="parsley:";e.listen=function(e,n){var r;if(R(),"object"==typeof arguments[1]&&"function"==typeof arguments[2]&&(r=arguments[1],n=arguments[2]),"function"!=typeof n)throw new Error("Wrong parameters");window.Parsley.on(i(e),t(n,r))},e.listenTo=function(e,n,r){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");if("string"!=typeof n||"function"!=typeof r)throw new Error("Wrong parameters");e.on(i(n),t(r))},e.unsubscribe=function(e,t){if(R(),"string"!=typeof e||"function"!=typeof t)throw new Error("Wrong arguments");window.Parsley.off(i(e),t.parsleyAdaptedCallback)},e.unsubscribeTo=function(e,t){if(R(),!(e instanceof x||e instanceof _))throw new Error("Must give Parsley instance");e.off(i(t))},e.unsubscribeAll=function(t){R(),window.Parsley.off(i(t)),e("form,input,textarea,select").each(function(){var n=e(this).data("Parsley");n&&n.off(i(t))})},e.emit=function(e,t){var n;R();var r=t instanceof x||t instanceof _,s=Array.prototype.slice.call(arguments,r?2:1);s.unshift(i(e)),r||(t=window.Parsley),(n=t).trigger.apply(n,_toConsumableArray(s))};e.extend(!0,M,{asyncValidators:{"default":{fn:function(e){return e.status>=200&&e.status<300},url:!1},reverse:{fn:function(e){return e.status<200||e.status>=300},url:!1}},addAsyncValidator:function(e,t,i,n){return M.asyncValidators[e]={fn:t,url:i||!1,options:n||{}},this}}),M.addValidator("remote",{requirementType:{"":"string",validator:"string",reverse:"boolean",options:"object"},validateString:function(t,i,n,r){var s,a,o={},l=n.validator||(!0===n.reverse?"reverse":"default");if("undefined"==typeof M.asyncValidators[l])throw new Error("Calling an undefined async validator: `"+l+"`");i=M.asyncValidators[l].url||i,i.indexOf("{value}")>-1?i=i.replace("{value}",encodeURIComponent(t)):o[r.$element.attr("name")||r.$element.attr("id")]=t;var u=e.extend(!0,n.options||{},M.asyncValidators[l].options);s=e.extend(!0,{},{url:i,data:o,type:"GET"},u),r.trigger("field:ajaxoptions",r,s),a=e.param(s),"undefined"==typeof M._remoteCache&&(M._remoteCache={});var d=M._remoteCache[a]=M._remoteCache[a]||e.ajax(s),h=function(){var t=M.asyncValidators[l].fn.call(r,d,i,n);return t||(t=e.Deferred().reject()),e.when(t)};return d.then(h,h)},priority:-1}),M.on("form:submit",function(){M._remoteCache={}}),window.ParsleyExtend.addAsyncValidator=function(){return ParsleyUtils.warnOnce("Accessing the method `addAsyncValidator` through an instance is deprecated. Simply call `Parsley.addAsyncValidator(...)`"),M.addAsyncValidator.apply(M,arguments)},M.addMessages("en",{defaultMessage:"This value seems to be invalid.",type:{email:"This value should be a valid email.",url:"This value should be a valid url.",number:"This value should be a valid number.",integer:"This value should be a valid integer.",digits:"This value should be digits.",alphanum:"This value should be alphanumeric."},notblank:"This value should not be blank.",required:"This value is required.",pattern:"This value seems to be invalid.",min:"This value should be greater than or equal to %s.",max:"This value should be lower than or equal to %s.",range:"This value should be between %s and %s.",minlength:"This value is too short. It should have %s characters or more.",maxlength:"This value is too long. It should have %s characters or fewer.",length:"This value length is invalid. It should be between %s and %s characters long.",mincheck:"You must select at least %s choices.",maxcheck:"You must select %s choices or fewer.",check:"You must select between %s and %s choices.",equalto:"This value should be the same."}),M.setLocale("en");var q=M;return q});
|
|
|
169 |
</script>
|
170 |
|
171 |
|
185 |
|
186 |
!function(a,b,c){!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)}(function(d){"use strict";function e(a,b,c,e){this.id=c,this.target=a,this.tooltip=F,this.elements={target:a},this._id=S+"-"+c,this.timers={img:{}},this.options=b,this.plugins={},this.cache={event:{},target:d(),disabled:E,attr:e,onTooltip:E,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=E}function f(a){return a===F||"object"!==d.type(a)}function g(a){return!(d.isFunction(a)||a&&a.attr||a.length||"object"===d.type(a)&&(a.jquery||a.then))}function h(a){var b,c,e,h;return f(a)?E:(f(a.metadata)&&(a.metadata={type:a.metadata}),"content"in a&&(b=a.content,f(b)||b.jquery||b.done?b=a.content={text:c=g(b)?E:b}:c=b.text,"ajax"in b&&(e=b.ajax,h=e&&e.once!==E,delete b.ajax,b.text=function(a,b){var f=c||d(this).attr(b.options.content.attr)||"Loading...",g=d.ajax(d.extend({},e,{context:b})).then(e.success,F,e.error).then(function(a){return a&&h&&b.set("content.text",a),a},function(a,c,d){b.destroyed||0===a.status||b.set("content.text",c+": "+d)});return h?f:(b.set("content.text",f),g)}),"title"in b&&(d.isPlainObject(b.title)&&(b.button=b.title.button,b.title=b.title.text),g(b.title||E)&&(b.title=E))),"position"in a&&f(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&f(a.show)&&(a.show=a.show.jquery?{target:a.show}:a.show===D?{ready:D}:{event:a.show}),"hide"in a&&f(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&f(a.style)&&(a.style={classes:a.style}),d.each(R,function(){this.sanitize&&this.sanitize(a)}),a)}function i(a,b){for(var c,d=0,e=a,f=b.split(".");e=e[f[d++]];)d<f.length&&(c=e);return[c||a,f.pop()]}function j(a,b){var c,d,e;for(c in this.checks)for(d in this.checks[c])(e=new RegExp(d,"i").exec(a))&&(b.push(e),("builtin"===c||this.plugins[c])&&this.checks[c][d].apply(this.plugins[c]||this,b))}function k(a){return V.concat("").join(a?"-"+a+" ":" ")}function l(a,b){return b>0?setTimeout(d.proxy(a,this),b):void a.call(this)}function m(a){this.tooltip.hasClass(ab)||(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=l.call(this,function(){this.toggle(D,a)},this.options.show.delay))}function n(a){if(!this.tooltip.hasClass(ab)&&!this.destroyed){var b=d(a.relatedTarget),c=b.closest(W)[0]===this.tooltip[0],e=b[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==b[0]&&"mouse"===this.options.position.target&&c||this.options.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(c||e))try{a.preventDefault(),a.stopImmediatePropagation()}catch(f){}else this.timers.hide=l.call(this,function(){this.toggle(E,a)},this.options.hide.delay,this)}}function o(a){!this.tooltip.hasClass(ab)&&this.options.hide.inactive&&(clearTimeout(this.timers.inactive),this.timers.inactive=l.call(this,function(){this.hide(a)},this.options.hide.inactive))}function p(a){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(a)}function q(a,c,e){d(b.body).delegate(a,(c.split?c:c.join("."+S+" "))+"."+S,function(){var a=y.api[d.attr(this,U)];a&&!a.disabled&&e.apply(a,arguments)})}function r(a,c,f){var g,i,j,k,l,m=d(b.body),n=a[0]===b?m:a,o=a.metadata?a.metadata(f.metadata):F,p="html5"===f.metadata.type&&o?o[f.metadata.name]:F,q=a.data(f.metadata.name||"qtipopts");try{q="string"==typeof q?d.parseJSON(q):q}catch(r){}if(k=d.extend(D,{},y.defaults,f,"object"==typeof q?h(q):F,h(p||o)),i=k.position,k.id=c,"boolean"==typeof k.content.text){if(j=a.attr(k.content.attr),k.content.attr===E||!j)return E;k.content.text=j}if(i.container.length||(i.container=m),i.target===E&&(i.target=n),k.show.target===E&&(k.show.target=n),k.show.solo===D&&(k.show.solo=i.container.closest("body")),k.hide.target===E&&(k.hide.target=n),k.position.viewport===D&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new A(i.at,D),i.my=new A(i.my),a.data(S))if(k.overwrite)a.qtip("destroy",!0);else if(k.overwrite===E)return E;return a.attr(T,c),k.suppress&&(l=a.attr("title"))&&a.removeAttr("title").attr(cb,l).attr("title",""),g=new e(a,k,c,!!j),a.data(S,g),g}function s(a){return a.charAt(0).toUpperCase()+a.slice(1)}function t(a,b){var d,e,f=b.charAt(0).toUpperCase()+b.slice(1),g=(b+" "+rb.join(f+" ")+f).split(" "),h=0;if(qb[b])return a.css(qb[b]);for(;d=g[h++];)if((e=a.css(d))!==c)return qb[b]=d,e}function u(a,b){return Math.ceil(parseFloat(t(a,b)))}function v(a,b){this._ns="tip",this.options=b,this.offset=b.offset,this.size=[b.width,b.height],this.init(this.qtip=a)}function w(a,b){this.options=b,this._ns="-modal",this.init(this.qtip=a)}function x(a){this._ns="ie6",this.init(this.qtip=a)}var y,z,A,B,C,D=!0,E=!1,F=null,G="x",H="y",I="width",J="height",K="top",L="left",M="bottom",N="right",O="center",P="flipinvert",Q="shift",R={},S="qtip",T="data-hasqtip",U="data-qtip-id",V=["ui-widget","ui-tooltip"],W="."+S,X="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),Y=S+"-fixed",Z=S+"-default",$=S+"-focus",_=S+"-hover",ab=S+"-disabled",bb="_replacedByqTip",cb="oldtitle",db={ie:function(){for(var a=4,c=b.createElement("div");(c.innerHTML="<!--[if gt IE "+a+"]><i></i><![endif]-->")&&c.getElementsByTagName("i")[0];a+=1);return a>4?a:0/0}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||E};z=e.prototype,z._when=function(a){return d.when.apply(d,a)},z.render=function(a){if(this.rendered||this.destroyed)return this;var b,c=this,e=this.options,f=this.cache,g=this.elements,h=e.content.text,i=e.content.title,j=e.content.button,k=e.position,l=("."+this._id+" ",[]);return d.attr(this.target[0],"aria-describedby",this._id),f.posClass=this._createPosClass((this.position={my:k.my,at:k.at}).my),this.tooltip=g.tooltip=b=d("<div/>",{id:this._id,"class":[S,Z,e.style.classes,f.posClass].join(" "),width:e.style.width||"",height:e.style.height||"",tracking:"mouse"===k.target&&k.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":E,"aria-describedby":this._id+"-content","aria-hidden":D}).toggleClass(ab,this.disabled).attr(U,this.id).data(S,this).appendTo(k.container).append(g.content=d("<div />",{"class":S+"-content",id:this._id+"-content","aria-atomic":D})),this.rendered=-1,this.positioning=D,i&&(this._createTitle(),d.isFunction(i)||l.push(this._updateTitle(i,E))),j&&this._createButton(),d.isFunction(h)||l.push(this._updateContent(h,E)),this.rendered=D,this._setWidget(),d.each(R,function(a){var b;"render"===this.initialize&&(b=this(c))&&(c.plugins[a]=b)}),this._unassignEvents(),this._assignEvents(),this._when(l).then(function(){c._trigger("render"),c.positioning=E,c.hiddenDuringWait||!e.show.ready&&!a||c.toggle(D,f.event,E),c.hiddenDuringWait=E}),y.api[this.id]=this,this},z.destroy=function(a){function b(){if(!this.destroyed){this.destroyed=D;var a,b=this.target,c=b.attr(cb);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),d.each(this.plugins,function(){this.destroy&&this.destroy()});for(a in this.timers)clearTimeout(this.timers[a]);b.removeData(S).removeAttr(U).removeAttr(T).removeAttr("aria-describedby"),this.options.suppress&&c&&b.attr("title",c).removeAttr(cb),this._unassignEvents(),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=F,delete y.api[this.id]}}return this.destroyed?this.target:(a===D&&"hide"!==this.triggering||!this.rendered?b.call(this):(this.tooltip.one("tooltiphidden",d.proxy(b,this)),!this.triggering&&this.hide()),this.target)},B=z.checks={builtin:{"^id$":function(a,b,c,e){var f=c===D?y.nextid:c,g=S+"-"+f;f!==E&&f.length>0&&!d("#"+g).length?(this._id=g,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):a[b]=e},"^prerender":function(a,b,c){c&&!this.rendered&&this.render(this.options.show.ready)},"^content.text$":function(a,b,c){this._updateContent(c)},"^content.attr$":function(a,b,c,d){this.options.content.text===this.target.attr(d)&&this._updateContent(this.target.attr(c))},"^content.title$":function(a,b,c){return c?(c&&!this.elements.title&&this._createTitle(),void this._updateTitle(c)):this._removeTitle()},"^content.button$":function(a,b,c){this._updateButton(c)},"^content.title.(text|button)$":function(a,b,c){this.set("content."+b,c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(this.position[b]=a[b]=new A(c,"at"===b))},"^position.container$":function(a,b,c){this.rendered&&this.tooltip.appendTo(c)},"^show.ready$":function(a,b,c){c&&(!this.rendered&&this.render(D)||this.toggle(D))},"^style.classes$":function(a,b,c,d){this.rendered&&this.tooltip.removeClass(d).addClass(c)},"^style.(width|height)":function(a,b,c){this.rendered&&this.tooltip.css(b,c)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def":function(a,b,c){this.rendered&&this.tooltip.toggleClass(Z,!!c)},"^events.(render|show|move|hide|focus|blur)$":function(a,b,c){this.rendered&&this.tooltip[(d.isFunction(c)?"":"un")+"bind"]("tooltip"+b,c)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var a=this.options.position;this.tooltip.attr("tracking","mouse"===a.target&&a.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},z.get=function(a){if(this.destroyed)return this;var b=i(this.options,a.toLowerCase()),c=b[0][b[1]];return c.precedance?c.string():c};var eb=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,fb=/^prerender|show\.ready/i;z.set=function(a,b){if(this.destroyed)return this;{var c,e=this.rendered,f=E,g=this.options;this.checks}return"string"==typeof a?(c=a,a={},a[c]=b):a=d.extend({},a),d.each(a,function(b,c){if(e&&fb.test(b))return void delete a[b];var h,j=i(g,b.toLowerCase());h=j[0][j[1]],j[0][j[1]]=c&&c.nodeType?d(c):c,f=eb.test(b)||f,a[b]=[j[0],j[1],c,h]}),h(g),this.positioning=D,d.each(a,d.proxy(j,this)),this.positioning=E,this.rendered&&this.tooltip[0].offsetWidth>0&&f&&this.reposition("mouse"===g.position.target?F:this.cache.event),this},z._update=function(a,b){var c=this,e=this.cache;return this.rendered&&a?(d.isFunction(a)&&(a=a.call(this.elements.target,e.event,this)||""),d.isFunction(a.then)?(e.waiting=D,a.then(function(a){return e.waiting=E,c._update(a,b)},F,function(a){return c._update(a,b)})):a===E||!a&&""!==a?E:(a.jquery&&a.length>0?b.empty().append(a.css({display:"block",visibility:"visible"})):b.html(a),this._waitForContent(b).then(function(a){c.rendered&&c.tooltip[0].offsetWidth>0&&c.reposition(e.event,!a.length)}))):E},z._waitForContent=function(a){var b=this.cache;return b.waiting=D,(d.fn.imagesLoaded?a.imagesLoaded():d.Deferred().resolve([])).done(function(){b.waiting=E}).promise()},z._updateContent=function(a,b){this._update(a,this.elements.content,b)},z._updateTitle=function(a,b){this._update(a,this.elements.title,b)===E&&this._removeTitle(E)},z._createTitle=function(){var a=this.elements,b=this._id+"-title";a.titlebar&&this._removeTitle(),a.titlebar=d("<div />",{"class":S+"-titlebar "+(this.options.style.widget?k("header"):"")}).append(a.title=d("<div />",{id:b,"class":S+"-title","aria-atomic":D})).insertBefore(a.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(a){d(this).toggleClass("ui-state-active ui-state-focus","down"===a.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(a){d(this).toggleClass("ui-state-hover","mouseover"===a.type)}),this.options.content.button&&this._createButton()},z._removeTitle=function(a){var b=this.elements;b.title&&(b.titlebar.remove(),b.titlebar=b.title=b.button=F,a!==E&&this.reposition())},z._createPosClass=function(a){return S+"-pos-"+(a||this.options.position.my).abbrev()},z.reposition=function(c,e){if(!this.rendered||this.positioning||this.destroyed)return this;this.positioning=D;var f,g,h,i,j=this.cache,k=this.tooltip,l=this.options.position,m=l.target,n=l.my,o=l.at,p=l.viewport,q=l.container,r=l.adjust,s=r.method.split(" "),t=k.outerWidth(E),u=k.outerHeight(E),v=0,w=0,x=k.css("position"),y={left:0,top:0},z=k[0].offsetWidth>0,A=c&&"scroll"===c.type,B=d(a),C=q[0].ownerDocument,F=this.mouse;if(d.isArray(m)&&2===m.length)o={x:L,y:K},y={left:m[0],top:m[1]};else if("mouse"===m)o={x:L,y:K},(!r.mouse||this.options.hide.distance)&&j.origin&&j.origin.pageX?c=j.origin:!c||c&&("resize"===c.type||"scroll"===c.type)?c=j.event:F&&F.pageX&&(c=F),"static"!==x&&(y=q.offset()),C.body.offsetWidth!==(a.innerWidth||C.documentElement.clientWidth)&&(g=d(b.body).offset()),y={left:c.pageX-y.left+(g&&g.left||0),top:c.pageY-y.top+(g&&g.top||0)},r.mouse&&A&&F&&(y.left-=(F.scrollX||0)-B.scrollLeft(),y.top-=(F.scrollY||0)-B.scrollTop());else{if("event"===m?c&&c.target&&"scroll"!==c.type&&"resize"!==c.type?j.target=d(c.target):c.target||(j.target=this.elements.target):"event"!==m&&(j.target=d(m.jquery?m:this.elements.target)),m=j.target,m=d(m).eq(0),0===m.length)return this;m[0]===b||m[0]===a?(v=db.iOS?a.innerWidth:m.width(),w=db.iOS?a.innerHeight:m.height(),m[0]===a&&(y={top:(p||m).scrollTop(),left:(p||m).scrollLeft()})):R.imagemap&&m.is("area")?f=R.imagemap(this,m,o,R.viewport?s:E):R.svg&&m&&m[0].ownerSVGElement?f=R.svg(this,m,o,R.viewport?s:E):(v=m.outerWidth(E),w=m.outerHeight(E),y=m.offset()),f&&(v=f.width,w=f.height,g=f.offset,y=f.position),y=this.reposition.offset(m,y,q),(db.iOS>3.1&&db.iOS<4.1||db.iOS>=4.3&&db.iOS<4.33||!db.iOS&&"fixed"===x)&&(y.left-=B.scrollLeft(),y.top-=B.scrollTop()),(!f||f&&f.adjustable!==E)&&(y.left+=o.x===N?v:o.x===O?v/2:0,y.top+=o.y===M?w:o.y===O?w/2:0)}return y.left+=r.x+(n.x===N?-t:n.x===O?-t/2:0),y.top+=r.y+(n.y===M?-u:n.y===O?-u/2:0),R.viewport?(h=y.adjusted=R.viewport(this,y,l,v,w,t,u),g&&h.left&&(y.left+=g.left),g&&h.top&&(y.top+=g.top),h.my&&(this.position.my=h.my)):y.adjusted={left:0,top:0},j.posClass!==(i=this._createPosClass(this.position.my))&&k.removeClass(j.posClass).addClass(j.posClass=i),this._trigger("move",[y,p.elem||p],c)?(delete y.adjusted,e===E||!z||isNaN(y.left)||isNaN(y.top)||"mouse"===m||!d.isFunction(l.effect)?k.css(y):d.isFunction(l.effect)&&(l.effect.call(k,this,d.extend({},y)),k.queue(function(a){d(this).css({opacity:"",height:""}),db.ie&&this.style.removeAttribute("filter"),a()})),this.positioning=E,this):this},z.reposition.offset=function(a,c,e){function f(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}if(!e[0])return c;var g,h,i,j,k=d(a[0].ownerDocument),l=!!db.ie&&"CSS1Compat"!==b.compatMode,m=e[0];do"static"!==(h=d.css(m,"position"))&&("fixed"===h?(i=m.getBoundingClientRect(),f(k,-1)):(i=d(m).position(),i.left+=parseFloat(d.css(m,"borderLeftWidth"))||0,i.top+=parseFloat(d.css(m,"borderTopWidth"))||0),c.left-=i.left+(parseFloat(d.css(m,"marginLeft"))||0),c.top-=i.top+(parseFloat(d.css(m,"marginTop"))||0),g||"hidden"===(j=d.css(m,"overflow"))||"visible"===j||(g=d(m)));while(m=m.offsetParent);return g&&(g[0]!==k[0]||l)&&f(g,1),c};var gb=(A=z.reposition.Corner=function(a,b){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,O).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!b;var c=a.charAt(0);this.precedance="t"===c||"b"===c?H:G}).prototype;gb.invert=function(a,b){this[a]=this[a]===L?N:this[a]===N?L:b||this[a]},gb.string=function(a){var b=this.x,c=this.y,d=b!==c?"center"===b||"center"!==c&&(this.precedance===H||this.forceY)?[c,b]:[b,c]:[b];return a!==!1?d.join(" "):d},gb.abbrev=function(){var a=this.string(!1);return a[0].charAt(0)+(a[1]&&a[1].charAt(0)||"")},gb.clone=function(){return new A(this.string(),this.forceY)},z.toggle=function(a,c){var e=this.cache,f=this.options,g=this.tooltip;if(c){if(/over|enter/.test(c.type)&&e.event&&/out|leave/.test(e.event.type)&&f.show.target.add(c.target).length===f.show.target.length&&g.has(c.relatedTarget).length)return this;e.event=d.event.fix(c)}if(this.waiting&&!a&&(this.hiddenDuringWait=D),!this.rendered)return a?this.render(1):this;if(this.destroyed||this.disabled)return this;var h,i,j,k=a?"show":"hide",l=this.options[k],m=(this.options[a?"hide":"show"],this.options.position),n=this.options.content,o=this.tooltip.css("width"),p=this.tooltip.is(":visible"),q=a||1===l.target.length,r=!c||l.target.length<2||e.target[0]===c.target;return(typeof a).search("boolean|number")&&(a=!p),h=!g.is(":animated")&&p===a&&r,i=h?F:!!this._trigger(k,[90]),this.destroyed?this:(i!==E&&a&&this.focus(c),!i||h?this:(d.attr(g[0],"aria-hidden",!a),a?(this.mouse&&(e.origin=d.event.fix(this.mouse)),d.isFunction(n.text)&&this._updateContent(n.text,E),d.isFunction(n.title)&&this._updateTitle(n.title,E),!C&&"mouse"===m.target&&m.adjust.mouse&&(d(b).bind("mousemove."+S,this._storeMouse),C=D),o||g.css("width",g.outerWidth(E)),this.reposition(c,arguments[2]),o||g.css("width",""),l.solo&&("string"==typeof l.solo?d(l.solo):d(W,l.solo)).not(g).not(l.target).qtip("hide",d.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete e.origin,C&&!d(W+'[tracking="true"]:visible',l.solo).not(g).length&&(d(b).unbind("mousemove."+S),C=E),this.blur(c)),j=d.proxy(function(){a?(db.ie&&g[0].style.removeAttribute("filter"),g.css("overflow",""),"string"==typeof l.autofocus&&d(this.options.show.autofocus,g).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):g.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(a?"visible":"hidden")},this),l.effect===E||q===E?(g[k](),j()):d.isFunction(l.effect)?(g.stop(1,1),l.effect.call(g,this),g.queue("fx",function(a){j(),a()})):g.fadeTo(90,a?1:0,j),a&&l.target.trigger("qtip-"+this.id+"-inactive"),this))},z.show=function(a){return this.toggle(D,a)},z.hide=function(a){return this.toggle(E,a)},z.focus=function(a){if(!this.rendered||this.destroyed)return this;var b=d(W),c=this.tooltip,e=parseInt(c[0].style.zIndex,10),f=y.zindex+b.length;return c.hasClass($)||this._trigger("focus",[f],a)&&(e!==f&&(b.each(function(){this.style.zIndex>e&&(this.style.zIndex=this.style.zIndex-1)}),b.filter("."+$).qtip("blur",a)),c.addClass($)[0].style.zIndex=f),this},z.blur=function(a){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass($),this._trigger("blur",[this.tooltip.css("zIndex")],a),this)},z.disable=function(a){return this.destroyed?this:("toggle"===a?a=!(this.rendered?this.tooltip.hasClass(ab):this.disabled):"boolean"!=typeof a&&(a=D),this.rendered&&this.tooltip.toggleClass(ab,a).attr("aria-disabled",a),this.disabled=!!a,this)},z.enable=function(){return this.disable(E)},z._createButton=function(){var a=this,b=this.elements,c=b.tooltip,e=this.options.content.button,f="string"==typeof e,g=f?e:"Close tooltip";b.button&&b.button.remove(),b.button=e.jquery?e:d("<a />",{"class":"qtip-close "+(this.options.style.widget?"":S+"-icon"),title:g,"aria-label":g}).prepend(d("<span />",{"class":"ui-icon ui-icon-close",html:"×"})),b.button.appendTo(b.titlebar||c).attr("role","button").click(function(b){return c.hasClass(ab)||a.hide(b),E})},z._updateButton=function(a){if(!this.rendered)return E;var b=this.elements.button;a?this._createButton():b.remove()},z._setWidget=function(){var a=this.options.style.widget,b=this.elements,c=b.tooltip,d=c.hasClass(ab);c.removeClass(ab),ab=a?"ui-state-disabled":"qtip-disabled",c.toggleClass(ab,d),c.toggleClass("ui-helper-reset "+k(),a).toggleClass(Z,this.options.style.def&&!a),b.content&&b.content.toggleClass(k("content"),a),b.titlebar&&b.titlebar.toggleClass(k("header"),a),b.button&&b.button.toggleClass(S+"-icon",!a)},z._storeMouse=function(a){return(this.mouse=d.event.fix(a)).type="mousemove",this},z._bind=function(a,b,c,e,f){if(a&&c&&b.length){var g="."+this._id+(e?"-"+e:"");return d(a).bind((b.split?b:b.join(g+" "))+g,d.proxy(c,f||this)),this}},z._unbind=function(a,b){return a&&d(a).unbind("."+this._id+(b?"-"+b:"")),this},z._trigger=function(a,b,c){var e=d.Event("tooltip"+a);return e.originalEvent=c&&d.extend({},c)||this.cache.event||F,this.triggering=a,this.tooltip.trigger(e,[this].concat(b||[])),this.triggering=E,!e.isDefaultPrevented()},z._bindEvents=function(a,b,c,e,f,g){var h=c.filter(e).add(e.filter(c)),i=[];h.length&&(d.each(b,function(b,c){var e=d.inArray(c,a);e>-1&&i.push(a.splice(e,1)[0])}),i.length&&(this._bind(h,i,function(a){var b=this.rendered?this.tooltip[0].offsetWidth>0:!1;(b?g:f).call(this,a)}),c=c.not(h),e=e.not(h))),this._bind(c,a,f),this._bind(e,b,g)},z._assignInitialEvents=function(a){function b(a){return this.disabled||this.destroyed?E:(this.cache.event=a&&d.event.fix(a),this.cache.target=a&&d(a.target),clearTimeout(this.timers.show),void(this.timers.show=l.call(this,function(){this.render("object"==typeof a||c.show.ready)},c.prerender?0:c.show.delay)))}var c=this.options,e=c.show.target,f=c.hide.target,g=c.show.event?d.trim(""+c.show.event).split(" "):[],h=c.hide.event?d.trim(""+c.hide.event).split(" "):[];this._bind(this.elements.target,["remove","removeqtip"],function(){this.destroy(!0)},"destroy"),/mouse(over|enter)/i.test(c.show.event)&&!/mouse(out|leave)/i.test(c.hide.event)&&h.push("mouseleave"),this._bind(e,"mousemove",function(a){this._storeMouse(a),this.cache.onTarget=D}),this._bindEvents(g,h,e,f,b,function(){return this.timers?void clearTimeout(this.timers.show):E}),(c.show.ready||c.prerender)&&b.call(this,a)},z._assignEvents=function(){var c=this,e=this.options,f=e.position,g=this.tooltip,h=e.show.target,i=e.hide.target,j=f.container,k=f.viewport,l=d(b),q=(d(b.body),d(a)),r=e.show.event?d.trim(""+e.show.event).split(" "):[],s=e.hide.event?d.trim(""+e.hide.event).split(" "):[];d.each(e.events,function(a,b){c._bind(g,"toggle"===a?["tooltipshow","tooltiphide"]:["tooltip"+a],b,null,g)}),/mouse(out|leave)/i.test(e.hide.event)&&"window"===e.hide.leave&&this._bind(l,["mouseout","blur"],function(a){/select|option/.test(a.target.nodeName)||a.relatedTarget||this.hide(a)}),e.hide.fixed?i=i.add(g.addClass(Y)):/mouse(over|enter)/i.test(e.show.event)&&this._bind(i,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+e.hide.event).indexOf("unfocus")>-1&&this._bind(j.closest("html"),["mousedown","touchstart"],function(a){var b=d(a.target),c=this.rendered&&!this.tooltip.hasClass(ab)&&this.tooltip[0].offsetWidth>0,e=b.parents(W).filter(this.tooltip[0]).length>0;b[0]===this.target[0]||b[0]===this.tooltip[0]||e||this.target.has(b[0]).length||!c||this.hide(a)}),"number"==typeof e.hide.inactive&&(this._bind(h,"qtip-"+this.id+"-inactive",o,"inactive"),this._bind(i.add(g),y.inactiveEvents,o)),this._bindEvents(r,s,h,i,m,n),this._bind(h.add(g),"mousemove",function(a){if("number"==typeof e.hide.distance){var b=this.cache.origin||{},c=this.options.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&this.hide(a)}this._storeMouse(a)}),"mouse"===f.target&&f.adjust.mouse&&(e.hide.event&&this._bind(h,["mouseenter","mouseleave"],function(a){return this.cache?void(this.cache.onTarget="mouseenter"===a.type):E}),this._bind(l,"mousemove",function(a){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(ab)&&this.tooltip[0].offsetWidth>0&&this.reposition(a)})),(f.adjust.resize||k.length)&&this._bind(d.event.special.resize?k:q,"resize",p),f.adjust.scroll&&this._bind(q.add(f.container),"scroll",p)},z._unassignEvents=function(){var c=this.options,e=c.show.target,f=c.hide.target,g=d.grep([this.elements.target[0],this.rendered&&this.tooltip[0],c.position.container[0],c.position.viewport[0],c.position.container.closest("html")[0],a,b],function(a){return"object"==typeof a});e&&e.toArray&&(g=g.concat(e.toArray())),f&&f.toArray&&(g=g.concat(f.toArray())),this._unbind(g)._unbind(g,"destroy")._unbind(g,"inactive")},d(function(){q(W,["mouseenter","mouseleave"],function(a){var b="mouseenter"===a.type,c=d(a.currentTarget),e=d(a.relatedTarget||a.target),f=this.options;b?(this.focus(a),c.hasClass(Y)&&!c.hasClass(ab)&&clearTimeout(this.timers.hide)):"mouse"===f.position.target&&f.position.adjust.mouse&&f.hide.event&&f.show.target&&!e.closest(f.show.target[0]).length&&this.hide(a),c.toggleClass(_,b)}),q("["+U+"]",X,o)}),y=d.fn.qtip=function(a,b,e){var f=(""+a).toLowerCase(),g=F,i=d.makeArray(arguments).slice(1),j=i[i.length-1],k=this[0]?d.data(this[0],S):F;return!arguments.length&&k||"api"===f?k:"string"==typeof a?(this.each(function(){var a=d.data(this,S);if(!a)return D;if(j&&j.timeStamp&&(a.cache.event=j),!b||"option"!==f&&"options"!==f)a[f]&&a[f].apply(a,i);else{if(e===c&&!d.isPlainObject(b))return g=a.get(b),E;a.set(b,e)}}),g!==F?g:this):"object"!=typeof a&&arguments.length?void 0:(k=h(d.extend(D,{},a)),this.each(function(a){var b,c;return c=d.isArray(k.id)?k.id[a]:k.id,c=!c||c===E||c.length<1||y.api[c]?y.nextid++:c,b=r(d(this),c,k),b===E?D:(y.api[c]=b,d.each(R,function(){"initialize"===this.initialize&&this(b)}),void b._assignInitialEvents(j))}))},d.qtip=e,y.api={},d.each({attr:function(a,b){if(this.length){var c=this[0],e="title",f=d.data(c,"qtip");if(a===e&&f&&"object"==typeof f&&f.options.suppress)return arguments.length<2?d.attr(c,cb):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",b),this.attr(cb,b))}return d.fn["attr"+bb].apply(this,arguments)},clone:function(a){var b=(d([]),d.fn["clone"+bb].apply(this,arguments));return a||b.filter("["+cb+"]").attr("title",function(){return d.attr(this,cb)}).removeAttr(cb),b}},function(a,b){if(!b||d.fn[a+bb])return D;var c=d.fn[a+bb]=d.fn[a];d.fn[a]=function(){return b.apply(this,arguments)||c.apply(this,arguments)}}),d.ui||(d["cleanData"+bb]=d.cleanData,d.cleanData=function(a){for(var b,c=0;(b=d(a[c])).length;c++)if(b.attr(T))try{b.triggerHandler("removeqtip")}catch(e){}d["cleanData"+bb].apply(this,arguments)}),y.version="2.2.1",y.nextid=0,y.inactiveEvents=X,y.zindex=15e3,y.defaults={prerender:E,id:E,overwrite:D,suppress:D,content:{text:D,attr:"title",title:E,button:E},position:{my:"top left",at:"bottom right",target:E,container:E,viewport:E,adjust:{x:0,y:0,mouse:D,scroll:D,resize:D,method:"flipinvert flipinvert"},effect:function(a,b){d(this).animate(b,{duration:200,queue:E})}},show:{target:E,event:"mouseenter",effect:D,delay:90,solo:E,ready:E,autofocus:E},hide:{target:E,event:"mouseleave",effect:D,delay:0,fixed:E,inactive:E,leave:"window",distance:E},style:{classes:"",widget:E,width:E,height:E,def:D},events:{render:F,move:F,show:F,hide:F,toggle:F,visible:F,hidden:F,focus:F,blur:F}};var hb,ib="margin",jb="border",kb="color",lb="background-color",mb="transparent",nb=" !important",ob=!!b.createElement("canvas").getContext,pb=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,qb={},rb=["Webkit","O","Moz","ms"];if(ob)var sb=a.devicePixelRatio||1,tb=function(){var a=b.createElement("canvas").getContext("2d");return a.backingStorePixelRatio||a.webkitBackingStorePixelRatio||a.mozBackingStorePixelRatio||a.msBackingStorePixelRatio||a.oBackingStorePixelRatio||1}(),ub=sb/tb;else var vb=function(a,b,c){return"<qtipvml:"+a+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(b||"")+' style="behavior: url(#default#VML); '+(c||"")+'" />'};d.extend(v.prototype,{init:function(a){var b,c;c=this.element=a.elements.tip=d("<div />",{"class":S+"-tip"}).prependTo(a.tooltip),ob?(b=d("<canvas />").appendTo(this.element)[0].getContext("2d"),b.lineJoin="miter",b.miterLimit=1e5,b.save()):(b=vb("shape",'coordorigin="0,0"',"position:absolute;"),this.element.html(b+b),a._bind(d("*",c).add(c),["click","mousedown"],function(a){a.stopPropagation()},this._ns)),a._bind(a.tooltip,"tooltipmove",this.reposition,this._ns,this),this.create()},_swapDimensions:function(){this.size[0]=this.options.height,this.size[1]=this.options.width},_resetDimensions:function(){this.size[0]=this.options.width,this.size[1]=this.options.height},_useTitle:function(a){var b=this.qtip.elements.titlebar;return b&&(a.y===K||a.y===O&&this.element.position().top+this.size[1]/2+this.options.offset<b.outerHeight(D))},_parseCorner:function(a){var b=this.qtip.options.position.my;return a===E||b===E?a=E:a===D?a=new A(b.string()):a.string||(a=new A(a),a.fixed=D),a},_parseWidth:function(a,b,c){var d=this.qtip.elements,e=jb+s(b)+"Width";return(c?u(c,e):u(d.content,e)||u(this._useTitle(a)&&d.titlebar||d.content,e)||u(d.tooltip,e))||0},_parseRadius:function(a){var b=this.qtip.elements,c=jb+s(a.y)+s(a.x)+"Radius";return db.ie<9?0:u(this._useTitle(a)&&b.titlebar||b.content,c)||u(b.tooltip,c)||0},_invalidColour:function(a,b,c){var d=a.css(b);return!d||c&&d===a.css(c)||pb.test(d)?E:d},_parseColours:function(a){var b=this.qtip.elements,c=this.element.css("cssText",""),e=jb+s(a[a.precedance])+s(kb),f=this._useTitle(a)&&b.titlebar||b.content,g=this._invalidColour,h=[];return h[0]=g(c,lb)||g(f,lb)||g(b.content,lb)||g(b.tooltip,lb)||c.css(lb),h[1]=g(c,e,kb)||g(f,e,kb)||g(b.content,e,kb)||g(b.tooltip,e,kb)||b.tooltip.css(e),d("*",c).add(c).css("cssText",lb+":"+mb+nb+";"+jb+":0"+nb+";"),h},_calculateSize:function(a){var b,c,d,e=a.precedance===H,f=this.options.width,g=this.options.height,h="c"===a.abbrev(),i=(e?f:g)*(h?.5:1),j=Math.pow,k=Math.round,l=Math.sqrt(j(i,2)+j(g,2)),m=[this.border/i*l,this.border/g*l];return m[2]=Math.sqrt(j(m[0],2)-j(this.border,2)),m[3]=Math.sqrt(j(m[1],2)-j(this.border,2)),b=l+m[2]+m[3]+(h?0:m[0]),c=b/l,d=[k(c*f),k(c*g)],e?d:d.reverse()},_calculateTip:function(a,b,c){c=c||1,b=b||this.size;var d=b[0]*c,e=b[1]*c,f=Math.ceil(d/2),g=Math.ceil(e/2),h={br:[0,0,d,e,d,0],bl:[0,0,d,0,0,e],tr:[0,e,d,0,d,e],tl:[0,0,0,e,d,e],tc:[0,e,f,0,d,e],bc:[0,0,d,0,f,e],rc:[0,0,d,g,0,e],lc:[d,0,d,e,0,g]};return h.lt=h.br,h.rt=h.bl,h.lb=h.tr,h.rb=h.tl,h[a.abbrev()]},_drawCoords:function(a,b){a.beginPath(),a.moveTo(b[0],b[1]),a.lineTo(b[2],b[3]),a.lineTo(b[4],b[5]),a.closePath()},create:function(){var a=this.corner=(ob||db.ie)&&this._parseCorner(this.options.corner);return(this.enabled=!!this.corner&&"c"!==this.corner.abbrev())&&(this.qtip.cache.corner=a.clone(),this.update()),this.element.toggle(this.enabled),this.corner},update:function(b,c){if(!this.enabled)return this;var e,f,g,h,i,j,k,l,m=this.qtip.elements,n=this.element,o=n.children(),p=this.options,q=this.size,r=p.mimic,s=Math.round;b||(b=this.qtip.cache.corner||this.corner),r===E?r=b:(r=new A(r),r.precedance=b.precedance,"inherit"===r.x?r.x=b.x:"inherit"===r.y?r.y=b.y:r.x===r.y&&(r[b.precedance]=b[b.precedance])),f=r.precedance,b.precedance===G?this._swapDimensions():this._resetDimensions(),e=this.color=this._parseColours(b),e[1]!==mb?(l=this.border=this._parseWidth(b,b[b.precedance]),p.border&&1>l&&!pb.test(e[1])&&(e[0]=e[1]),this.border=l=p.border!==D?p.border:l):this.border=l=0,k=this.size=this._calculateSize(b),n.css({width:k[0],height:k[1],lineHeight:k[1]+"px"}),j=b.precedance===H?[s(r.x===L?l:r.x===N?k[0]-q[0]-l:(k[0]-q[0])/2),s(r.y===K?k[1]-q[1]:0)]:[s(r.x===L?k[0]-q[0]:0),s(r.y===K?l:r.y===M?k[1]-q[1]-l:(k[1]-q[1])/2)],ob?(g=o[0].getContext("2d"),g.restore(),g.save(),g.clearRect(0,0,6e3,6e3),h=this._calculateTip(r,q,ub),i=this._calculateTip(r,this.size,ub),o.attr(I,k[0]*ub).attr(J,k[1]*ub),o.css(I,k[0]).css(J,k[1]),this._drawCoords(g,i),g.fillStyle=e[1],g.fill(),g.translate(j[0]*ub,j[1]*ub),this._drawCoords(g,h),g.fillStyle=e[0],g.fill()):(h=this._calculateTip(r),h="m"+h[0]+","+h[1]+" l"+h[2]+","+h[3]+" "+h[4]+","+h[5]+" xe",j[2]=l&&/^(r|b)/i.test(b.string())?8===db.ie?2:1:0,o.css({coordsize:k[0]+l+" "+(k[1]+l),antialias:""+(r.string().indexOf(O)>-1),left:j[0]-j[2]*Number(f===G),top:j[1]-j[2]*Number(f===H),width:k[0]+l,height:k[1]+l}).each(function(a){var b=d(this);b[b.prop?"prop":"attr"]({coordsize:k[0]+l+" "+(k[1]+l),path:h,fillcolor:e[0],filled:!!a,stroked:!a}).toggle(!(!l&&!a)),!a&&b.html(vb("stroke",'weight="'+2*l+'px" color="'+e[1]+'" miterlimit="1000" joinstyle="miter"'))})),a.opera&&setTimeout(function(){m.tip.css({display:"inline-block",visibility:"visible"})},1),c!==E&&this.calculate(b,k)},calculate:function(a,b){if(!this.enabled)return E;var c,e,f=this,g=this.qtip.elements,h=this.element,i=this.options.offset,j=(g.tooltip.hasClass("ui-widget"),{});return a=a||this.corner,c=a.precedance,b=b||this._calculateSize(a),e=[a.x,a.y],c===G&&e.reverse(),d.each(e,function(d,e){var h,k,l;
|
187 |
e===O?(h=c===H?L:K,j[h]="50%",j[ib+"-"+h]=-Math.round(b[c===H?0:1]/2)+i):(h=f._parseWidth(a,e,g.tooltip),k=f._parseWidth(a,e,g.content),l=f._parseRadius(a),j[e]=Math.max(-f.border,d?k:i+(l>h?l:-h)))}),j[a[c]]-=b[c===G?0:1],h.css({margin:"",top:"",bottom:"",left:"",right:""}).css(j),j},reposition:function(a,b,d){function e(a,b,c,d,e){a===Q&&j.precedance===b&&k[d]&&j[c]!==O?j.precedance=j.precedance===G?H:G:a!==Q&&k[d]&&(j[b]=j[b]===O?k[d]>0?d:e:j[b]===d?e:d)}function f(a,b,e){j[a]===O?p[ib+"-"+b]=o[a]=g[ib+"-"+b]-k[b]:(h=g[e]!==c?[k[b],-g[b]]:[-k[b],g[b]],(o[a]=Math.max(h[0],h[1]))>h[0]&&(d[b]-=k[b],o[b]=E),p[g[e]!==c?e:b]=o[a])}if(this.enabled){var g,h,i=b.cache,j=this.corner.clone(),k=d.adjusted,l=b.options.position.adjust.method.split(" "),m=l[0],n=l[1]||l[0],o={left:E,top:E,x:0,y:0},p={};this.corner.fixed!==D&&(e(m,G,H,L,N),e(n,H,G,K,M),(j.string()!==i.corner.string()||i.cornerTop!==k.top||i.cornerLeft!==k.left)&&this.update(j,E)),g=this.calculate(j),g.right!==c&&(g.left=-g.right),g.bottom!==c&&(g.top=-g.bottom),g.user=this.offset,(o.left=m===Q&&!!k.left)&&f(G,L,N),(o.top=n===Q&&!!k.top)&&f(H,K,M),this.element.css(p).toggle(!(o.x&&o.y||j.x===O&&o.y||j.y===O&&o.x)),d.left-=g.left.charAt?g.user:m!==Q||o.top||!o.left&&!o.top?g.left+this.border:0,d.top-=g.top.charAt?g.user:n!==Q||o.left||!o.left&&!o.top?g.top+this.border:0,i.cornerLeft=k.left,i.cornerTop=k.top,i.corner=j.clone()}},destroy:function(){this.qtip._unbind(this.qtip.tooltip,this._ns),this.qtip.elements.tip&&this.qtip.elements.tip.find("*").remove().end().remove()}}),hb=R.tip=function(a){return new v(a,a.options.style.tip)},hb.initialize="render",hb.sanitize=function(a){if(a.style&&"tip"in a.style){var b=a.style.tip;"object"!=typeof b&&(b=a.style.tip={corner:b}),/string|boolean/i.test(typeof b.corner)||(b.corner=D)}},B.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){this.create(),this.qtip.reposition()},"^style.tip.(height|width)$":function(a){this.size=[a.width,a.height],this.update(),this.qtip.reposition()},"^content.title|style.(classes|widget)$":function(){this.update()}},d.extend(D,y.defaults,{style:{tip:{corner:D,mimic:E,width:6,height:6,border:D,offset:0}}});var wb,xb,yb="qtip-modal",zb="."+yb;xb=function(){function a(a){if(d.expr[":"].focusable)return d.expr[":"].focusable;var b,c,e,f=!isNaN(d.attr(a,"tabindex")),g=a.nodeName&&a.nodeName.toLowerCase();return"area"===g?(b=a.parentNode,c=b.name,a.href&&c&&"map"===b.nodeName.toLowerCase()?(e=d("img[usemap=#"+c+"]")[0],!!e&&e.is(":visible")):!1):/input|select|textarea|button|object/.test(g)?!a.disabled:"a"===g?a.href||f:f}function c(a){k.length<1&&a.length?a.not("body").blur():k.first().focus()}function e(a){if(i.is(":visible")){var b,e=d(a.target),h=f.tooltip,j=e.closest(W);b=j.length<1?E:parseInt(j[0].style.zIndex,10)>parseInt(h[0].style.zIndex,10),b||e.closest(W)[0]===h[0]||c(e),g=a.target===k[k.length-1]}}var f,g,h,i,j=this,k={};d.extend(j,{init:function(){return i=j.elem=d("<div />",{id:"qtip-overlay",html:"<div></div>",mousedown:function(){return E}}).hide(),d(b.body).bind("focusin"+zb,e),d(b).bind("keydown"+zb,function(a){f&&f.options.show.modal.escape&&27===a.keyCode&&f.hide(a)}),i.bind("click"+zb,function(a){f&&f.options.show.modal.blur&&f.hide(a)}),j},update:function(b){f=b,k=b.options.show.modal.stealfocus!==E?b.tooltip.find("*").filter(function(){return a(this)}):[]},toggle:function(a,e,g){var k=(d(b.body),a.tooltip),l=a.options.show.modal,m=l.effect,n=e?"show":"hide",o=i.is(":visible"),p=d(zb).filter(":visible:not(:animated)").not(k);return j.update(a),e&&l.stealfocus!==E&&c(d(":focus")),i.toggleClass("blurs",l.blur),e&&i.appendTo(b.body),i.is(":animated")&&o===e&&h!==E||!e&&p.length?j:(i.stop(D,E),d.isFunction(m)?m.call(i,e):m===E?i[n]():i.fadeTo(parseInt(g,10)||90,e?1:0,function(){e||i.hide()}),e||i.queue(function(a){i.css({left:"",top:""}),d(zb).length||i.detach(),a()}),h=e,f.destroyed&&(f=F),j)}}),j.init()},xb=new xb,d.extend(w.prototype,{init:function(a){var b=a.tooltip;return this.options.on?(a.elements.overlay=xb.elem,b.addClass(yb).css("z-index",y.modal_zindex+d(zb).length),a._bind(b,["tooltipshow","tooltiphide"],function(a,c,e){var f=a.originalEvent;if(a.target===b[0])if(f&&"tooltiphide"===a.type&&/mouse(leave|enter)/.test(f.type)&&d(f.relatedTarget).closest(xb.elem[0]).length)try{a.preventDefault()}catch(g){}else(!f||f&&"tooltipsolo"!==f.type)&&this.toggle(a,"tooltipshow"===a.type,e)},this._ns,this),a._bind(b,"tooltipfocus",function(a,c){if(!a.isDefaultPrevented()&&a.target===b[0]){var e=d(zb),f=y.modal_zindex+e.length,g=parseInt(b[0].style.zIndex,10);xb.elem[0].style.zIndex=f-1,e.each(function(){this.style.zIndex>g&&(this.style.zIndex-=1)}),e.filter("."+$).qtip("blur",a.originalEvent),b.addClass($)[0].style.zIndex=f,xb.update(c);try{a.preventDefault()}catch(h){}}},this._ns,this),void a._bind(b,"tooltiphide",function(a){a.target===b[0]&&d(zb).filter(":visible").not(b).last().qtip("focus",a)},this._ns,this)):this},toggle:function(a,b,c){return a&&a.isDefaultPrevented()?this:void xb.toggle(this.qtip,!!b,c)},destroy:function(){this.qtip.tooltip.removeClass(yb),this.qtip._unbind(this.qtip.tooltip,this._ns),xb.toggle(this.qtip,E),delete this.qtip.elements.overlay}}),wb=R.modal=function(a){return new w(a,a.options.show.modal)},wb.sanitize=function(a){a.show&&("object"!=typeof a.show.modal?a.show.modal={on:!!a.show.modal}:"undefined"==typeof a.show.modal.on&&(a.show.modal.on=D))},y.modal_zindex=y.zindex-200,wb.initialize="render",B.modal={"^show.modal.(on|blur)$":function(){this.destroy(),this.init(),this.qtip.elems.overlay.toggle(this.qtip.tooltip[0].offsetWidth>0)}},d.extend(D,y.defaults,{show:{modal:{on:E,effect:D,blur:D,stealfocus:D,escape:D}}}),R.viewport=function(c,d,e,f,g,h,i){function j(a,b,c,e,f,g,h,i,j){var k=d[f],s=u[a],t=v[a],w=c===Q,x=s===f?j:s===g?-j:-j/2,y=t===f?i:t===g?-i:-i/2,z=q[f]+r[f]-(n?0:m[f]),A=z-k,B=k+j-(h===I?o:p)-z,C=x-(u.precedance===a||s===u[b]?y:0)-(t===O?i/2:0);return w?(C=(s===f?1:-1)*x,d[f]+=A>0?A:B>0?-B:0,d[f]=Math.max(-m[f]+r[f],k-C,Math.min(Math.max(-m[f]+r[f]+(h===I?o:p),k+C),d[f],"center"===s?k-x:1e9))):(e*=c===P?2:0,A>0&&(s!==f||B>0)?(d[f]-=C+e,l.invert(a,f)):B>0&&(s!==g||A>0)&&(d[f]-=(s===O?-C:C)+e,l.invert(a,g)),d[f]<q&&-d[f]>B&&(d[f]=k,l=u.clone())),d[f]-k}var k,l,m,n,o,p,q,r,s=e.target,t=c.elements.tooltip,u=e.my,v=e.at,w=e.adjust,x=w.method.split(" "),y=x[0],z=x[1]||x[0],A=e.viewport,B=e.container,C=(c.cache,{left:0,top:0});return A.jquery&&s[0]!==a&&s[0]!==b.body&&"none"!==w.method?(m=B.offset()||C,n="static"===B.css("position"),k="fixed"===t.css("position"),o=A[0]===a?A.width():A.outerWidth(E),p=A[0]===a?A.height():A.outerHeight(E),q={left:k?0:A.scrollLeft(),top:k?0:A.scrollTop()},r=A.offset()||C,("shift"!==y||"shift"!==z)&&(l=u.clone()),C={left:"none"!==y?j(G,H,y,w.x,L,N,I,f,h):0,top:"none"!==z?j(H,G,z,w.y,K,M,J,g,i):0,my:l}):C},R.polys={polygon:function(a,b){var c,d,e,f={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10},adjustable:E},g=0,h=[],i=1,j=1,k=0,l=0;for(g=a.length;g--;)c=[parseInt(a[--g],10),parseInt(a[g+1],10)],c[0]>f.position.right&&(f.position.right=c[0]),c[0]<f.position.left&&(f.position.left=c[0]),c[1]>f.position.bottom&&(f.position.bottom=c[1]),c[1]<f.position.top&&(f.position.top=c[1]),h.push(c);if(d=f.width=Math.abs(f.position.right-f.position.left),e=f.height=Math.abs(f.position.bottom-f.position.top),"c"===b.abbrev())f.position={left:f.position.left+f.width/2,top:f.position.top+f.height/2};else{for(;d>0&&e>0&&i>0&&j>0;)for(d=Math.floor(d/2),e=Math.floor(e/2),b.x===L?i=d:b.x===N?i=f.width-d:i+=Math.floor(d/2),b.y===K?j=e:b.y===M?j=f.height-e:j+=Math.floor(e/2),g=h.length;g--&&!(h.length<2);)k=h[g][0]-f.position.left,l=h[g][1]-f.position.top,(b.x===L&&k>=i||b.x===N&&i>=k||b.x===O&&(i>k||k>f.width-i)||b.y===K&&l>=j||b.y===M&&j>=l||b.y===O&&(j>l||l>f.height-j))&&h.splice(g,1);f.position={left:h[0][0],top:h[0][1]}}return f},rect:function(a,b,c,d){return{width:Math.abs(c-a),height:Math.abs(d-b),position:{left:Math.min(a,c),top:Math.min(b,d)}}},_angles:{tc:1.5,tr:7/4,tl:5/4,bc:.5,br:.25,bl:.75,rc:2,lc:1,c:0},ellipse:function(a,b,c,d,e){var f=R.polys._angles[e.abbrev()],g=0===f?0:c*Math.cos(f*Math.PI),h=d*Math.sin(f*Math.PI);return{width:2*c-Math.abs(g),height:2*d-Math.abs(h),position:{left:a+g,top:b+h},adjustable:E}},circle:function(a,b,c,d){return R.polys.ellipse(a,b,c,c,d)}},R.svg=function(a,c,e){for(var f,g,h,i,j,k,l,m,n,o=(d(b),c[0]),p=d(o.ownerSVGElement),q=o.ownerDocument,r=(parseInt(c.css("stroke-width"),10)||0)/2;!o.getBBox;)o=o.parentNode;if(!o.getBBox||!o.parentNode)return E;switch(o.nodeName){case"ellipse":case"circle":m=R.polys.ellipse(o.cx.baseVal.value,o.cy.baseVal.value,(o.rx||o.r).baseVal.value+r,(o.ry||o.r).baseVal.value+r,e);break;case"line":case"polygon":case"polyline":for(l=o.points||[{x:o.x1.baseVal.value,y:o.y1.baseVal.value},{x:o.x2.baseVal.value,y:o.y2.baseVal.value}],m=[],k=-1,i=l.numberOfItems||l.length;++k<i;)j=l.getItem?l.getItem(k):l[k],m.push.apply(m,[j.x,j.y]);m=R.polys.polygon(m,e);break;default:m=o.getBBox(),m={width:m.width,height:m.height,position:{left:m.x,top:m.y}}}return n=m.position,p=p[0],p.createSVGPoint&&(g=o.getScreenCTM(),l=p.createSVGPoint(),l.x=n.left,l.y=n.top,h=l.matrixTransform(g),n.left=h.x,n.top=h.y),q!==b&&"mouse"!==a.position.target&&(f=d((q.defaultView||q.parentWindow).frameElement).offset(),f&&(n.left+=f.left,n.top+=f.top)),q=d(q),n.left+=q.scrollLeft(),n.top+=q.scrollTop(),m},R.imagemap=function(a,b,c){b.jquery||(b=d(b));var e,f,g,h,i,j=(b.attr("shape")||"rect").toLowerCase().replace("poly","polygon"),k=d('img[usemap="#'+b.parent("map").attr("name")+'"]'),l=d.trim(b.attr("coords")),m=l.replace(/,$/,"").split(",");if(!k.length)return E;if("polygon"===j)h=R.polys.polygon(m,c);else{if(!R.polys[j])return E;for(g=-1,i=m.length,f=[];++g<i;)f.push(parseInt(m[g],10));h=R.polys[j].apply(this,f.concat(c))}return e=k.offset(),e.left+=Math.ceil((k.outerWidth(E)-k.width())/2),e.top+=Math.ceil((k.outerHeight(E)-k.height())/2),h.position.left+=e.left,h.position.top+=e.top,h};var Ab,Bb='<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>';d.extend(x.prototype,{_scroll:function(){var b=this.qtip.elements.overlay;b&&(b[0].style.top=d(a).scrollTop()+"px")},init:function(c){var e=c.tooltip;d("select, object").length<1&&(this.bgiframe=c.elements.bgiframe=d(Bb).appendTo(e),c._bind(e,"tooltipmove",this.adjustBGIFrame,this._ns,this)),this.redrawContainer=d("<div/>",{id:S+"-rcontainer"}).appendTo(b.body),c.elements.overlay&&c.elements.overlay.addClass("qtipmodal-ie6fix")&&(c._bind(a,["scroll","resize"],this._scroll,this._ns,this),c._bind(e,["tooltipshow"],this._scroll,this._ns,this)),this.redraw()},adjustBGIFrame:function(){var a,b,c=this.qtip.tooltip,d={height:c.outerHeight(E),width:c.outerWidth(E)},e=this.qtip.plugins.tip,f=this.qtip.elements.tip;b=parseInt(c.css("borderLeftWidth"),10)||0,b={left:-b,top:-b},e&&f&&(a="x"===e.corner.precedance?[I,L]:[J,K],b[a[1]]-=f[a[0]]()),this.bgiframe.css(b).css(d)},redraw:function(){if(this.qtip.rendered<1||this.drawing)return this;var a,b,c,d,e=this.qtip.tooltip,f=this.qtip.options.style,g=this.qtip.options.position.container;return this.qtip.drawing=1,f.height&&e.css(J,f.height),f.width?e.css(I,f.width):(e.css(I,"").appendTo(this.redrawContainer),b=e.width(),1>b%2&&(b+=1),c=e.css("maxWidth")||"",d=e.css("minWidth")||"",a=(c+d).indexOf("%")>-1?g.width()/100:0,c=(c.indexOf("%")>-1?a:1)*parseInt(c,10)||b,d=(d.indexOf("%")>-1?a:1)*parseInt(d,10)||0,b=c+d?Math.min(Math.max(b,d),c):b,e.css(I,Math.round(b)).appendTo(g)),this.drawing=0,this},destroy:function(){this.bgiframe&&this.bgiframe.remove(),this.qtip._unbind([a,this.qtip.tooltip],this._ns)}}),Ab=R.ie6=function(a){return 6===db.ie?new x(a):E},Ab.initialize="render",B.ie6={"^content|style$":function(){this.redraw()}}})}(window,document);
|
|
|
188 |
</script>
|
installer/dup-installer/classes/class.db.php
CHANGED
@@ -26,7 +26,6 @@ class DUPX_DB
|
|
26 |
public static function connect($host, $username, $password, $dbname = '')
|
27 |
{
|
28 |
$dbh = null;
|
29 |
-
|
30 |
try {
|
31 |
//sock connections
|
32 |
if ('sock' === substr($host, -4)) {
|
@@ -92,7 +91,7 @@ class DUPX_DB
|
|
92 |
*
|
93 |
* @param obj $dbh A valid database link handle
|
94 |
* @param string $name A valid table name to remove
|
95 |
-
*
|
96 |
* @return null
|
97 |
*/
|
98 |
public static function dropTable($dbh, $name)
|
@@ -122,12 +121,12 @@ class DUPX_DB
|
|
122 |
}
|
123 |
|
124 |
if (DUPX_U::isTraversable($collations)) {
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
}
|
129 |
}
|
130 |
}
|
|
|
131 |
$result->free();
|
132 |
|
133 |
return $status;
|
@@ -143,7 +142,7 @@ class DUPX_DB
|
|
143 |
*/
|
144 |
public static function getDatabases($dbh, $dbuser = '')
|
145 |
{
|
146 |
-
$sql = strlen($dbuser) ? "SHOW DATABASES LIKE '%
|
147 |
$query = @mysqli_query($dbh, $sql);
|
148 |
if ($query) {
|
149 |
while ($db = @mysqli_fetch_array($query)) {
|
@@ -256,7 +255,7 @@ class DUPX_DB
|
|
256 |
return version_compare($version, '4.1', '>=');
|
257 |
case 'set_charset' :
|
258 |
return version_compare($version, '5.0.7', '>=');
|
259 |
-
}
|
260 |
return false;
|
261 |
}
|
262 |
|
@@ -291,7 +290,7 @@ class DUPX_DB
|
|
291 |
{
|
292 |
$result = array();
|
293 |
|
294 |
-
DUPX_Log::info("calling mysqli query on $sql");
|
295 |
$query_result = mysqli_query($dbh, $sql);
|
296 |
|
297 |
if ($query_result !== false) {
|
@@ -363,11 +362,27 @@ class DUPX_DB
|
|
363 |
|
364 |
if (self::hasAbility($dbh, 'collation') && !empty($charset)) {
|
365 |
if (function_exists('mysqli_set_charset') && self::hasAbility($dbh, 'set_charset')) {
|
366 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
367 |
} else {
|
368 |
$sql = " SET NAMES ".mysqli_real_escape_string($dbh, $charset);
|
369 |
-
if (!empty($collate))
|
370 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
}
|
372 |
}
|
373 |
}
|
@@ -388,4 +403,22 @@ class DUPX_DB
|
|
388 |
}
|
389 |
return in_array($table_name, $cached_table_names);
|
390 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
}
|
26 |
public static function connect($host, $username, $password, $dbname = '')
|
27 |
{
|
28 |
$dbh = null;
|
|
|
29 |
try {
|
30 |
//sock connections
|
31 |
if ('sock' === substr($host, -4)) {
|
91 |
*
|
92 |
* @param obj $dbh A valid database link handle
|
93 |
* @param string $name A valid table name to remove
|
94 |
+
*
|
95 |
* @return null
|
96 |
*/
|
97 |
public static function dropTable($dbh, $name)
|
121 |
}
|
122 |
|
123 |
if (DUPX_U::isTraversable($collations)) {
|
124 |
+
foreach ($collations as $key => $val) {
|
125 |
+
$status[$key]['name'] = $val;
|
126 |
+
$status[$key]['found'] = (in_array($val, $localhost)) ? 1 : 0;
|
|
|
127 |
}
|
128 |
}
|
129 |
+
}
|
130 |
$result->free();
|
131 |
|
132 |
return $status;
|
142 |
*/
|
143 |
public static function getDatabases($dbh, $dbuser = '')
|
144 |
{
|
145 |
+
$sql = strlen($dbuser) ? "SHOW DATABASES LIKE '%".mysqli_real_escape_string($dbh, $dbuser)."%'" : 'SHOW DATABASES';
|
146 |
$query = @mysqli_query($dbh, $sql);
|
147 |
if ($query) {
|
148 |
while ($db = @mysqli_fetch_array($query)) {
|
255 |
return version_compare($version, '4.1', '>=');
|
256 |
case 'set_charset' :
|
257 |
return version_compare($version, '5.0.7', '>=');
|
258 |
+
}
|
259 |
return false;
|
260 |
}
|
261 |
|
290 |
{
|
291 |
$result = array();
|
292 |
|
293 |
+
DUPX_Log::info("calling mysqli query on $sql", DUPX_Log::LV_HARD_DEBUG);
|
294 |
$query_result = mysqli_query($dbh, $sql);
|
295 |
|
296 |
if ($query_result !== false) {
|
362 |
|
363 |
if (self::hasAbility($dbh, 'collation') && !empty($charset)) {
|
364 |
if (function_exists('mysqli_set_charset') && self::hasAbility($dbh, 'set_charset')) {
|
365 |
+
if (($result = mysqli_set_charset($dbh, mysqli_real_escape_string($dbh, $charset))) === false) {
|
366 |
+
$errMsg = mysqli_error($dbh);
|
367 |
+
DUPX_Log::info('DATABASE ERROR: mysqli_set_charset '.DUPX_Log::varToString($charset).' MSG: '.$errMsg);
|
368 |
+
} else {
|
369 |
+
DUPX_Log::info('DATABASE: mysqli_set_charset '.DUPX_Log::varToString($charset), DUPX_Log::LV_DETAILED);
|
370 |
+
}
|
371 |
+
return $result;
|
372 |
} else {
|
373 |
$sql = " SET NAMES ".mysqli_real_escape_string($dbh, $charset);
|
374 |
+
if (!empty($collate)) {
|
375 |
+
$sql .= " COLLATE ".mysqli_real_escape_string($dbh, $collate);
|
376 |
+
}
|
377 |
+
|
378 |
+
if (($result = mysqli_query($dbh, $sql)) === false) {
|
379 |
+
$errMsg = mysqli_error($dbh);
|
380 |
+
DUPX_Log::info('DATABASE SQL ERROR: '.DUPX_Log::varToString($sql).' MSG: '.$errMsg);
|
381 |
+
} else {
|
382 |
+
DUPX_Log::info('DATABASE SQL: '.DUPX_Log::varToString($sql), DUPX_Log::LV_DETAILED);
|
383 |
+
}
|
384 |
+
|
385 |
+
return $result;
|
386 |
}
|
387 |
}
|
388 |
}
|
403 |
}
|
404 |
return in_array($table_name, $cached_table_names);
|
405 |
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* mysqli_query wrapper with logging
|
409 |
+
*
|
410 |
+
* @param mysqli $link
|
411 |
+
* @param string $sql
|
412 |
+
* @return type
|
413 |
+
*/
|
414 |
+
public static function mysqli_query($link, $sql, $file = '', $line = '')
|
415 |
+
{
|
416 |
+
if (($result = mysqli_query($link, $sql)) === false) {
|
417 |
+
DUPX_Log::info('DB QUERY [ERROR]['.$file.':'.$line.'] SQL: '.DUPX_Log::varToString($sql)."\n\t MSG: ".mysqli_error($link));
|
418 |
+
} else {
|
419 |
+
DUPX_Log::info('DB QUERY ['.$file.':'.$line.']: '.DUPX_Log::varToString($sql), DUPX_Log::LV_HARD_DEBUG);
|
420 |
+
}
|
421 |
+
|
422 |
+
return $result;
|
423 |
+
}
|
424 |
}
|
installer/dup-installer/classes/class.engine.php
CHANGED
@@ -1,6 +1,4 @@
|
|
1 |
<?php
|
2 |
-
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
-
|
4 |
/**
|
5 |
* Walks every table in db that then walks every row and column replacing searches with replaces
|
6 |
* large tables are split into 50k row blocks to save on memory.
|
@@ -11,39 +9,42 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
11 |
* @package SC\DUPX\UpdateEngine
|
12 |
*
|
13 |
*/
|
|
|
|
|
14 |
class DUPX_UpdateEngine
|
15 |
{
|
|
|
16 |
|
17 |
/**
|
18 |
* Used to report on all log errors into the installer-txt.log
|
19 |
*
|
20 |
-
* @param string $report The report error array of all error types
|
21 |
-
*
|
22 |
* @return string Writes the results of the update engine tables to the log
|
23 |
*/
|
24 |
-
public static function logErrors(
|
25 |
{
|
26 |
-
|
|
|
|
|
27 |
DUPX_Log::info("--------------------------------------");
|
28 |
DUPX_Log::info("DATA-REPLACE ERRORS (MySQL)");
|
29 |
-
foreach ($report['errsql'] as $error) {
|
30 |
DUPX_Log::info($error);
|
31 |
}
|
32 |
DUPX_Log::info("");
|
33 |
}
|
34 |
-
if (!empty($report['errser'])) {
|
35 |
DUPX_Log::info("--------------------------------------");
|
36 |
DUPX_Log::info("DATA-REPLACE ERRORS (Serialization):");
|
37 |
-
foreach ($report['errser'] as $error) {
|
38 |
DUPX_Log::info($error);
|
39 |
}
|
40 |
DUPX_Log::info("");
|
41 |
}
|
42 |
-
if (!empty($report['errkey'])) {
|
43 |
DUPX_Log::info("--------------------------------------");
|
44 |
DUPX_Log::info("DATA-REPLACE ERRORS (Key):");
|
45 |
DUPX_Log::info('Use SQL: SELECT @row := @row + 1 as row, t.* FROM some_table t, (SELECT @row := 0) r');
|
46 |
-
foreach ($report['errkey'] as $error) {
|
47 |
DUPX_Log::info($error);
|
48 |
}
|
49 |
}
|
@@ -52,22 +53,18 @@ class DUPX_UpdateEngine
|
|
52 |
/**
|
53 |
* Used to report on all log stats into the installer-txt.log
|
54 |
*
|
55 |
-
* @param string $report The report stats array of all error types
|
56 |
-
*
|
57 |
* @return string Writes the results of the update engine tables to the log
|
58 |
*/
|
59 |
-
public static function logStats(
|
60 |
{
|
61 |
-
|
|
|
|
|
|
|
62 |
$stats = "--------------------------------------\n";
|
63 |
-
$
|
64 |
-
|
65 |
-
|
66 |
-
$stats .= sprintf("Search{$srchnum}:\t'%s' \nChange{$srchnum}:\t'%s' \n", $item['search'], $item['replace']);
|
67 |
-
}
|
68 |
-
$stats .= sprintf("SCANNED:\tTables:%d \t|\t Rows:%d \t|\t Cells:%d \n", $report['scan_tables'], $report['scan_rows'], $report['scan_cells']);
|
69 |
-
$stats .= sprintf("UPDATED:\tTables:%d \t|\t Rows:%d \t|\t Cells:%d \n", $report['updt_tables'], $report['updt_rows'], $report['updt_cells']);
|
70 |
-
$stats .= sprintf("ERRORS:\t\t%d \nRUNTIME:\t%f sec", $report['err_all'], $report['time']);
|
71 |
DUPX_Log::info($stats);
|
72 |
}
|
73 |
}
|
@@ -75,30 +72,26 @@ class DUPX_UpdateEngine
|
|
75 |
/**
|
76 |
* Returns only the text type columns of a table ignoring all numeric types
|
77 |
*
|
78 |
-
* @param obj $
|
79 |
* @param string $table A valid table name
|
80 |
*
|
81 |
* @return array All the column names of a table
|
82 |
*/
|
83 |
-
|
84 |
{
|
85 |
-
$
|
86 |
-
|
87 |
-
$type_where
|
88 |
-
$type_where .= "type
|
89 |
-
$type_where .= "type
|
90 |
-
$type_where .= "type
|
91 |
-
$
|
92 |
-
|
93 |
-
$
|
94 |
-
$type_where .= "type NOT LIKE 'date%' AND ";
|
95 |
-
$type_where .= "type NOT LIKE 'time%' AND ";
|
96 |
-
$type_where .= "type NOT LIKE 'year%' ";
|
97 |
-
|
98 |
-
$result = mysqli_query($conn, "SHOW COLUMNS FROM `".mysqli_real_escape_string($conn, $table)."` WHERE {$type_where}");
|
99 |
if (!$result) {
|
100 |
return null;
|
101 |
}
|
|
|
102 |
$fields = array();
|
103 |
if (mysqli_num_rows($result) > 0) {
|
104 |
while ($row = mysqli_fetch_assoc($result)) {
|
@@ -107,380 +100,617 @@ class DUPX_UpdateEngine
|
|
107 |
}
|
108 |
|
109 |
//Return Primary which is needed for index lookup. LIKE '%PRIMARY%' is less accurate with lookup
|
110 |
-
//$result = mysqli_query($
|
111 |
-
$result = mysqli_query($
|
112 |
if (mysqli_num_rows($result) > 0) {
|
113 |
while ($row = mysqli_fetch_assoc($result)) {
|
114 |
$fields[] = $row['Column_name'];
|
115 |
}
|
116 |
}
|
117 |
|
118 |
-
return (count($fields) > 0) ? $fields : null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
}
|
120 |
|
121 |
/**
|
122 |
* Begins the processing for replace logic
|
123 |
*
|
124 |
-
* @param mysql $dbh The db connection object
|
125 |
-
* @param array $list Key value pair of 'search' and 'replace' arrays
|
126 |
* @param array $tables The tables we want to look at
|
127 |
-
* @param array $fullsearch Search every column regardless of its data type
|
128 |
*
|
129 |
* @return array Collection of information gathered during the run.
|
130 |
*/
|
131 |
-
public static function load($
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
'
|
138 |
-
'
|
139 |
-
'
|
140 |
-
'
|
141 |
-
'
|
142 |
-
'
|
143 |
-
'
|
144 |
-
'
|
145 |
-
'
|
146 |
-
'
|
147 |
-
'
|
148 |
-
'errkey_sum' => 0,
|
149 |
-
'time' => '',
|
150 |
-
'err_all' => 0
|
151 |
);
|
|
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
}
|
158 |
|
159 |
-
$
|
160 |
-
if (is_array($tables) && !empty($tables)) {
|
161 |
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
$row_count = mysqli_query($conn, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($conn, $table)."`");
|
176 |
-
$rows_result = mysqli_fetch_array($row_count);
|
177 |
-
@mysqli_free_result($row_count);
|
178 |
-
$row_count = $rows_result[0];
|
179 |
-
if ($row_count == 0) {
|
180 |
-
DUPX_Log::info("{$table}^ ({$row_count})");
|
181 |
-
continue;
|
182 |
-
}
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
$colList = self::getTextColumns($conn, $table);
|
194 |
-
if ($colList != null && is_array($colList)) {
|
195 |
-
array_walk($colList, 'set_sql_column_safe');
|
196 |
-
$colList = implode(',', $colList);
|
197 |
-
}
|
198 |
-
$colMsg = (empty($colList)) ? '*' : '~';
|
199 |
-
}
|
200 |
|
201 |
-
|
202 |
-
|
203 |
-
continue;
|
204 |
-
} else {
|
205 |
-
DUPX_Log::info("{$table}{$colMsg} ({$row_count})");
|
206 |
-
}
|
207 |
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
|
|
|
|
|
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
|
220 |
-
|
221 |
-
DUPX_Log::info("\tScan => {$start} of {$scan_count}", 2);
|
222 |
-
|
223 |
-
//Loops every row
|
224 |
-
while ($row = mysqli_fetch_array($data)) {
|
225 |
-
$report['scan_rows']++;
|
226 |
-
$current_row++;
|
227 |
-
$upd_col = array();
|
228 |
-
$upd_sql = array();
|
229 |
-
$where_sql = array();
|
230 |
-
$upd = false;
|
231 |
-
$serial_err = 0;
|
232 |
-
$is_unkeyed = !in_array(true, $columns);
|
233 |
-
$rowErrors = array();
|
234 |
-
|
235 |
-
//Loops every cell
|
236 |
-
foreach ($columns as $column => $primary_key) {
|
237 |
-
$report['scan_cells']++;
|
238 |
-
if (!isset($row[$column])) continue;
|
239 |
-
|
240 |
-
$safe_column = '`'.mysqli_real_escape_string($conn, $column).'`';
|
241 |
-
$edited_data = $data_to_fix = $row[$column];
|
242 |
-
$base64converted = false;
|
243 |
-
$txt_found = false;
|
244 |
-
|
245 |
-
//Unkeyed table code
|
246 |
-
//Added this here to add all columns to $where_sql
|
247 |
-
//The if statement with $txt_found would skip additional columns -TG
|
248 |
-
if($is_unkeyed && ! empty($data_to_fix)) {
|
249 |
-
$where_sql[] = $safe_column . ' = "' . mysqli_real_escape_string($conn, $data_to_fix) . '"';
|
250 |
-
}
|
251 |
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
}
|
261 |
-
|
262 |
-
if (!$txt_found) {
|
263 |
-
//if not found decetc Base 64
|
264 |
-
if (($decoded = DUPX_U::is_base64($row[$column])) !== false) {
|
265 |
-
$edited_data = $decoded;
|
266 |
-
$base64converted = true;
|
267 |
-
|
268 |
-
// Search strings in data decoded
|
269 |
-
foreach ($list as $item) {
|
270 |
-
if (strpos($edited_data, $item['search']) !== false) {
|
271 |
-
$txt_found = true;
|
272 |
-
break;
|
273 |
-
}
|
274 |
-
}
|
275 |
-
}
|
276 |
-
|
277 |
-
//Skip table cell if match not found
|
278 |
-
if (!$txt_found) {
|
279 |
-
continue;
|
280 |
-
}
|
281 |
-
}
|
282 |
-
|
283 |
-
if (self::isSerialized($edited_data) && strlen($edited_data) > MAX_STRLEN_SERIALIZED_CHECK) {
|
284 |
-
// skip search and replace for too big serialized string
|
285 |
-
$serial_err++;
|
286 |
-
$trimLen = DUPX_Log::isLevel(DUPX_Log::LV_HARD_DEBUG) ? 10000 : 150;
|
287 |
-
$rowErrors[$column] = 'ENGINE: serialize data too big to convert; data len:'.strlen($edited_data).' Max size:'.MAX_STRLEN_SERIALIZED_CHECK;
|
288 |
-
$rowErrors[$column] .= "\n\tDATA: ".mb_strimwidth($edited_data, 0, $trimLen, ' [...]');
|
289 |
-
} else {
|
290 |
-
//Replace logic - level 1: simple check on any string or serlized strings
|
291 |
-
foreach ($list as $item) {
|
292 |
-
$objArr = array();
|
293 |
-
$edited_data = self::recursiveUnserializeReplace($item['search'], $item['replace'], $edited_data, false, $objArr);
|
294 |
-
}
|
295 |
-
|
296 |
-
//Replace logic - level 2: repair serialized strings that have become broken
|
297 |
-
$serial_check = self::fixSerialString($edited_data);
|
298 |
-
if ($serial_check['fixed']) {
|
299 |
-
$edited_data = $serial_check['data'];
|
300 |
-
} elseif ($serial_check['tried'] && !$serial_check['fixed']) {
|
301 |
-
$serial_err++;
|
302 |
-
$trimLen = DUPX_Log::isLevel(DUPX_Log::LV_HARD_DEBUG) ? 10000 : 150;
|
303 |
-
$rowErrors[$column] = 'ENGINE: serialize data serial check error';
|
304 |
-
$rowErrors[$column] .= "\n\tDATA: ".mb_strimwidth($edited_data, 0, $trimLen, ' [...]');
|
305 |
-
}
|
306 |
-
}
|
307 |
-
}
|
308 |
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
|
|
|
|
320 |
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
}
|
325 |
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
if ($result) {
|
331 |
-
foreach ($rowErrors as $errCol => $msgCol) {
|
332 |
-
$longMsg = $msgCol."\n\tTABLE:".$table.' COLUMN: '.$errCol. ' WHERE: '.implode(' AND ', array_filter($where_sql));
|
333 |
-
$report['errser'][] = $longMsg;
|
334 |
-
|
335 |
-
$nManager->addFinalReportNotice(array(
|
336 |
-
'shortMsg' => 'DATA-REPLACE ERROR: Serialization',
|
337 |
-
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
338 |
-
'longMsg' => $longMsg,
|
339 |
-
'sections' => 'search_replace'
|
340 |
-
));
|
341 |
-
}
|
342 |
-
$report['updt_rows']++;
|
343 |
-
} else {
|
344 |
-
$errMsg = mysqli_error($conn);
|
345 |
-
$report['errsql'][] = (DUPX_Log::isLevel(DUPX_Log::LV_DEBUG))
|
346 |
-
? 'DB ERROR: ' . $errMsg . "\nSQL: ".mb_strimwidth($sql, 0, 100000, ' [...]')."\n"
|
347 |
-
: 'DB ERROR: ' . $errMsg;
|
348 |
-
|
349 |
-
$nManager->addFinalReportNotice(array(
|
350 |
-
'shortMsg' => 'DATA-REPLACE ERRORS: MySQL',
|
351 |
-
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
352 |
-
'longMsg' => $errMsg,
|
353 |
-
'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_PRE,
|
354 |
-
'sections' => 'search_replace'
|
355 |
-
));
|
356 |
-
}
|
357 |
-
//DEBUG ONLY:
|
358 |
-
DUPX_Log::info("\t".mb_strimwidth($sql, 0, 100000, ' [...]')."\n", DUPX_Log::LV_HARD_DEBUG);
|
359 |
-
} elseif ($upd) {
|
360 |
-
$errMsg = sprintf("Row [%s] on Table [%s] requires a manual update.", $current_row, $table);
|
361 |
-
$report['errkey'][] = $errMsg;
|
362 |
-
|
363 |
-
$nManager->addFinalReportNotice(array(
|
364 |
-
'shortMsg' => 'DATA-REPLACE ERROR: Key',
|
365 |
-
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
366 |
-
'longMsg' => $errMsg,
|
367 |
-
'sections' => 'search_replace'
|
368 |
-
));
|
369 |
-
}
|
370 |
-
}
|
371 |
-
//DUPX_U::fcgiFlush();
|
372 |
-
@mysqli_free_result($data);
|
373 |
-
}
|
374 |
|
375 |
-
|
376 |
-
|
377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
378 |
}
|
379 |
}
|
380 |
|
381 |
-
|
382 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
383 |
|
384 |
-
|
|
|
|
|
|
|
385 |
|
386 |
-
|
387 |
-
|
388 |
-
$report['errsql_sum'] = empty($report['errsql']) ? 0 : count($report['errsql']);
|
389 |
-
$report['errser_sum'] = empty($report['errser']) ? 0 : count($report['errser']);
|
390 |
-
$report['errkey_sum'] = empty($report['errkey']) ? 0 : count($report['errkey']);
|
391 |
-
$report['err_all'] = $report['errsql_sum'] + $report['errser_sum'] + $report['errkey_sum'];
|
392 |
|
393 |
-
return $
|
394 |
}
|
395 |
|
396 |
/**
|
397 |
-
*
|
398 |
-
* serializing any subordinate arrays and performing the replace.
|
399 |
*
|
400 |
-
* @param
|
401 |
-
* @param
|
402 |
-
* @param array $data Used to pass any subordinate arrays back to in.
|
403 |
-
* @param bool $serialised Does the array passed via $data need serializing.
|
404 |
*
|
405 |
-
* @return
|
406 |
*/
|
407 |
-
|
408 |
{
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
418 |
}
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
return $data;
|
426 |
}
|
427 |
}
|
428 |
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
$
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
$property_name = self::cleanPropertyName($_tmp,$key);
|
442 |
-
$_tmp->setVar($property_name,$obj_replace_result);
|
443 |
-
}else{
|
444 |
-
$_tmp->$key = $obj_replace_result;
|
445 |
}
|
446 |
}
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
460 |
}
|
461 |
}
|
462 |
}
|
463 |
}
|
464 |
-
|
465 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
466 |
} else {
|
467 |
-
if
|
468 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
469 |
}
|
470 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
471 |
|
472 |
-
|
473 |
-
|
474 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
475 |
}
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
|
|
|
|
480 |
}
|
|
|
481 |
return $data;
|
482 |
}
|
483 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
484 |
/**
|
485 |
* Test if a string in properly serialized
|
486 |
*
|
@@ -488,7 +718,7 @@ class DUPX_UpdateEngine
|
|
488 |
*
|
489 |
* @return bool Is the string a serialized string
|
490 |
*/
|
491 |
-
public static function
|
492 |
{
|
493 |
if (!is_string($data)) {
|
494 |
return false;
|
@@ -497,9 +727,9 @@ class DUPX_UpdateEngine
|
|
497 |
} else {
|
498 |
try {
|
499 |
DUPX_Handler::setMode(DUPX_Handler::MODE_OFF);
|
500 |
-
$unserialize_ret = @unserialize($data)
|
501 |
DUPX_Handler::setMode();
|
502 |
-
return $unserialize_ret;
|
503 |
} catch (Exception $e) {
|
504 |
DUPX_Log::info("Unserialize exception: ".$e->getMessage());
|
505 |
//DEBUG ONLY:
|
@@ -508,6 +738,84 @@ class DUPX_UpdateEngine
|
|
508 |
}
|
509 |
}
|
510 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
511 |
|
512 |
/**
|
513 |
* Fixes the string length of a string object that has been serialized but the length is broken
|
@@ -519,34 +827,133 @@ class DUPX_UpdateEngine
|
|
519 |
public static function fixSerialString($data)
|
520 |
{
|
521 |
$result = array('data' => $data, 'fixed' => false, 'tried' => false);
|
522 |
-
if (preg_match("/s:[0-9]+:/", $data)) {
|
523 |
-
if (!self::isSerialized($data)) {
|
524 |
-
$regex = '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|d:|i:|o:|N;))!s';
|
525 |
-
$serial_string = preg_match('/^s:[0-9]+:"(.*$)/s', trim($data), $matches);
|
526 |
-
//Nested serial string
|
527 |
-
if ($serial_string) {
|
528 |
-
$inner = preg_replace_callback($regex, 'DUPX_UpdateEngine::fixStringCallback',
|
529 |
-
rtrim($matches[1], '";'));
|
530 |
-
$serialized_fixed = 's:' . strlen($inner) . ':"' . $inner . '";';
|
531 |
-
} else {
|
532 |
-
$serialized_fixed = preg_replace_callback($regex, 'DUPX_UpdateEngine::fixStringCallback', $data);
|
533 |
-
}
|
534 |
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
|
|
|
|
|
|
|
|
|
|
540 |
}
|
|
|
|
|
541 |
}
|
|
|
542 |
return $result;
|
543 |
}
|
544 |
|
545 |
/**
|
546 |
-
*
|
|
|
|
|
|
|
|
|
|
|
547 |
*/
|
548 |
-
|
549 |
{
|
550 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
551 |
}
|
552 |
}
|
1 |
<?php
|
|
|
|
|
2 |
/**
|
3 |
* Walks every table in db that then walks every row and column replacing searches with replaces
|
4 |
* large tables are split into 50k row blocks to save on memory.
|
9 |
* @package SC\DUPX\UpdateEngine
|
10 |
*
|
11 |
*/
|
12 |
+
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
13 |
+
|
14 |
class DUPX_UpdateEngine
|
15 |
{
|
16 |
+
private static $report = null;
|
17 |
|
18 |
/**
|
19 |
* Used to report on all log errors into the installer-txt.log
|
20 |
*
|
|
|
|
|
21 |
* @return string Writes the results of the update engine tables to the log
|
22 |
*/
|
23 |
+
public static function logErrors()
|
24 |
{
|
25 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
26 |
+
|
27 |
+
if (!empty($s3Funcs->report['errsql'])) {
|
28 |
DUPX_Log::info("--------------------------------------");
|
29 |
DUPX_Log::info("DATA-REPLACE ERRORS (MySQL)");
|
30 |
+
foreach ($s3Funcs->report['errsql'] as $error) {
|
31 |
DUPX_Log::info($error);
|
32 |
}
|
33 |
DUPX_Log::info("");
|
34 |
}
|
35 |
+
if (!empty($s3Funcs->report['errser'])) {
|
36 |
DUPX_Log::info("--------------------------------------");
|
37 |
DUPX_Log::info("DATA-REPLACE ERRORS (Serialization):");
|
38 |
+
foreach ($s3Funcs->report['errser'] as $error) {
|
39 |
DUPX_Log::info($error);
|
40 |
}
|
41 |
DUPX_Log::info("");
|
42 |
}
|
43 |
+
if (!empty($s3Funcs->report['errkey'])) {
|
44 |
DUPX_Log::info("--------------------------------------");
|
45 |
DUPX_Log::info("DATA-REPLACE ERRORS (Key):");
|
46 |
DUPX_Log::info('Use SQL: SELECT @row := @row + 1 as row, t.* FROM some_table t, (SELECT @row := 0) r');
|
47 |
+
foreach ($s3Funcs->report['errkey'] as $error) {
|
48 |
DUPX_Log::info($error);
|
49 |
}
|
50 |
}
|
53 |
/**
|
54 |
* Used to report on all log stats into the installer-txt.log
|
55 |
*
|
|
|
|
|
56 |
* @return string Writes the results of the update engine tables to the log
|
57 |
*/
|
58 |
+
public static function logStats()
|
59 |
{
|
60 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
61 |
+
DUPX_Log::resetIndent();
|
62 |
+
|
63 |
+
if (!empty($s3Funcs->report) && is_array($s3Funcs->report)) {
|
64 |
$stats = "--------------------------------------\n";
|
65 |
+
$stats .= sprintf("SCANNED:\tTables:%d \t|\t Rows:%d \t|\t Cells:%d \n", $s3Funcs->report['scan_tables'], $s3Funcs->report['scan_rows'], $s3Funcs->report['scan_cells']);
|
66 |
+
$stats .= sprintf("UPDATED:\tTables:%d \t|\t Rows:%d \t|\t Cells:%d \n", $s3Funcs->report['updt_tables'], $s3Funcs->report['updt_rows'], $s3Funcs->report['updt_cells']);
|
67 |
+
$stats .= sprintf("ERRORS:\t\t%d \nRUNTIME:\t%f sec", $s3Funcs->report['err_all'], $s3Funcs->report['time']);
|
|
|
|
|
|
|
|
|
|
|
68 |
DUPX_Log::info($stats);
|
69 |
}
|
70 |
}
|
72 |
/**
|
73 |
* Returns only the text type columns of a table ignoring all numeric types
|
74 |
*
|
75 |
+
* @param obj $conn A valid database link handle
|
76 |
* @param string $table A valid table name
|
77 |
*
|
78 |
* @return array All the column names of a table
|
79 |
*/
|
80 |
+
private static function getTextColumns($table)
|
81 |
{
|
82 |
+
$dbh = DUPX_S3_Funcs::getInstance()->getDbConnection();
|
83 |
+
|
84 |
+
$type_where = '';
|
85 |
+
$type_where .= "type LIKE '%char%' OR ";
|
86 |
+
$type_where .= "type LIKE '%text' OR ";
|
87 |
+
$type_where .= "type LIKE '%blob' ";
|
88 |
+
$sql = "SHOW COLUMNS FROM `".mysqli_real_escape_string($dbh, $table)."` WHERE {$type_where}";
|
89 |
+
|
90 |
+
$result = DUPX_DB::mysqli_query($dbh, $sql, __FILE__, __LINE__);
|
|
|
|
|
|
|
|
|
|
|
91 |
if (!$result) {
|
92 |
return null;
|
93 |
}
|
94 |
+
|
95 |
$fields = array();
|
96 |
if (mysqli_num_rows($result) > 0) {
|
97 |
while ($row = mysqli_fetch_assoc($result)) {
|
100 |
}
|
101 |
|
102 |
//Return Primary which is needed for index lookup. LIKE '%PRIMARY%' is less accurate with lookup
|
103 |
+
//$result = mysqli_query($dbh, "SHOW INDEX FROM `{$table}` WHERE KEY_NAME LIKE '%PRIMARY%'");
|
104 |
+
$result = mysqli_query($dbh, "SHOW INDEX FROM `".mysqli_real_escape_string($dbh, $table)."`");
|
105 |
if (mysqli_num_rows($result) > 0) {
|
106 |
while ($row = mysqli_fetch_assoc($result)) {
|
107 |
$fields[] = $row['Column_name'];
|
108 |
}
|
109 |
}
|
110 |
|
111 |
+
return (count($fields) > 0) ? array_unique($fields) : null;
|
112 |
+
}
|
113 |
+
|
114 |
+
public static function set_sql_column_safe(&$str)
|
115 |
+
{
|
116 |
+
$str = "`$str`";
|
117 |
+
}
|
118 |
+
|
119 |
+
public static function loadInit()
|
120 |
+
{
|
121 |
+
DUPX_Log::info('ENGINE LOAD INIT', DUPX_Log::LV_DEBUG);
|
122 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
123 |
+
$s3Funcs->report['profile_start'] = DUPX_U::getMicrotime();
|
124 |
+
|
125 |
+
$dbh = $s3Funcs->getDbConnection();
|
126 |
+
@mysqli_autocommit($dbh, false);
|
127 |
}
|
128 |
|
129 |
/**
|
130 |
* Begins the processing for replace logic
|
131 |
*
|
|
|
|
|
132 |
* @param array $tables The tables we want to look at
|
|
|
133 |
*
|
134 |
* @return array Collection of information gathered during the run.
|
135 |
*/
|
136 |
+
public static function load($tables = array())
|
137 |
+
{
|
138 |
+
self::loadInit();
|
139 |
+
|
140 |
+
if (is_array($tables)) {
|
141 |
+
foreach ($tables as $table) {
|
142 |
+
self::evaluateTalbe($table);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
|
146 |
+
self::commitAndSave();
|
147 |
+
return self::loadEnd();
|
148 |
+
}
|
149 |
+
|
150 |
+
public static function commitAndSave()
|
151 |
{
|
152 |
+
DUPX_Log::info('ENGINE COMMIT AND SAVE', DUPX_Log::LV_DEBUG);
|
153 |
+
|
154 |
+
$dbh = DUPX_S3_Funcs::getInstance()->getDbConnection();
|
155 |
+
|
156 |
+
@mysqli_commit($dbh);
|
157 |
+
@mysqli_autocommit($dbh, true);
|
158 |
+
|
159 |
+
DUPX_NOTICE_MANAGER::getInstance()->saveNotices();
|
160 |
+
}
|
161 |
+
|
162 |
+
public static function loadEnd()
|
163 |
+
{
|
164 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
165 |
+
DUPX_Log::info('ENGINE LOAD END', DUPX_Log::LV_DEBUG);
|
166 |
+
|
167 |
+
$s3Funcs->report['profile_end'] = DUPX_U::getMicrotime();
|
168 |
+
$s3Funcs->report['time'] = DUPX_U::elapsedTime($s3Funcs->report['profile_end'], $s3Funcs->report['profile_start']);
|
169 |
+
$s3Funcs->report['errsql_sum'] = empty($s3Funcs->report['errsql']) ? 0 : count($s3Funcs->report['errsql']);
|
170 |
+
$s3Funcs->report['errser_sum'] = empty($s3Funcs->report['errser']) ? 0 : count($s3Funcs->report['errser']);
|
171 |
+
$s3Funcs->report['errkey_sum'] = empty($s3Funcs->report['errkey']) ? 0 : count($s3Funcs->report['errkey']);
|
172 |
+
$s3Funcs->report['err_all'] = $s3Funcs->report['errsql_sum'] + $s3Funcs->report['errser_sum'] + $s3Funcs->report['errkey_sum'];
|
173 |
+
|
174 |
+
return $s3Funcs->report;
|
175 |
+
}
|
176 |
|
177 |
+
public static function getTableRowParamsDefault($table = '')
|
178 |
+
{
|
179 |
+
return array(
|
180 |
+
'table' => $table,
|
181 |
+
'updated' => false,
|
182 |
+
'row_count' => 0,
|
183 |
+
'columns' => array(),
|
184 |
+
'colList' => '*',
|
185 |
+
'colMsg' => 'every column',
|
186 |
+
'columnsSRList' => array(),
|
187 |
+
'pages' => 0,
|
188 |
+
'page_size' => 0,
|
189 |
+
'page' => 0,
|
190 |
+
'current_row' => 0
|
|
|
|
|
|
|
191 |
);
|
192 |
+
}
|
193 |
|
194 |
+
private static function getTableRowsParams($table)
|
195 |
+
{
|
196 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
197 |
+
$dbh = $s3Funcs->getDbConnection();
|
|
|
198 |
|
199 |
+
$rowsParams = self::getTableRowParamsDefault($table);
|
|
|
200 |
|
201 |
+
// Count the number of rows we have in the table if large we'll split into blocks
|
202 |
+
$rowsParams['row_count'] = mysqli_query($dbh, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($dbh, $rowsParams['table'])."`");
|
203 |
+
if (!$rowsParams['row_count']) {
|
204 |
+
return null;
|
205 |
+
}
|
206 |
+
$rows_result = mysqli_fetch_array($rowsParams['row_count']);
|
207 |
+
@mysqli_free_result($rowsParams['row_count']);
|
208 |
+
$rowsParams['row_count'] = $rows_result[0];
|
209 |
+
if ($rowsParams['row_count'] == 0) {
|
210 |
+
$rowsParams['colMsg'] = 'no columns ';
|
211 |
+
self::logEvaluateTable($rowsParams);
|
212 |
+
return null;
|
213 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
214 |
|
215 |
+
// Get a list of columns in this table
|
216 |
+
$sql = 'DESCRIBE '.mysqli_real_escape_string($dbh, $rowsParams['table']);
|
217 |
+
$fields = mysqli_query($dbh, $sql);
|
218 |
+
if (!$fields) {
|
219 |
+
return null;
|
220 |
+
}
|
221 |
+
while ($column = mysqli_fetch_array($fields)) {
|
222 |
+
$rowsParams['columns'][$column['Field']] = $column['Key'] == 'PRI' ? true : false;
|
223 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
224 |
|
225 |
+
$rowsParams['page_size'] = $GLOBALS['DATABASE_PAGE_SIZE'];
|
226 |
+
$rowsParams['pages'] = ceil($rowsParams['row_count'] / $rowsParams['page_size']);
|
|
|
|
|
|
|
|
|
227 |
|
228 |
+
// Grab the columns of the table. Only grab text based columns because
|
229 |
+
// they are the only data types that should allow any type of search/replace logic
|
230 |
+
if (!$s3Funcs->getPost('fullsearch')) {
|
231 |
+
$rowsParams['colList'] = self::getTextColumns($rowsParams['table']);
|
232 |
+
if ($rowsParams['colList'] != null && is_array($rowsParams['colList'])) {
|
233 |
+
array_walk($rowsParams['colList'], array(__CLASS__, 'set_sql_column_safe'));
|
234 |
+
$rowsParams['colList'] = implode(',', $rowsParams['colList']);
|
235 |
+
}
|
236 |
+
$rowsParams['colMsg'] = (empty($rowsParams['colList'])) ? 'every column' : 'text columns';
|
237 |
+
}
|
238 |
|
239 |
+
if (empty($rowsParams['colList'])) {
|
240 |
+
$rowsParams['colMsg'] = 'no columns ';
|
241 |
+
}
|
242 |
|
243 |
+
self::logEvaluateTable($rowsParams);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
|
245 |
+
if (empty($rowsParams['colList'])) {
|
246 |
+
return null;
|
247 |
+
} else {
|
248 |
+
// PREPARE SEARCH AN REPLACE LISF FOR TABLES
|
249 |
+
$rowsParams['columnsSRList'] = self::getColumnsSearchReplaceList($rowsParams['table'], $rowsParams['columns']);
|
250 |
+
return $rowsParams;
|
251 |
+
}
|
252 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
|
254 |
+
public static function logEvaluateTable($rowsParams)
|
255 |
+
{
|
256 |
+
DUPX_Log::resetIndent();
|
257 |
+
$log = "\n".'EVALUATE TABLE: '.str_pad(DUPX_Log::varToString($rowsParams['table']), 50, '_', STR_PAD_RIGHT);
|
258 |
+
$log .= '[ROWS:'.str_pad($rowsParams['row_count'], 6, " ", STR_PAD_LEFT).']';
|
259 |
+
$log .= '[PG:'.str_pad($rowsParams['pages'], 4, " ", STR_PAD_LEFT).']';
|
260 |
+
$log .= '[SCAN:'.$rowsParams['colMsg'].']';
|
261 |
+
if (DUPX_Log::isLevel(DUPX_Log::LV_DETAILED)) {
|
262 |
+
$log .= '[COLS: '.$rowsParams['colList'].']';
|
263 |
+
}
|
264 |
+
DUPX_Log::info($log);
|
265 |
+
DUPX_Log::incIndent();
|
266 |
+
}
|
267 |
|
268 |
+
public static function evaluateTalbe($table)
|
269 |
+
{
|
270 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
|
|
271 |
|
272 |
+
// init table params if isn't inizialized
|
273 |
+
if (!self::initTableParams($table)) {
|
274 |
+
return false;
|
275 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
276 |
|
277 |
+
//Paged Records
|
278 |
+
$pages = $s3Funcs->cTableParams['pages'];
|
279 |
+
for ($page = 0; $page < $pages; $page ++) {
|
280 |
+
self::evaluateTableRows($table, $page);
|
281 |
+
}
|
282 |
+
|
283 |
+
if ($s3Funcs->cTableParams['updated']) {
|
284 |
+
$s3Funcs->report['updt_tables'] ++;
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
public static function evaluateTableRows($table, $page)
|
289 |
+
{
|
290 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
291 |
+
|
292 |
+
// init table params if isn't inizialized
|
293 |
+
if (!self::initTableParams($table)) {
|
294 |
+
return false;
|
295 |
+
}
|
296 |
+
|
297 |
+
$s3Funcs->cTableParams['page'] = $page;
|
298 |
+
if ($s3Funcs->cTableParams['page'] >= $s3Funcs->cTableParams['pages']) {
|
299 |
+
DUPX_Log::info('ENGINE EXIT PAGE:'.DUPX_Log::varToString($table).' PAGES:'.$s3Funcs->cTableParams['pages'], DUPX_Log::LV_DEBUG);
|
300 |
+
return false;
|
301 |
+
}
|
302 |
+
|
303 |
+
self::evaluatePagedRows($s3Funcs->cTableParams);
|
304 |
+
}
|
305 |
+
|
306 |
+
public static function initTableParams($table)
|
307 |
+
{
|
308 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
309 |
+
if (is_null($s3Funcs->cTableParams) || $s3Funcs->cTableParams['table'] !== $table) {
|
310 |
+
DUPX_Log::info('ENGINE INIT TABLE PARAMS '.DUPX_Log::varToString($table), DUPX_Log::LV_DETAILED);
|
311 |
+
$s3Funcs->report['scan_tables'] ++;
|
312 |
+
|
313 |
+
if (($s3Funcs->cTableParams = self::getTableRowsParams($table)) === null) {
|
314 |
+
DUPX_Log::info('ENGINE TABLE PARAMS EMPTY', DUPX_Log::LV_DEBUG);
|
315 |
+
return false;
|
316 |
}
|
317 |
}
|
318 |
|
319 |
+
return true;
|
320 |
+
}
|
321 |
+
|
322 |
+
/**
|
323 |
+
* evaluate rows with pagination
|
324 |
+
*
|
325 |
+
* @param array $rowsParams
|
326 |
+
*
|
327 |
+
* @return boolean // if true table is modified and updated
|
328 |
+
*/
|
329 |
+
private static function evaluatePagedRows(&$rowsParams)
|
330 |
+
{
|
331 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
332 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
333 |
+
$dbh = $s3Funcs->getDbConnection();
|
334 |
+
$start = $rowsParams['page'] * $rowsParams['page_size'];
|
335 |
+
$end = $start + $rowsParams['page_size'] - 1;
|
336 |
+
|
337 |
+
$sql = sprintf("SELECT {$rowsParams['colList']} FROM `%s` LIMIT %d, %d", $rowsParams['table'], $start, $rowsParams['page_size']);
|
338 |
+
$data = DUPX_DB::mysqli_query($dbh, $sql, __FILE__, __LINE__);
|
339 |
+
|
340 |
+
$scan_count = min($rowsParams['row_count'], $end);
|
341 |
+
if (DUPX_Log::isLevel(DUPX_Log::LV_DETAILED)) {
|
342 |
+
DUPX_Log::info('ENGINE EV TABLE '.str_pad(DUPX_Log::varToString($rowsParams['table']), 50, '_', STR_PAD_RIGHT).
|
343 |
+
'[PAGE:'.str_pad($rowsParams['page'], 4, " ", STR_PAD_LEFT).']'.
|
344 |
+
'[START:'.str_pad($start, 6, " ", STR_PAD_LEFT).']'.
|
345 |
+
'[OF:'.str_pad($scan_count, 6, " ", STR_PAD_LEFT).']', DUPX_Log::LV_DETAILED);
|
346 |
+
}
|
347 |
+
|
348 |
+
if (!$data) {
|
349 |
+
$errMsg = mysqli_error($dbh);
|
350 |
+
$s3Funcs->report['errsql'][] = $errMsg;
|
351 |
+
$nManager->addFinalReportNotice(array(
|
352 |
+
'shortMsg' => 'DATA-REPLACE ERRORS: MySQL',
|
353 |
+
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
354 |
+
'longMsg' => $errMsg,
|
355 |
+
'sections' => 'search_replace'
|
356 |
+
));
|
357 |
+
}
|
358 |
|
359 |
+
//Loops every row
|
360 |
+
while ($row = mysqli_fetch_assoc($data)) {
|
361 |
+
self::evaluateRow($rowsParams, $row);
|
362 |
+
}
|
363 |
|
364 |
+
//DUPX_U::fcgiFlush();
|
365 |
+
@mysqli_free_result($data);
|
|
|
|
|
|
|
|
|
366 |
|
367 |
+
return $rowsParams['updated'];
|
368 |
}
|
369 |
|
370 |
/**
|
371 |
+
* evaluate single row columns
|
|
|
372 |
*
|
373 |
+
* @param array $rowsParams
|
374 |
+
* @param array $row
|
|
|
|
|
375 |
*
|
376 |
+
* @return boolean true if row is modified and updated
|
377 |
*/
|
378 |
+
private static function evaluateRow(&$rowsParams, $row)
|
379 |
{
|
380 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
381 |
+
$s3Funcs = DUPX_S3_Funcs::getInstance();
|
382 |
+
$dbh = $s3Funcs->getDbConnection();
|
383 |
+
$maxSerializeLenCheck = $s3Funcs->getPost('maxSerializeStrlen');
|
384 |
+
|
385 |
+
$s3Funcs->report['scan_rows'] ++;
|
386 |
+
$rowsParams['current_row'] ++;
|
387 |
+
|
388 |
+
$upd_col = array();
|
389 |
+
$upd_sql = array();
|
390 |
+
$where_sql = array();
|
391 |
+
$upd = false;
|
392 |
+
$serial_err = 0;
|
393 |
+
$is_unkeyed = !in_array(true, $rowsParams['columns']);
|
394 |
+
|
395 |
+
$rowErrors = array();
|
396 |
+
|
397 |
+
|
398 |
+
//Loops every cell
|
399 |
+
foreach ($rowsParams['columns'] as $column => $primary_key) {
|
400 |
+
$s3Funcs->report['scan_cells'] ++;
|
401 |
+
if (!isset($row[$column])) {
|
402 |
+
continue;
|
403 |
+
}
|
404 |
+
|
405 |
+
$safe_column = '`'.mysqli_real_escape_string($dbh, $column).'`';
|
406 |
+
$edited_data = $data_to_fix = $row[$column];
|
407 |
+
$base64converted = false;
|
408 |
+
$txt_found = false;
|
409 |
+
|
410 |
+
//Unkeyed table code
|
411 |
+
//Added this here to add all columns to $where_sql
|
412 |
+
//The if statement with $txt_found would skip additional columns -TG
|
413 |
+
if ($is_unkeyed && !empty($data_to_fix)) {
|
414 |
+
$where_sql[] = $safe_column.' = "'.mysqli_real_escape_string($dbh, $data_to_fix).'"';
|
415 |
+
}
|
416 |
+
|
417 |
+
//Only replacing string values
|
418 |
+
if (!empty($row[$column]) && !is_numeric($row[$column]) && $primary_key != 1) {
|
419 |
+
// get search and reaplace list for column
|
420 |
+
$tColList = &$rowsParams['columnsSRList'][$column]['list'];
|
421 |
+
$tColSearchList = &$rowsParams['columnsSRList'][$column]['sList'];
|
422 |
+
$tColreplaceList = &$rowsParams['columnsSRList'][$column]['rList'];
|
423 |
+
$tColExactMatch = $rowsParams['columnsSRList'][$column]['exactMatch'];
|
424 |
+
|
425 |
+
// skip empty search col
|
426 |
+
if (empty($tColSearchList)) {
|
427 |
+
continue;
|
428 |
}
|
429 |
+
|
430 |
+
// Search strings in data
|
431 |
+
foreach ($tColList as $item) {
|
432 |
+
if (strpos($edited_data, $item['search']) !== false) {
|
433 |
+
$txt_found = true;
|
434 |
+
break;
|
|
|
435 |
}
|
436 |
}
|
437 |
|
438 |
+
if (!$txt_found) {
|
439 |
+
//if not found decetc Base 64
|
440 |
+
if (($decoded = DUPX_U::is_base64($row[$column])) !== false) {
|
441 |
+
$edited_data = $decoded;
|
442 |
+
$base64converted = true;
|
443 |
+
|
444 |
+
// Search strings in data decoded
|
445 |
+
foreach ($tColList as $item) {
|
446 |
+
if (strpos($edited_data, $item['search']) !== false) {
|
447 |
+
$txt_found = true;
|
448 |
+
break;
|
449 |
+
}
|
|
|
|
|
|
|
|
|
450 |
}
|
451 |
}
|
452 |
+
|
453 |
+
//Skip table cell if match not found
|
454 |
+
if (!$txt_found) {
|
455 |
+
continue;
|
456 |
+
}
|
457 |
+
}
|
458 |
+
|
459 |
+
// 0 no limit
|
460 |
+
if ($maxSerializeLenCheck > 0 && self::is_serialized_string($edited_data) && strlen($edited_data) > $maxSerializeLenCheck) {
|
461 |
+
$serial_err ++;
|
462 |
+
$trimLen = DUPX_Log::isLevel(DUPX_Log::LV_HARD_DEBUG) ? 10000 : 200;
|
463 |
+
$rowErrors[$column] = 'ENGINE: serialize data too big to convert; data len:'.strlen($edited_data).' Max size:'.$maxSerializeLenCheck;
|
464 |
+
$rowErrors[$column] .= "\n\tDATA: ".mb_strimwidth($edited_data, 0, $trimLen, ' [...]');
|
465 |
+
} else {
|
466 |
+
//Replace logic - level 1: simple check on any string or serlized strings
|
467 |
+
if ($tColExactMatch) {
|
468 |
+
// if is exact match search and replace the itentical string
|
469 |
+
if (($rIndex = array_search($edited_data, $tColSearchList)) !== false) {
|
470 |
+
DUPX_Log::info("ColExactMatch ".$column.' search:'.$edited_data.' replace:'.$tColreplaceList[$rIndex].' index:'.$rIndex, DUPX_Log::LV_DEBUG);
|
471 |
+
$edited_data = $tColreplaceList[$rIndex];
|
472 |
+
}
|
473 |
+
} else {
|
474 |
+
// search if column contain search list
|
475 |
+
$edited_data = self::searchAndReplaceItems($tColSearchList, $tColreplaceList, $edited_data);
|
476 |
+
|
477 |
+
//Replace logic - level 2: repair serialized strings that have become broken
|
478 |
+
// check value without unserialize it
|
479 |
+
if (self::is_serialized_string($edited_data)) {
|
480 |
+
$serial_check = self::fixSerialString($edited_data);
|
481 |
+
if ($serial_check['fixed']) {
|
482 |
+
$edited_data = $serial_check['data'];
|
483 |
+
} elseif ($serial_check['tried'] && !$serial_check['fixed']) {
|
484 |
+
$serial_err ++;
|
485 |
+
$trimLen = DUPX_Log::isLevel(DUPX_Log::LV_HARD_DEBUG) ? 10000 : 200;
|
486 |
+
$rowErrors[$column] = 'ENGINE: serialize data serial check error';
|
487 |
+
$rowErrors[$column] .= "\n\tDATA: ".mb_strimwidth($edited_data, 0, $trimLen, ' [...]');
|
488 |
}
|
489 |
}
|
490 |
}
|
491 |
}
|
492 |
+
}
|
493 |
+
|
494 |
+
//Change was made
|
495 |
+
if ($serial_err > 0 || $edited_data != $data_to_fix) {
|
496 |
+
$s3Funcs->report['updt_cells'] ++;
|
497 |
+
//Base 64 encode
|
498 |
+
if ($base64converted) {
|
499 |
+
$edited_data = base64_encode($edited_data);
|
500 |
+
}
|
501 |
+
$upd_col[] = $safe_column;
|
502 |
+
$upd_sql[] = $safe_column.' = "'.mysqli_real_escape_string($dbh, $edited_data).'"';
|
503 |
+
$upd = true;
|
504 |
+
}
|
505 |
+
|
506 |
+
if ($primary_key) {
|
507 |
+
$where_sql[] = $safe_column.' = "'.mysqli_real_escape_string($dbh, $data_to_fix).'"';
|
508 |
+
}
|
509 |
+
}
|
510 |
+
|
511 |
+
//PERFORM ROW UPDATE
|
512 |
+
if ($upd && !empty($where_sql)) {
|
513 |
+
$sql = "UPDATE `{$rowsParams['table']}` SET ".implode(', ', $upd_sql).' WHERE '.implode(' AND ', array_filter($where_sql));
|
514 |
+
$result = DUPX_DB::mysqli_query($dbh, $sql, __FILE__, __LINE__);
|
515 |
+
|
516 |
+
if ($result) {
|
517 |
+
foreach ($rowErrors as $errCol => $msgCol) {
|
518 |
+
$longMsg = $msgCol."\n\tTABLE:".$rowsParams['table'].' COLUMN: '.$errCol.' WHERE: '.implode(' AND ', array_filter($where_sql));
|
519 |
+
$s3Funcs->report['errser'][] = $longMsg;
|
520 |
+
|
521 |
+
$nManager->addFinalReportNotice(array(
|
522 |
+
'shortMsg' => 'DATA-REPLACE ERROR: Serialization',
|
523 |
+
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
524 |
+
'longMsg' => $longMsg,
|
525 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE,
|
526 |
+
'sections' => 'search_replace'
|
527 |
+
));
|
528 |
+
}
|
529 |
+
$s3Funcs->report['updt_rows'] ++;
|
530 |
+
$rowsParams['updated'] = true;
|
531 |
+
} else {
|
532 |
+
$errMsg = mysqli_error($dbh)."\n\tTABLE:".$rowsParams['table'].' COLUMN: '.$errCol.' WHERE: '.implode(' AND ', array_filter($where_sql));
|
533 |
+
$s3Funcs->report['errsql'][] = ($GLOBALS['LOGGING'] == 1) ? 'DB ERROR: '.$errMsg : 'DB ERROR: '.$errMsg."\nSQL: [{$sql}]\n";
|
534 |
+
$nManager->addFinalReportNotice(array(
|
535 |
+
'shortMsg' => 'DATA-REPLACE ERRORS: MySQL',
|
536 |
+
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
537 |
+
'longMsg' => $errMsg,
|
538 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE,
|
539 |
+
'sections' => 'search_replace'
|
540 |
+
));
|
541 |
+
}
|
542 |
+
} elseif ($upd) {
|
543 |
+
$errMsg = sprintf("Row [%s] on Table [%s] requires a manual update.", $rowsParams['current_row'], $rowsParams['table']);
|
544 |
+
$s3Funcs->report['errkey'][] = $errMsg;
|
545 |
+
|
546 |
+
$nManager->addFinalReportNotice(array(
|
547 |
+
'shortMsg' => 'DATA-REPLACE ERROR: Key',
|
548 |
+
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
549 |
+
'longMsg' => $errMsg,
|
550 |
+
'sections' => 'search_replace'
|
551 |
+
));
|
552 |
+
}
|
553 |
+
|
554 |
+
return $rowsParams['updated'];
|
555 |
+
}
|
556 |
+
|
557 |
+
private static function getColumnsSearchReplaceList($table, $columns)
|
558 |
+
{
|
559 |
+
// PREPARE SEARCH AN REPLACE LISF FOR TABLES
|
560 |
+
$srManager = DUPX_S_R_MANAGER::getInstance();
|
561 |
+
$searchList = array();
|
562 |
+
$replaceList = array();
|
563 |
+
$list = $srManager->getSearchReplaceList($table);
|
564 |
+
foreach ($list as $item) {
|
565 |
+
$searchList[] = $item['search'];
|
566 |
+
$replaceList[] = $item['replace'];
|
567 |
+
}
|
568 |
+
|
569 |
+
$columnsSRList = array();
|
570 |
+
foreach ($columns as $column => $primary_key) {
|
571 |
+
if (($cScope = self::getSearchReplaceCustomScope($table, $column)) === false) {
|
572 |
+
// if don't have custom scope get normal search and reaplce table list
|
573 |
+
$columnsSRList[$column] = array(
|
574 |
+
'list' => &$list,
|
575 |
+
'sList' => &$searchList,
|
576 |
+
'rList' => &$replaceList,
|
577 |
+
'exactMatch' => false
|
578 |
+
);
|
579 |
} else {
|
580 |
+
// if column have custom scope overvrite default table search/replace list
|
581 |
+
$columnsSRList[$column] = array(
|
582 |
+
'list' => $srManager->getSearchReplaceList($cScope, true, false),
|
583 |
+
'sList' => array(),
|
584 |
+
'rList' => array(),
|
585 |
+
'exactMatch' => self::isExactMatch($table, $column)
|
586 |
+
);
|
587 |
+
foreach ($columnsSRList[$column]['list'] as $item) {
|
588 |
+
$columnsSRList[$column]['sList'][] = $item['search'];
|
589 |
+
$columnsSRList[$column]['rList'][] = $item['replace'];
|
590 |
}
|
591 |
}
|
592 |
+
}
|
593 |
+
|
594 |
+
return $columnsSRList;
|
595 |
+
}
|
596 |
+
|
597 |
+
/**
|
598 |
+
* searches and replaces strings without deserializing
|
599 |
+
* recursion for arrays
|
600 |
+
*
|
601 |
+
* @param array $search
|
602 |
+
* @param array $replace
|
603 |
+
* @param mixed $data
|
604 |
+
*
|
605 |
+
* @return mixed
|
606 |
+
*/
|
607 |
+
public static function searchAndReplaceItems($search, $replace, $data)
|
608 |
+
{
|
609 |
+
|
610 |
+
if (empty($data) || is_numeric($data) || is_bool($data) || is_callable($data)) {
|
611 |
+
|
612 |
+
/* do nothing */
|
613 |
+
} else if (is_string($data)) {
|
614 |
+
|
615 |
+
// Multiple replace string. If the string is serialized will fixed with fixSerialString
|
616 |
+
$data = str_replace($search, $replace, $data);
|
617 |
+
} else if (is_array($data)) {
|
618 |
|
619 |
+
$_tmp = array();
|
620 |
+
foreach ($data as $key => $value) {
|
621 |
+
|
622 |
+
// prevent recursion overhead
|
623 |
+
if (empty($value) || is_numeric($value) || is_bool($value) || is_callable($value) || is_object($data)) {
|
624 |
+
|
625 |
+
$_tmp[$key] = $value;
|
626 |
+
} else {
|
627 |
+
|
628 |
+
$_tmp[$key] = self::searchAndReplaceItems($search, $replace, $value, false);
|
629 |
+
}
|
630 |
}
|
631 |
+
|
632 |
+
$data = $_tmp;
|
633 |
+
unset($_tmp);
|
634 |
+
} elseif (is_object($data)) {
|
635 |
+
// it can never be an object type
|
636 |
+
DUPX_Log::info("OBJECT DATA IMPOSSIBLE\n");
|
637 |
}
|
638 |
+
|
639 |
return $data;
|
640 |
}
|
641 |
|
642 |
+
/**
|
643 |
+
* FROM WORDPRESS
|
644 |
+
* Check value to find if it was serialized.
|
645 |
+
*
|
646 |
+
* If $data is not an string, then returned value will always be false.
|
647 |
+
* Serialized data is always a string.
|
648 |
+
*
|
649 |
+
* @since 2.0.5
|
650 |
+
*
|
651 |
+
* @param string $data Value to check to see if was serialized.
|
652 |
+
* @param bool $strict Optional. Whether to be strict about the end of the string. Default true.
|
653 |
+
* @return bool False if not serialized and true if it was.
|
654 |
+
*/
|
655 |
+
public static function is_serialized_string($data, $strict = true)
|
656 |
+
{
|
657 |
+
// if it isn't a string, it isn't serialized.
|
658 |
+
if (!is_string($data)) {
|
659 |
+
return false;
|
660 |
+
}
|
661 |
+
$data = trim($data);
|
662 |
+
if ('N;' == $data) {
|
663 |
+
return true;
|
664 |
+
}
|
665 |
+
if (strlen($data) < 4) {
|
666 |
+
return false;
|
667 |
+
}
|
668 |
+
if (':' !== $data[1]) {
|
669 |
+
return false;
|
670 |
+
}
|
671 |
+
if ($strict) {
|
672 |
+
$lastc = substr($data, -1);
|
673 |
+
if (';' !== $lastc && '}' !== $lastc) {
|
674 |
+
return false;
|
675 |
+
}
|
676 |
+
} else {
|
677 |
+
$semicolon = strpos($data, ';');
|
678 |
+
$brace = strpos($data, '}');
|
679 |
+
// Either ; or } must exist.
|
680 |
+
if (false === $semicolon && false === $brace) {
|
681 |
+
return false;
|
682 |
+
}
|
683 |
+
// But neither must be in the first X characters.
|
684 |
+
if (false !== $semicolon && $semicolon < 3) {
|
685 |
+
return false;
|
686 |
+
}
|
687 |
+
if (false !== $brace && $brace < 4) {
|
688 |
+
return false;
|
689 |
+
}
|
690 |
+
}
|
691 |
+
$token = $data[0];
|
692 |
+
switch ($token) {
|
693 |
+
case 's' :
|
694 |
+
if ($strict) {
|
695 |
+
if ('"' !== substr($data, -2, 1)) {
|
696 |
+
return false;
|
697 |
+
}
|
698 |
+
} elseif (false === strpos($data, '"')) {
|
699 |
+
return false;
|
700 |
+
}
|
701 |
+
// or else fall through
|
702 |
+
case 'a' :
|
703 |
+
case 'O' :
|
704 |
+
return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
|
705 |
+
case 'b' :
|
706 |
+
case 'i' :
|
707 |
+
case 'd' :
|
708 |
+
$end = $strict ? '$' : '';
|
709 |
+
return (bool) preg_match("/^{$token}:[0-9.E-]+;$end/", $data);
|
710 |
+
}
|
711 |
+
return false;
|
712 |
+
}
|
713 |
+
|
714 |
/**
|
715 |
* Test if a string in properly serialized
|
716 |
*
|
718 |
*
|
719 |
* @return bool Is the string a serialized string
|
720 |
*/
|
721 |
+
public static function unserializeTest($data)
|
722 |
{
|
723 |
if (!is_string($data)) {
|
724 |
return false;
|
727 |
} else {
|
728 |
try {
|
729 |
DUPX_Handler::setMode(DUPX_Handler::MODE_OFF);
|
730 |
+
$unserialize_ret = @unserialize($data);
|
731 |
DUPX_Handler::setMode();
|
732 |
+
return ($unserialize_ret !== false);
|
733 |
} catch (Exception $e) {
|
734 |
DUPX_Log::info("Unserialize exception: ".$e->getMessage());
|
735 |
//DEBUG ONLY:
|
738 |
}
|
739 |
}
|
740 |
}
|
741 |
+
/**
|
742 |
+
* custom columns list
|
743 |
+
* if the table / column pair exists in this array then the search scope will be overwritten with that contained in the array
|
744 |
+
*
|
745 |
+
* @var array
|
746 |
+
*/
|
747 |
+
private static $customScopes = array(
|
748 |
+
'signups' => array(
|
749 |
+
'domain' => array(
|
750 |
+
'scope' => 'domain_host',
|
751 |
+
'exact' => true
|
752 |
+
),
|
753 |
+
'path' => array(
|
754 |
+
'scope' => 'domain_path',
|
755 |
+
'exact' => true
|
756 |
+
)
|
757 |
+
),
|
758 |
+
'site' => array(
|
759 |
+
'domain' => array(
|
760 |
+
'scope' => 'domain_host',
|
761 |
+
'exact' => true
|
762 |
+
),
|
763 |
+
'path' => array(
|
764 |
+
'scope' => 'domain_path',
|
765 |
+
'exact' => true
|
766 |
+
)
|
767 |
+
)
|
768 |
+
);
|
769 |
+
|
770 |
+
/**
|
771 |
+
*
|
772 |
+
* @param string $table
|
773 |
+
* @param string $column
|
774 |
+
* @return boolean|string false if custom scope not found or return custom scoper for table/column
|
775 |
+
*/
|
776 |
+
private static function getSearchReplaceCustomScope($table, $column)
|
777 |
+
{
|
778 |
+
if (strpos($table, $GLOBALS['DUPX_AC']->wp_tableprefix) !== 0) {
|
779 |
+
return false;
|
780 |
+
}
|
781 |
+
|
782 |
+
$table_key = substr($table, strlen($GLOBALS['DUPX_AC']->wp_tableprefix));
|
783 |
+
|
784 |
+
if (!array_key_exists($table_key, self::$customScopes)) {
|
785 |
+
return false;
|
786 |
+
}
|
787 |
+
|
788 |
+
if (!array_key_exists($column, self::$customScopes[$table_key])) {
|
789 |
+
return false;
|
790 |
+
}
|
791 |
+
|
792 |
+
return self::$customScopes[$table_key][$column]['scope'];
|
793 |
+
}
|
794 |
+
|
795 |
+
/**
|
796 |
+
*
|
797 |
+
* @param string $table
|
798 |
+
* @param string $column
|
799 |
+
* @return boolean if true search a exact match in column if false search as LIKE
|
800 |
+
*/
|
801 |
+
private static function isExactMatch($table, $column)
|
802 |
+
{
|
803 |
+
if (strpos($table, $GLOBALS['DUPX_AC']->wp_tableprefix) !== 0) {
|
804 |
+
return false;
|
805 |
+
}
|
806 |
+
|
807 |
+
$table_key = substr($table, strlen($GLOBALS['DUPX_AC']->wp_tableprefix));
|
808 |
+
|
809 |
+
if (!array_key_exists($table_key, self::$customScopes)) {
|
810 |
+
return false;
|
811 |
+
}
|
812 |
+
|
813 |
+
if (!array_key_exists($column, self::$customScopes[$table_key])) {
|
814 |
+
return false;
|
815 |
+
}
|
816 |
+
|
817 |
+
return self::$customScopes[$table_key][$column]['exact'];
|
818 |
+
}
|
819 |
|
820 |
/**
|
821 |
* Fixes the string length of a string object that has been serialized but the length is broken
|
827 |
public static function fixSerialString($data)
|
828 |
{
|
829 |
$result = array('data' => $data, 'fixed' => false, 'tried' => false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
830 |
|
831 |
+
// check if serialized string must be fixed
|
832 |
+
if (!self::unserializeTest($data)) {
|
833 |
+
|
834 |
+
$serialized_fixed = self::recursiveFixSerialString($data);
|
835 |
+
|
836 |
+
if (self::unserializeTest($serialized_fixed)) {
|
837 |
+
|
838 |
+
$result['data'] = $serialized_fixed;
|
839 |
+
|
840 |
+
$result['fixed'] = true;
|
841 |
}
|
842 |
+
|
843 |
+
$result['tried'] = true;
|
844 |
}
|
845 |
+
|
846 |
return $result;
|
847 |
}
|
848 |
|
849 |
/**
|
850 |
+
* Fixes the string length of a string object that has been serialized but the length is broken
|
851 |
+
* Work on nested serialized string recursively.
|
852 |
+
*
|
853 |
+
* @param string $data The string ojbect to recalculate the size on.
|
854 |
+
*
|
855 |
+
* @return string A serialized string that fixes and string length types
|
856 |
*/
|
857 |
+
public static function recursiveFixSerialString($data)
|
858 |
{
|
859 |
+
|
860 |
+
if (!self::is_serialized_string($data)) {
|
861 |
+
return $data;
|
862 |
+
}
|
863 |
+
|
864 |
+
$result = '';
|
865 |
+
|
866 |
+
$matches = null;
|
867 |
+
|
868 |
+
$openLevel = 0;
|
869 |
+
$openContent = '';
|
870 |
+
$openContentL2 = '';
|
871 |
+
|
872 |
+
// parse every char
|
873 |
+
for ($i = 0; $i < strlen($data); $i++) {
|
874 |
+
|
875 |
+
$cChar = $data[$i];
|
876 |
+
|
877 |
+
$addChar = true;
|
878 |
+
|
879 |
+
if ($cChar == 's') {
|
880 |
+
|
881 |
+
// test if is a open string
|
882 |
+
if (preg_match('/^(s:\d+:")/', substr($data, $i), $matches)) {
|
883 |
+
|
884 |
+
$addChar = false;
|
885 |
+
|
886 |
+
$openLevel ++;
|
887 |
+
|
888 |
+
$i += strlen($matches[0]) - 1;
|
889 |
+
}
|
890 |
+
} else if ($openLevel > 0 && $cChar == '"') {
|
891 |
+
|
892 |
+
// test if is a close string
|
893 |
+
if (preg_match('/^";(?:}|a:|s:|S:|b:|d:|i:|o:|O:|C:|r:|R:|N;)/', substr($data, $i))) {
|
894 |
+
|
895 |
+
$addChar = false;
|
896 |
+
|
897 |
+
switch ($openLevel) {
|
898 |
+
case 1:
|
899 |
+
// level 1
|
900 |
+
// flush string content
|
901 |
+
$result .= 's:'.strlen($openContent).':"'.$openContent.'";';
|
902 |
+
|
903 |
+
$openContent = '';
|
904 |
+
|
905 |
+
break;
|
906 |
+
case 2;
|
907 |
+
// level 2
|
908 |
+
// fix serial string level2
|
909 |
+
$sublevelstr = self::recursiveFixSerialString($openContentL2);
|
910 |
+
|
911 |
+
// flush content on level 1
|
912 |
+
$openContent .= 's:'.strlen($sublevelstr).':"'.$sublevelstr.'";';
|
913 |
+
|
914 |
+
$openContentL2 = '';
|
915 |
+
|
916 |
+
break;
|
917 |
+
default:
|
918 |
+
// level > 2
|
919 |
+
// keep writing at level 2; it will be corrected with recursion
|
920 |
+
break;
|
921 |
+
}
|
922 |
+
|
923 |
+
$openLevel --;
|
924 |
+
|
925 |
+
$closeString = '";';
|
926 |
+
|
927 |
+
$i += strlen($closeString) - 1;
|
928 |
+
}
|
929 |
+
}
|
930 |
+
|
931 |
+
|
932 |
+
if ($addChar) {
|
933 |
+
|
934 |
+
switch ($openLevel) {
|
935 |
+
case 0:
|
936 |
+
// level 0
|
937 |
+
// add char on result
|
938 |
+
$result .= $cChar;
|
939 |
+
|
940 |
+
break;
|
941 |
+
case 1:
|
942 |
+
// level 1
|
943 |
+
// add char on content level1
|
944 |
+
$openContent .= $cChar;
|
945 |
+
|
946 |
+
break;
|
947 |
+
default:
|
948 |
+
// level > 1
|
949 |
+
// add char on content level2
|
950 |
+
$openContentL2 .= $cChar;
|
951 |
+
|
952 |
+
break;
|
953 |
+
}
|
954 |
+
}
|
955 |
+
}
|
956 |
+
|
957 |
+
return $result;
|
958 |
}
|
959 |
}
|
installer/dup-installer/classes/class.http.php
CHANGED
@@ -43,7 +43,13 @@ class DUPX_HTTP
|
|
43 |
$isSecure = true;
|
44 |
}
|
45 |
$protocol = $isSecure ? 'https' : 'http';
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
$url = ($show_query) ? $url : preg_replace('/\?.*/', '', $url);
|
48 |
return $url;
|
49 |
}
|
43 |
$isSecure = true;
|
44 |
}
|
45 |
$protocol = $isSecure ? 'https' : 'http';
|
46 |
+
// for ngrok url and Local by Flywheel Live URL
|
47 |
+
if (isset($_SERVER['HTTP_X_ORIGINAL_HOST'])) {
|
48 |
+
$host = $_SERVER['HTTP_X_ORIGINAL_HOST'];
|
49 |
+
} else {
|
50 |
+
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];//WAS SERVER_NAME and caused problems on some boxes
|
51 |
+
}
|
52 |
+
$url = "{$protocol}://{$host}{$_SERVER['REQUEST_URI']}";
|
53 |
$url = ($show_query) ? $url : preg_replace('/\?.*/', '', $url);
|
54 |
return $url;
|
55 |
}
|
installer/dup-installer/classes/class.s3.func.php
ADDED
@@ -0,0 +1,1319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class used to update and edit web server configuration files
|
4 |
+
* for .htaccess, web.config and user.ini
|
5 |
+
*
|
6 |
+
* Standard: PSR-2
|
7 |
+
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
8 |
+
*
|
9 |
+
* @package SC\DUPX\Crypt
|
10 |
+
*
|
11 |
+
*/
|
12 |
+
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Step 3 functions
|
16 |
+
* Singlethon
|
17 |
+
*/
|
18 |
+
final class DUPX_S3_Funcs
|
19 |
+
{
|
20 |
+
const MODE_NORMAL = 1;
|
21 |
+
// const MODE_CHUNK = 2; reserved for PRO version
|
22 |
+
const MODE_SKIP = 3; // not implemented yet
|
23 |
+
|
24 |
+
/**
|
25 |
+
*
|
26 |
+
* @var DUPX_S3_Funcs
|
27 |
+
*/
|
28 |
+
protected static $instance = null;
|
29 |
+
|
30 |
+
/**
|
31 |
+
*
|
32 |
+
* @var array
|
33 |
+
*/
|
34 |
+
public $post = null;
|
35 |
+
|
36 |
+
/**
|
37 |
+
*
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
public $cTableParams = null;
|
41 |
+
|
42 |
+
/**
|
43 |
+
*
|
44 |
+
* @var array
|
45 |
+
*/
|
46 |
+
public $report = array();
|
47 |
+
|
48 |
+
/**
|
49 |
+
*
|
50 |
+
* @var int
|
51 |
+
*/
|
52 |
+
private $timeStart = null;
|
53 |
+
|
54 |
+
/**
|
55 |
+
*
|
56 |
+
* @var database connection
|
57 |
+
*/
|
58 |
+
private $dbh = null;
|
59 |
+
|
60 |
+
/**
|
61 |
+
*
|
62 |
+
* @var bool
|
63 |
+
*/
|
64 |
+
private $fullReport = false;
|
65 |
+
|
66 |
+
private function __construct()
|
67 |
+
{
|
68 |
+
$this->timeStart = DUPX_U::getMicrotime();
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
*
|
73 |
+
* @return self
|
74 |
+
*/
|
75 |
+
public static function getInstance()
|
76 |
+
{
|
77 |
+
if (is_null(self::$instance)) {
|
78 |
+
self::$instance = new self;
|
79 |
+
}
|
80 |
+
return self::$instance;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* inizialize 3sFunc data
|
85 |
+
*/
|
86 |
+
public function initData()
|
87 |
+
{
|
88 |
+
DUPX_Log::info('INIT S3 DATA', 2);
|
89 |
+
// else init data from $_POST
|
90 |
+
$this->setPostData();
|
91 |
+
$this->setReplaceList();
|
92 |
+
$this->initReport();
|
93 |
+
$this->copyOriginalConfigFiles();
|
94 |
+
}
|
95 |
+
|
96 |
+
private function initReport()
|
97 |
+
{
|
98 |
+
$this->report = self::getInitReport();
|
99 |
+
}
|
100 |
+
|
101 |
+
public static function getInitReport()
|
102 |
+
{
|
103 |
+
return array(
|
104 |
+
'pass' => 0,
|
105 |
+
'chunk' => 0,
|
106 |
+
'chunkPos' => array(),
|
107 |
+
'progress_perc' => 0,
|
108 |
+
'scan_tables' => 0,
|
109 |
+
'scan_rows' => 0,
|
110 |
+
'scan_cells' => 0,
|
111 |
+
'updt_tables' => 0,
|
112 |
+
'updt_rows' => 0,
|
113 |
+
'updt_cells' => 0,
|
114 |
+
'errsql' => array(),
|
115 |
+
'errser' => array(),
|
116 |
+
'errkey' => array(),
|
117 |
+
'errsql_sum' => 0,
|
118 |
+
'errser_sum' => 0,
|
119 |
+
'errkey_sum' => 0,
|
120 |
+
'profile_start' => '',
|
121 |
+
'profile_end' => '',
|
122 |
+
'time' => '',
|
123 |
+
'err_all' => 0,
|
124 |
+
'warn_all' => 0,
|
125 |
+
'warnlist' => array()
|
126 |
+
);
|
127 |
+
}
|
128 |
+
|
129 |
+
public function getJsonReport()
|
130 |
+
{
|
131 |
+
$this->report['warn_all'] = empty($this->report['warnlist']) ? 0 : count($this->report['warnlist']);
|
132 |
+
|
133 |
+
if ($this->fullReport) {
|
134 |
+
return array(
|
135 |
+
'step1' => json_decode(urldecode($this->post['json'])),
|
136 |
+
'step3' => $this->report
|
137 |
+
);
|
138 |
+
} else {
|
139 |
+
return array(
|
140 |
+
'step3' => $this->report
|
141 |
+
);
|
142 |
+
}
|
143 |
+
}
|
144 |
+
|
145 |
+
private static function logSectionHeader($title, $func, $line)
|
146 |
+
{
|
147 |
+
$log = "\n".'===================================='."\n".
|
148 |
+
$title;
|
149 |
+
if ($GLOBALS["LOGGING"] > 1) {
|
150 |
+
$log .= ' [FUNC: '.$func.' L:'.$line.']';
|
151 |
+
}
|
152 |
+
$log .= "\n".
|
153 |
+
'====================================';
|
154 |
+
DUPX_Log::info($log);
|
155 |
+
}
|
156 |
+
|
157 |
+
private function setPostData()
|
158 |
+
{
|
159 |
+
// POST PARAMS
|
160 |
+
// SEARCH AND SEPLACE SETTINGS
|
161 |
+
$this->post = array();
|
162 |
+
|
163 |
+
$this->post['blogname'] = isset($_POST['blogname']) ? htmlspecialchars($_POST['blogname'], ENT_QUOTES) : 'No Blog Title Set';
|
164 |
+
$this->post['postguid'] = filter_input(INPUT_POST, 'postguid', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
|
165 |
+
$this->post['fullsearch'] = filter_input(INPUT_POST, 'fullsearch', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
|
166 |
+
|
167 |
+
$this->post['path_old'] = DUPX_U::isset_sanitize($_POST, 'path_old', array('default' => null, 'trim' => true));
|
168 |
+
$this->post['path_new'] = DUPX_U::isset_sanitize($_POST, 'path_new', array('default' => null, 'trim' => true));
|
169 |
+
|
170 |
+
$this->post['siteurl'] = DUPX_U::isset_sanitize($_POST, 'siteurl', array('default' => null, 'trim' => true));
|
171 |
+
if (!is_null($this->post['siteurl'])) {
|
172 |
+
$this->post['siteurl'] = rtrim($this->post['siteurl'], '/');
|
173 |
+
}
|
174 |
+
|
175 |
+
$this->post['url_old'] = DUPX_U::isset_sanitize($_POST, 'url_old', array('default' => null, 'trim' => true));
|
176 |
+
if (!is_null($this->post['url_old'])) {
|
177 |
+
$this->post['siteurl'] = rtrim($this->post['url_old'], '/');
|
178 |
+
}
|
179 |
+
|
180 |
+
$this->post['url_new'] = DUPX_U::isset_sanitize($_POST, 'url_new', array('default' => null, 'trim' => true));
|
181 |
+
if (!is_null($this->post['url_new'])) {
|
182 |
+
$this->post['siteurl'] = rtrim($this->post['url_new'], '/');
|
183 |
+
}
|
184 |
+
|
185 |
+
$this->post['tables'] = isset($_POST['tables']) && is_array($_POST['tables']) ? array_map('DUPX_U::sanitize_text_field', $_POST['tables']) : array();
|
186 |
+
$this->post['maxSerializeStrlen'] = filter_input(INPUT_POST, DUPX_CTRL::NAME_MAX_SERIALIZE_STRLEN_IN_M, FILTER_VALIDATE_INT,
|
187 |
+
array("options" => array('default' => DUPX_Constants::DEFAULT_MAX_STRLEN_SERIALIZED_CHECK_IN_M, 'min_range' => 0))) * 1000000;
|
188 |
+
$this->post['replaceMail'] = filter_input(INPUT_POST, 'search_replace_email_domain', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
|
189 |
+
|
190 |
+
// DATABASE CONNECTION
|
191 |
+
$this->post['dbhost'] = trim(filter_input(INPUT_POST, 'dbhost', FILTER_DEFAULT, array('options' => array('default' => ''))));
|
192 |
+
$this->post['dbuser'] = trim(filter_input(INPUT_POST, 'dbuser', FILTER_DEFAULT, array('options' => array('default' => ''))));
|
193 |
+
$this->post['dbname'] = trim(filter_input(INPUT_POST, 'dbname', FILTER_DEFAULT, array('options' => array('default' => ''))));
|
194 |
+
$this->post['dbpass'] = trim(filter_input(INPUT_POST, 'dbpass', FILTER_DEFAULT, array('options' => array('default' => ''))));
|
195 |
+
$this->post['dbcharset'] = DUPX_U::isset_sanitize($_POST, 'dbcharset', array('default' => ''));
|
196 |
+
$this->post['dbcollate'] = DUPX_U::isset_sanitize($_POST, 'dbcollate', array('default' => ''));
|
197 |
+
|
198 |
+
// NEW ADMIN USER
|
199 |
+
$this->post['wp_username'] = DUPX_U::isset_sanitize($_POST, 'wp_username', array('default' => '', 'trim' => true));
|
200 |
+
$this->post['wp_password'] = DUPX_U::isset_sanitize($_POST, 'wp_password', array('default' => '', 'trim' => true));
|
201 |
+
$this->post['wp_mail'] = DUPX_U::isset_sanitize($_POST, 'wp_mail', array('default' => '', 'trim' => true));
|
202 |
+
$this->post['wp_nickname'] = DUPX_U::isset_sanitize($_POST, 'wp_nickname', array('default' => '', 'trim' => true));
|
203 |
+
$this->post['wp_first_name'] = DUPX_U::isset_sanitize($_POST, 'wp_first_name', array('default' => '', 'trim' => true));
|
204 |
+
$this->post['wp_last_name'] = DUPX_U::isset_sanitize($_POST, 'wp_last_name', array('default' => '', 'trim' => true));
|
205 |
+
|
206 |
+
// WP CONFIG SETTINGS
|
207 |
+
$this->post['ssl_admin'] = filter_input(INPUT_POST, 'ssl_admin', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
|
208 |
+
$this->post['cache_wp'] = filter_input(INPUT_POST, 'cache_wp', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
|
209 |
+
$this->post['cache_path'] = filter_input(INPUT_POST, 'cache_path', FILTER_VALIDATE_BOOLEAN, array('options' => array('default' => false)));
|
210 |
+
|
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()
|
218 |
+
),
|
219 |
+
'flags' => FILTER_REQUIRE_ARRAY,
|
220 |
+
));
|
221 |
+
|
222 |
+
$this->post['json'] = filter_input(INPUT_POST, 'json', FILTER_DEFAULT, array('options' => array('default' => '{}')));
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* get vaule post if thepost isn't inizialized inizialize it
|
227 |
+
*
|
228 |
+
* @param string $key
|
229 |
+
* @return mixed
|
230 |
+
*/
|
231 |
+
public function getPost($key = null)
|
232 |
+
{
|
233 |
+
if (is_null($this->post)) {
|
234 |
+
$this->initData();
|
235 |
+
}
|
236 |
+
|
237 |
+
if (is_null($key)) {
|
238 |
+
return $this->post;
|
239 |
+
} else if (isset($this->post[$key])) {
|
240 |
+
return $this->post[$key];
|
241 |
+
} else {
|
242 |
+
return null;
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
/**
|
247 |
+
* add table in tables list to scan in search and replace engine if isn't already in array
|
248 |
+
*
|
249 |
+
* @param string $table
|
250 |
+
*/
|
251 |
+
public function addTable($table)
|
252 |
+
{
|
253 |
+
if (empty($table)) {
|
254 |
+
return;
|
255 |
+
}
|
256 |
+
|
257 |
+
// make sure post data is inizialized
|
258 |
+
$this->getPost();
|
259 |
+
if (!in_array($table, $this->post['tables'])) {
|
260 |
+
$this->post['tables'][] = $table;
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* open db connection if is closed
|
266 |
+
*/
|
267 |
+
private function dbConnection()
|
268 |
+
{
|
269 |
+
if (is_null($this->dbh)) {
|
270 |
+
// make sure post data is inizialized
|
271 |
+
$this->getPost();
|
272 |
+
|
273 |
+
//MYSQL CONNECTION
|
274 |
+
$this->dbh = DUPX_DB::connect($this->post['dbhost'], $this->post['dbuser'], $this->post['dbpass'], $this->post['dbname']);
|
275 |
+
$dbConnError = (mysqli_connect_error()) ? 'Error: '.mysqli_connect_error() : 'Unable to Connect';
|
276 |
+
|
277 |
+
if (!$this->dbh) {
|
278 |
+
$msg = "Unable to connect with the following parameters: <br/> <b>HOST:</b> {$post_db_host}<br/> <b>DATABASE:</b> {$post_db_name}<br/>";
|
279 |
+
$msg .= "<b>Connection Error:</b> {$dbConnError}";
|
280 |
+
DUPX_Log::error($msg);
|
281 |
+
}
|
282 |
+
|
283 |
+
$db_max_time = mysqli_real_escape_string($this->dbh, $GLOBALS['DB_MAX_TIME']);
|
284 |
+
@mysqli_query($this->dbh, "SET wait_timeout = ".mysqli_real_escape_string($this->dbh, $db_max_time));
|
285 |
+
|
286 |
+
$post_db_charset = $this->post['dbcharset'];
|
287 |
+
$post_db_collate = $this->post['dbcollate'];
|
288 |
+
DUPX_DB::setCharset($this->dbh, $post_db_charset, $post_db_collate);
|
289 |
+
}
|
290 |
+
}
|
291 |
+
|
292 |
+
public function getDbConnection()
|
293 |
+
{
|
294 |
+
// make sure dbConnection is inizialized
|
295 |
+
$this->dbConnection();
|
296 |
+
return $this->dbh;
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* close db connection if is open
|
301 |
+
*/
|
302 |
+
public function closeDbConnection()
|
303 |
+
{
|
304 |
+
if (!is_null($this->dbh)) {
|
305 |
+
mysqli_close($this->dbh);
|
306 |
+
$this->dbh = null;
|
307 |
+
}
|
308 |
+
}
|
309 |
+
|
310 |
+
public function initLog()
|
311 |
+
{
|
312 |
+
// make sure dbConnection is inizialized
|
313 |
+
$this->dbConnection();
|
314 |
+
|
315 |
+
$charsetServer = @mysqli_character_set_name($this->dbh);
|
316 |
+
$charsetClient = @mysqli_character_set_name($this->dbh);
|
317 |
+
|
318 |
+
//LOGGING
|
319 |
+
$date = @date('h:i:s');
|
320 |
+
$log = "\n\n".
|
321 |
+
"********************************************************************************\n".
|
322 |
+
"DUPLICATOR PRO INSTALL-LOG\n".
|
323 |
+
"STEP-3 START @ ".$date."\n".
|
324 |
+
"NOTICE: Do NOT post to public sites or forums\n".
|
325 |
+
"********************************************************************************\n".
|
326 |
+
"CHARSET SERVER:\t".DUPX_Log::varToString($charsetServer)."\n".
|
327 |
+
"CHARSET CLIENT:\t".DUPX_Log::varToString($charsetClient)."\n".
|
328 |
+
"********************************************************************************\n".
|
329 |
+
"OPTIONS:\n";
|
330 |
+
|
331 |
+
$skipOpts = array('tables', 'plugins', 'dbpass', 'json', 'search', 'replace', 'mu_search', 'mu_replace', 'wp_password');
|
332 |
+
foreach ($this->post as $key => $val) {
|
333 |
+
if (in_array($key, $skipOpts)) {
|
334 |
+
continue;
|
335 |
+
}
|
336 |
+
$log .= str_pad($key, 22, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($val)."\n";
|
337 |
+
}
|
338 |
+
$log .= "********************************************************************************\n";
|
339 |
+
|
340 |
+
DUPX_Log::info($log);
|
341 |
+
|
342 |
+
$POST_LOG = $this->post;
|
343 |
+
unset($POST_LOG['tables']);
|
344 |
+
unset($POST_LOG['plugins']);
|
345 |
+
unset($POST_LOG['dbpass']);
|
346 |
+
ksort($POST_LOG);
|
347 |
+
|
348 |
+
//Detailed logging
|
349 |
+
$log = "--------------------------------------\n";
|
350 |
+
$log .= "POST DATA\n";
|
351 |
+
$log .= "--------------------------------------\n";
|
352 |
+
$log .= print_r($POST_LOG, true);
|
353 |
+
DUPX_Log::info($log, DUPX_Log::LV_DEBUG);
|
354 |
+
|
355 |
+
$log = "--------------------------------------\n";
|
356 |
+
$log .= "TABLES TO SCAN\n";
|
357 |
+
$log .= "--------------------------------------\n";
|
358 |
+
$log .= (isset($this->post['tables']) && count($this->post['tables']) > 0) ? DUPX_Log::varToString($this->post['tables']) : 'No tables selected to update';
|
359 |
+
$log .= "--------------------------------------\n";
|
360 |
+
$log .= "KEEP PLUGINS ACTIVE\n";
|
361 |
+
$log .= "--------------------------------------\n";
|
362 |
+
$log .= (isset($this->post['plugins']) && count($this->post['plugins']) > 0) ? DUPX_Log::varToString($this->post['plugins']) : 'No plugins selected for activation';
|
363 |
+
DUPX_Log::info($log, 2);
|
364 |
+
DUPX_Log::flush();
|
365 |
+
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
*
|
369 |
+
* @staticvar type $configTransformer
|
370 |
+
*
|
371 |
+
* @return WPConfigTransformer
|
372 |
+
*/
|
373 |
+
public function getWpConfigTransformer()
|
374 |
+
{
|
375 |
+
static $configTransformer = null;
|
376 |
+
|
377 |
+
if (is_null($configTransformer)) {
|
378 |
+
//@todo: integrate all logic into DUPX_WPConfig::updateVars
|
379 |
+
if (is_writable($this->getWpconfigArkPath())) {
|
380 |
+
$configTransformer = new WPConfigTransformer($this->getWpconfigArkPath());
|
381 |
+
} else {
|
382 |
+
$err_log = "\nWARNING: Unable to update file permissions and write to dup-wp-config-arc__[HASH].txt. ";
|
383 |
+
$err_log .= "Check that the wp-config.php is in the archive.zip and check with your host or administrator to enable PHP to write to the wp-config.php file. ";
|
384 |
+
$err_log .= "If performing a 'Manual Extraction' please be sure to select the 'Manual Archive Extraction' option on step 1 under options.";
|
385 |
+
chmod($this->getWpconfigArkPath(), 0644) ? DUPX_Log::info("File Permission Update: dup-wp-config-arc__[HASH].txt set to 0644") : DUPX_Log::error("{$err_log}");
|
386 |
+
}
|
387 |
+
}
|
388 |
+
|
389 |
+
return $configTransformer;
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
*
|
394 |
+
* @staticvar string $path
|
395 |
+
* @return string
|
396 |
+
*/
|
397 |
+
public function getWpconfigArkPath()
|
398 |
+
{
|
399 |
+
static $path = null;
|
400 |
+
if (is_null($path)) {
|
401 |
+
$path = $GLOBALS['DUPX_AC']->installSiteOverwriteOn ? $GLOBALS['DUPX_ROOT'].'/dup-wp-config-arc__'.$GLOBALS['DUPX_AC']->package_hash.'.txt' : $GLOBALS['DUPX_ROOT'].'/wp-config.php';
|
402 |
+
}
|
403 |
+
return $path;
|
404 |
+
}
|
405 |
+
|
406 |
+
/**
|
407 |
+
*
|
408 |
+
* @staticvar string $path
|
409 |
+
* @return string
|
410 |
+
*/
|
411 |
+
public function getHtaccessArkPath()
|
412 |
+
{
|
413 |
+
static $path = null;
|
414 |
+
if (is_null($path)) {
|
415 |
+
$path = $GLOBALS['DUPX_ROOT'].'/htaccess.orig';
|
416 |
+
}
|
417 |
+
return $path;
|
418 |
+
}
|
419 |
+
|
420 |
+
/**
|
421 |
+
*
|
422 |
+
* @staticvar string $path
|
423 |
+
* @return string
|
424 |
+
*/
|
425 |
+
public function getOrigWpConfigPath()
|
426 |
+
{
|
427 |
+
static $path = null;
|
428 |
+
if (is_null($path)) {
|
429 |
+
$path = $GLOBALS['DUPX_INIT'].'/dup-orig-wp-config__'.$GLOBALS['DUPX_AC']->package_hash.'.txt';
|
430 |
+
}
|
431 |
+
return $path;
|
432 |
+
}
|
433 |
+
|
434 |
+
/**
|
435 |
+
*
|
436 |
+
* @staticvar string $path
|
437 |
+
* @return string
|
438 |
+
*/
|
439 |
+
public function getOrigHtaccessPath()
|
440 |
+
{
|
441 |
+
static $path = null;
|
442 |
+
if (is_null($path)) {
|
443 |
+
$path = $GLOBALS['DUPX_INIT'].'/dup-orig-wp-config__'.$GLOBALS['DUPX_AC']->package_hash.'.txt';
|
444 |
+
}
|
445 |
+
return $GLOBALS['DUPX_INIT'].'/dup-orig-htaccess__'.$GLOBALS['DUPX_AC']->package_hash.'.txt';
|
446 |
+
}
|
447 |
+
|
448 |
+
/**
|
449 |
+
*
|
450 |
+
* @return string
|
451 |
+
*/
|
452 |
+
public function copyOriginalConfigFiles()
|
453 |
+
{
|
454 |
+
$wpOrigPath = $this->getOrigWpConfigPath();
|
455 |
+
$wpArkPath = $this->getWpconfigArkPath();
|
456 |
+
|
457 |
+
if (file_exists($wpOrigPath)) {
|
458 |
+
if (!@unlink($wpOrigPath)) {
|
459 |
+
DUPX_Log::info('Can\'t delete copy of WP Config orig file');
|
460 |
+
}
|
461 |
+
}
|
462 |
+
|
463 |
+
if (!file_exists($wpArkPath)) {
|
464 |
+
DUPX_Log::info('WP Config ark file don\' exists');
|
465 |
+
}
|
466 |
+
|
467 |
+
if (!@copy($wpArkPath, $wpOrigPath)) {
|
468 |
+
$errors = error_get_last();
|
469 |
+
DUPX_Log::info("COPY ERROR: ".$errors['type']."\n".$errors['message']);
|
470 |
+
} else {
|
471 |
+
echo DUPX_Log::info("Original WP Config file copied", 2);
|
472 |
+
}
|
473 |
+
|
474 |
+
$htOrigPath = $this->getOrigHtaccessPath();
|
475 |
+
$htArkPath = $this->getHtaccessArkPath();
|
476 |
+
|
477 |
+
if (file_exists($htOrigPath)) {
|
478 |
+
if (!@unlink($htOrigPath)) {
|
479 |
+
DUPX_Log::info('Can\'t delete copy of htaccess orig file');
|
480 |
+
}
|
481 |
+
}
|
482 |
+
|
483 |
+
if (!file_exists($htArkPath)) {
|
484 |
+
DUPX_Log::info('htaccess ark file don\' exists');
|
485 |
+
}
|
486 |
+
|
487 |
+
if (!@copy($htArkPath, $htOrigPath)) {
|
488 |
+
$errors = error_get_last();
|
489 |
+
DUPX_Log::info("COPY ERROR: ".$errors['type']."\n".$errors['message']);
|
490 |
+
} else {
|
491 |
+
echo DUPX_Log::info("htaccess file copied", 2);
|
492 |
+
}
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* set replace list
|
497 |
+
*
|
498 |
+
* Auto inizialize function
|
499 |
+
*/
|
500 |
+
public function setReplaceList()
|
501 |
+
{
|
502 |
+
self::logSectionHeader('SET SEARCH AND REPLACE LIST', __FUNCTION__, __LINE__);
|
503 |
+
$this->setGlobalSearchAndReplaceList();
|
504 |
+
}
|
505 |
+
|
506 |
+
/**
|
507 |
+
*
|
508 |
+
* @return int MODE_NORAML
|
509 |
+
*/
|
510 |
+
public function getEngineMode()
|
511 |
+
{
|
512 |
+
return self::MODE_NORMAL;
|
513 |
+
}
|
514 |
+
|
515 |
+
private function setGlobalSearchAndReplaceList()
|
516 |
+
{
|
517 |
+
$s_r_manager = DUPX_S_R_MANAGER::getInstance();
|
518 |
+
|
519 |
+
// make sure dbConnection is inizialized
|
520 |
+
$this->dbConnection();
|
521 |
+
|
522 |
+
// DIRS PATHS
|
523 |
+
$post_path_old = $this->post['path_old'];
|
524 |
+
$post_path_new = $this->post['path_new'];
|
525 |
+
$s_r_manager->addItem($post_path_old, $post_path_new, DUPX_S_R_ITEM::TYPE_PATH, 10);
|
526 |
+
|
527 |
+
// URLS
|
528 |
+
// url from _POST
|
529 |
+
$old_urls_list = array($this->post['url_old']);
|
530 |
+
$post_url_new = $this->post['url_new'];
|
531 |
+
$at_new_domain = '@'.DUPX_U::getDomain($post_url_new);
|
532 |
+
|
533 |
+
try {
|
534 |
+
$confTransformer = $this->getWpConfigTransformer();
|
535 |
+
|
536 |
+
// urls from wp-config
|
537 |
+
if (!is_null($confTransformer)) {
|
538 |
+
if ($confTransformer->exists('constant', 'WP_HOME')) {
|
539 |
+
$old_urls_list[] = $confTransformer->get_value('constant', 'WP_HOME');
|
540 |
+
}
|
541 |
+
|
542 |
+
if ($confTransformer->exists('constant', 'WP_SITEURL')) {
|
543 |
+
$old_urls_list[] = $confTransformer->get_value('constant', 'WP_SITEURL');
|
544 |
+
}
|
545 |
+
}
|
546 |
+
|
547 |
+
// urls from db
|
548 |
+
$dbUrls = mysqli_query($this->dbh, 'SELECT * FROM `'.mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix).'options` where option_name IN (\'siteurl\',\'home\')');
|
549 |
+
if ($dbUrls instanceof mysqli_result) {
|
550 |
+
while ($row = $dbUrls->fetch_object()) {
|
551 |
+
$old_urls_list[] = $row->option_value;
|
552 |
+
}
|
553 |
+
} else {
|
554 |
+
DUPX_Log::info('DB ERROR: '.mysqli_error($this->dbh));
|
555 |
+
}
|
556 |
+
} catch (Exception $e) {
|
557 |
+
DUPX_Log::info('CONTINUE EXCEPTION: '.$e->getMessage());
|
558 |
+
DUPX_Log::info('TRACE:');
|
559 |
+
DUPX_Log::info($e->getTraceAsString());
|
560 |
+
}
|
561 |
+
|
562 |
+
foreach (array_unique($old_urls_list) as $old_url) {
|
563 |
+
$s_r_manager->addItem($old_url, $post_url_new, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, 10);
|
564 |
+
|
565 |
+
// Replace email address (xyz@oldomain.com to xyz@newdomain.com).
|
566 |
+
if ($this->post['replaceMail']) {
|
567 |
+
$at_old_domain = '@'.DUPX_U::getDomain($old_url);
|
568 |
+
$s_r_manager->addItem($at_old_domain, $at_new_domain, DUPX_S_R_ITEM::TYPE_STRING, 20);
|
569 |
+
}
|
570 |
+
}
|
571 |
+
}
|
572 |
+
|
573 |
+
public function runSearchAndReplace()
|
574 |
+
{
|
575 |
+
self::logSectionHeader('RUN SEARCH AND REPLACE', __FUNCTION__, __LINE__);
|
576 |
+
|
577 |
+
// make sure post data is inizialized
|
578 |
+
$this->getPost();
|
579 |
+
|
580 |
+
DUPX_UpdateEngine::load($this->post['tables']);
|
581 |
+
DUPX_UpdateEngine::logStats();
|
582 |
+
DUPX_UpdateEngine::logErrors();
|
583 |
+
}
|
584 |
+
|
585 |
+
public function removeMaincenanceMode()
|
586 |
+
{
|
587 |
+
self::logSectionHeader('REMOVE MAINTENANCE MODE', __FUNCTION__, __LINE__);
|
588 |
+
// make sure post data is inizialized
|
589 |
+
$this->getPost();
|
590 |
+
|
591 |
+
|
592 |
+
if (isset($this->post['remove_redundant']) && $this->post['remove_redundant']) {
|
593 |
+
if ($GLOBALS['DUPX_STATE']->mode == DUPX_InstallerMode::OverwriteInstall) {
|
594 |
+
DUPX_U::maintenanceMode(false, $GLOBALS['DUPX_ROOT']);
|
595 |
+
}
|
596 |
+
}
|
597 |
+
}
|
598 |
+
|
599 |
+
public function removeLicenseKey()
|
600 |
+
{
|
601 |
+
self::logSectionHeader('REMOVE LICENSE KEY', __FUNCTION__, __LINE__);
|
602 |
+
// make sure dbConnection is inizialized
|
603 |
+
$this->dbConnection();
|
604 |
+
|
605 |
+
if (isset($GLOBALS['DUPX_AC']->brand) && isset($GLOBALS['DUPX_AC']->brand->enabled) && $GLOBALS['DUPX_AC']->brand->enabled) {
|
606 |
+
$license_check = mysqli_query($this->dbh,
|
607 |
+
"SELECT COUNT(1) AS count FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE `option_name` LIKE 'duplicator_pro_license_key' ");
|
608 |
+
$license_row = mysqli_fetch_row($license_check);
|
609 |
+
$license_count = is_null($license_row) ? 0 : $license_row[0];
|
610 |
+
if ($license_count > 0) {
|
611 |
+
mysqli_query($this->dbh,
|
612 |
+
"UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET `option_value` = '' WHERE `option_name` LIKE 'duplicator_pro_license_key'");
|
613 |
+
}
|
614 |
+
}
|
615 |
+
}
|
616 |
+
|
617 |
+
public function createNewAdminUser()
|
618 |
+
{
|
619 |
+
self::logSectionHeader('CREATE NEW ADMIN USER', __FUNCTION__, __LINE__);
|
620 |
+
// make sure dbConnection is inizialized
|
621 |
+
$this->dbConnection();
|
622 |
+
|
623 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
624 |
+
|
625 |
+
if (strlen($this->post['wp_username']) >= 4 && strlen($this->post['wp_password']) >= 6) {
|
626 |
+
$wp_username = mysqli_real_escape_string($this->dbh, $this->post['wp_username']);
|
627 |
+
$newuser_check = mysqli_query($this->dbh,
|
628 |
+
"SELECT COUNT(*) AS count FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."users` WHERE user_login = '{$wp_username}' ");
|
629 |
+
$newuser_row = mysqli_fetch_row($newuser_check);
|
630 |
+
$newuser_count = is_null($newuser_row) ? 0 : $newuser_row[0];
|
631 |
+
|
632 |
+
if ($newuser_count == 0) {
|
633 |
+
|
634 |
+
$newuser_datetime = @date("Y-m-d H:i:s");
|
635 |
+
$newuser_datetime = mysqli_real_escape_string($this->dbh, $newuser_datetime);
|
636 |
+
$newuser_security = mysqli_real_escape_string($this->dbh, 'a:1:{s:13:"administrator";b:1;}');
|
637 |
+
|
638 |
+
$post_wp_username = $this->post['wp_username'];
|
639 |
+
$post_wp_password = $this->post['wp_password'];
|
640 |
+
|
641 |
+
$post_wp_mail = $this->post['wp_mail'];
|
642 |
+
$post_wp_nickname = $this->post['wp_nickname'];
|
643 |
+
if (empty($post_wp_nickname)) {
|
644 |
+
$post_wp_nickname = $post_wp_username;
|
645 |
+
}
|
646 |
+
$post_wp_first_name = $this->post['wp_first_name'];
|
647 |
+
$post_wp_last_name = $this->post['wp_last_name'];
|
648 |
+
|
649 |
+
$wp_username = mysqli_real_escape_string($this->dbh, $post_wp_username);
|
650 |
+
$wp_password = mysqli_real_escape_string($this->dbh, $post_wp_password);
|
651 |
+
$wp_mail = mysqli_real_escape_string($this->dbh, $post_wp_mail);
|
652 |
+
$wp_nickname = mysqli_real_escape_string($this->dbh, $post_wp_nickname);
|
653 |
+
$wp_first_name = mysqli_real_escape_string($this->dbh, $post_wp_first_name);
|
654 |
+
$wp_last_name = mysqli_real_escape_string($this->dbh, $post_wp_last_name);
|
655 |
+
|
656 |
+
$newuser1 = @mysqli_query($this->dbh,
|
657 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."users`
|
658 |
+
(`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_registered`, `user_activation_key`, `user_status`, `display_name`)
|
659 |
+
VALUES ('{$wp_username}', MD5('{$wp_password}'), '{$wp_username}', '{$wp_mail}', '{$newuser_datetime}', '', '0', '{$wp_username}')");
|
660 |
+
|
661 |
+
$newuser1_insert_id = intval(mysqli_insert_id($this->dbh));
|
662 |
+
|
663 |
+
$newuser2 = @mysqli_query($this->dbh,
|
664 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta`
|
665 |
+
(`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', '".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."capabilities', '{$newuser_security}')");
|
666 |
+
|
667 |
+
$newuser3 = @mysqli_query($this->dbh,
|
668 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta`
|
669 |
+
(`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', '".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."user_level', '10')");
|
670 |
+
|
671 |
+
//Misc Meta-Data Settings:
|
672 |
+
@mysqli_query($this->dbh,
|
673 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'rich_editing', 'true')");
|
674 |
+
@mysqli_query($this->dbh,
|
675 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'admin_color', 'fresh')");
|
676 |
+
@mysqli_query($this->dbh,
|
677 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'nickname', '{$wp_nickname}')");
|
678 |
+
@mysqli_query($this->dbh,
|
679 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'first_name', '{$wp_first_name}')");
|
680 |
+
@mysqli_query($this->dbh,
|
681 |
+
"INSERT INTO `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'last_name', '{$wp_last_name}')");
|
682 |
+
|
683 |
+
DUPX_Log::info("\nNEW WP-ADMIN USER:");
|
684 |
+
if ($newuser1 && $newuser2 && $newuser3) {
|
685 |
+
DUPX_Log::info("- New username '{$this->post['wp_username']}' was created successfully allong with MU usermeta.");
|
686 |
+
} elseif ($newuser1) {
|
687 |
+
DUPX_Log::info("- New username '{$this->post['wp_username']}' was created successfully.");
|
688 |
+
} else {
|
689 |
+
$newuser_warnmsg = "- Failed to create the user '{$this->post['wp_username']}' \n ";
|
690 |
+
$this->report['warnlist'][] = $newuser_warnmsg;
|
691 |
+
|
692 |
+
$nManager->addFinalReportNotice(array(
|
693 |
+
'shortMsg' => 'New admin user create error',
|
694 |
+
'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
|
695 |
+
'longMsg' => $newuser_warnmsg,
|
696 |
+
'sections' => 'general'
|
697 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'new-user-create-error');
|
698 |
+
|
699 |
+
DUPX_Log::info($newuser_warnmsg);
|
700 |
+
}
|
701 |
+
} else {
|
702 |
+
$newuser_warnmsg = "\nNEW WP-ADMIN USER:\n - Username '{$this->post['wp_username']}' already exists in the database. Unable to create new account.\n";
|
703 |
+
$this->report['warnlist'][] = $newuser_warnmsg;
|
704 |
+
|
705 |
+
$nManager->addFinalReportNotice(array(
|
706 |
+
'shortMsg' => 'New admin user create error',
|
707 |
+
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
708 |
+
'longMsg' => $newuser_warnmsg,
|
709 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE,
|
710 |
+
'sections' => 'general'
|
711 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'new-user-create-error');
|
712 |
+
|
713 |
+
DUPX_Log::info($newuser_warnmsg);
|
714 |
+
}
|
715 |
+
}
|
716 |
+
}
|
717 |
+
|
718 |
+
public function configurationFileUpdate()
|
719 |
+
{
|
720 |
+
self::logSectionHeader('CONFIGURATION FILE UPDATES', __FUNCTION__, __LINE__);
|
721 |
+
DUPX_Log::incIndent();
|
722 |
+
// make sure post data is inizialized
|
723 |
+
$this->getPost();
|
724 |
+
$strReplaced = 0;
|
725 |
+
|
726 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
727 |
+
try {
|
728 |
+
if (file_exists($this->getWpconfigArkPath())) {
|
729 |
+
$confTransformer = $this->getWpConfigTransformer();
|
730 |
+
|
731 |
+
$mu_newDomain = parse_url($this->getPost('url_new'));
|
732 |
+
$mu_oldDomain = parse_url($this->getPost('url_old'));
|
733 |
+
$mu_newDomainHost = $mu_newDomain['host'];
|
734 |
+
$mu_oldDomainHost = $mu_oldDomain['host'];
|
735 |
+
$mu_newUrlPath = parse_url($this->getPost('url_new'), PHP_URL_PATH);
|
736 |
+
$mu_oldUrlPath = parse_url($this->getPost('url_old'), PHP_URL_PATH);
|
737 |
+
|
738 |
+
if (empty($mu_newUrlPath) || ($mu_newUrlPath == '/')) {
|
739 |
+
$mu_newUrlPath = '/';
|
740 |
+
} else {
|
741 |
+
$mu_newUrlPath = rtrim($mu_newUrlPath, '/').'/';
|
742 |
+
}
|
743 |
+
|
744 |
+
if (empty($mu_oldUrlPath) || ($mu_oldUrlPath == '/')) {
|
745 |
+
$mu_oldUrlPath = '/';
|
746 |
+
} else {
|
747 |
+
$mu_oldUrlPath = rtrim($mu_oldUrlPath, '/').'/';
|
748 |
+
}
|
749 |
+
|
750 |
+
if ($confTransformer->exists('constant', 'WP_HOME')) {
|
751 |
+
$confTransformer->update('constant', 'WP_HOME', $this->post['url_new'], array('normalize' => true, 'add' => false));
|
752 |
+
DUPX_Log::info('UPDATE WP_HOME '.DUPX_Log::varToString($this->post['url_new']));
|
753 |
+
}
|
754 |
+
if ($confTransformer->exists('constant', 'WP_SITEURL')) {
|
755 |
+
$confTransformer->update('constant', 'WP_SITEURL', $this->post['url_new'], array('normalize' => true, 'add' => false));
|
756 |
+
DUPX_Log::info('UPDATE WP_SITEURL '.DUPX_Log::varToString($this->post['url_new']));
|
757 |
+
}
|
758 |
+
if ($confTransformer->exists('constant', 'DOMAIN_CURRENT_SITE')) {
|
759 |
+
$confTransformer->update('constant', 'DOMAIN_CURRENT_SITE', $mu_newDomainHost, array('normalize' => true, 'add' => false));
|
760 |
+
DUPX_Log::info('UPDATE DOMAIN_CURRENT_SITE '.DUPX_Log::varToString($mu_newDomainHost));
|
761 |
+
}
|
762 |
+
if ($confTransformer->exists('constant', 'PATH_CURRENT_SITE')) {
|
763 |
+
$confTransformer->update('constant', 'PATH_CURRENT_SITE', $mu_newUrlPath, array('normalize' => true, 'add' => false));
|
764 |
+
DUPX_Log::info('UPDATE PATH_CURRENT_SITE '.DUPX_Log::varToString($mu_newUrlPath));
|
765 |
+
}
|
766 |
+
|
767 |
+
/**
|
768 |
+
* clean multisite settings for security reasons.
|
769 |
+
*/
|
770 |
+
if ($confTransformer->exists('constant', 'WP_ALLOW_MULTISITE')) {
|
771 |
+
$confTransformer->remove('constant', 'WP_ALLOW_MULTISITE');
|
772 |
+
DUPX_Log::info('REMOVED WP_ALLOW_MULTISITE');
|
773 |
+
}
|
774 |
+
if ($confTransformer->exists('constant', 'ALLOW_MULTISITE')) {
|
775 |
+
$confTransformer->update('constant', 'ALLOW_MULTISITE', 'false', array('add' => false, 'raw' => true, 'normalize' => true));
|
776 |
+
DUPX_Log::info('TRANSFORMER: ALLOW_MULTISITE constant value set to false in WP config file');
|
777 |
+
}
|
778 |
+
if ($confTransformer->exists('constant', 'MULTISITE')) {
|
779 |
+
$confTransformer->update('constant', 'MULTISITE', 'false', array('add' => false, 'raw' => true, 'normalize' => true));
|
780 |
+
DUPX_Log::info('TRANSFORMER: MULTISITE constant value set to false in WP config file');
|
781 |
+
}
|
782 |
+
if ($confTransformer->exists('constant', 'NOBLOGREDIRECT')) {
|
783 |
+
$confTransformer->update('constant', 'NOBLOGREDIRECT', 'false', array('add' => false, 'raw' => true, 'normalize' => true));
|
784 |
+
DUPX_Log::info('TRANSFORMER: NOBLOGREDIRECT constant value set to false in WP config file');
|
785 |
+
}
|
786 |
+
if ($confTransformer->exists('constant', 'SUBDOMAIN_INSTALL')) {
|
787 |
+
$confTransformer->remove('constant', 'SUBDOMAIN_INSTALL');
|
788 |
+
DUPX_Log::info('TRANSFORMER: SUBDOMAIN_INSTALL constant removed from WP config file');
|
789 |
+
}
|
790 |
+
if ($confTransformer->exists('constant', 'VHOST')) {
|
791 |
+
$confTransformer->remove('constant', 'VHOST');
|
792 |
+
DUPX_Log::info('TRANSFORMER: VHOST constant removed from WP config file');
|
793 |
+
}
|
794 |
+
if ($confTransformer->exists('constant', 'SUNRISE')) {
|
795 |
+
$confTransformer->remove('constant', 'SUNRISE');
|
796 |
+
DUPX_Log::info('TRANSFORMER: SUNRISE constant removed from WP config file');
|
797 |
+
}
|
798 |
+
|
799 |
+
|
800 |
+
$dbname = DUPX_U::getEscapedGenericString($this->post['dbname']);
|
801 |
+
$dbuser = DUPX_U::getEscapedGenericString($this->post['dbuser']);
|
802 |
+
$dbpass = DUPX_U::getEscapedGenericString($this->post['dbpass']);
|
803 |
+
$dbhost = DUPX_U::getEscapedGenericString($this->post['dbhost']);
|
804 |
+
|
805 |
+
$confTransformer->update('constant', 'DB_NAME', $dbname, array('raw' => true));
|
806 |
+
DUPX_Log::info('UPDATE DB_NAME '.DUPX_Log::varToString($dbname));
|
807 |
+
|
808 |
+
$confTransformer->update('constant', 'DB_USER', $dbuser, array('raw' => true));
|
809 |
+
DUPX_Log::info('UPDATE DB_USER '.DUPX_Log::varToString($dbuser));
|
810 |
+
|
811 |
+
$confTransformer->update('constant', 'DB_PASSWORD', $dbpass, array('raw' => true));
|
812 |
+
DUPX_Log::info('UPDATE DB_PASSWORD '.DUPX_Log::varToString('** OBSCURED **'));
|
813 |
+
|
814 |
+
$confTransformer->update('constant', 'DB_HOST', $dbhost, array('raw' => true));
|
815 |
+
DUPX_Log::info('UPDATE DB_HOST '.DUPX_Log::varToString($dbhost));
|
816 |
+
|
817 |
+
//SSL CHECKS
|
818 |
+
if ($this->post['ssl_admin']) {
|
819 |
+
$confTransformer->update('constant', 'FORCE_SSL_ADMIN', 'true', array('raw' => true, 'normalize' => true));
|
820 |
+
DUPX_Log::info('UPDATE FORCE_SSL_ADMIN '.DUPX_Log::varToString(true));
|
821 |
+
} else {
|
822 |
+
if ($confTransformer->exists('constant', 'FORCE_SSL_ADMIN')) {
|
823 |
+
$confTransformer->update('constant', 'FORCE_SSL_ADMIN', 'false', array('raw' => true, 'add' => false, 'normalize' => true));
|
824 |
+
DUPX_Log::info('UPDATE FORCE_SSL_ADMIN '.DUPX_Log::varToString(false));
|
825 |
+
}
|
826 |
+
}
|
827 |
+
|
828 |
+
// COOKIE_DOMAIN
|
829 |
+
if ($confTransformer->exists('constant', 'COOKIE_DOMAIN')) {
|
830 |
+
$const_val = $confTransformer->get_value('constant', 'COOKIE_DOMAIN');
|
831 |
+
$const_new_val = str_replace($mu_oldDomainHost, $mu_newDomainHost, $const_val, $strReplaced);
|
832 |
+
if ($strReplaced > 0) {
|
833 |
+
$confTransformer->update('constant', 'COOKIE_DOMAIN', $const_new_val, array('normalize' => true));
|
834 |
+
}
|
835 |
+
}
|
836 |
+
|
837 |
+
if ($this->post['cache_wp']) {
|
838 |
+
$confTransformer->update('constant', 'WP_CACHE', 'true', array('raw' => true, 'normalize' => true));
|
839 |
+
DUPX_Log::info('UPDATE WP_CACHE '.DUPX_Log::varToString(true));
|
840 |
+
} else {
|
841 |
+
if ($confTransformer->exists('constant', 'WP_CACHE')) {
|
842 |
+
$confTransformer->update('constant', 'WP_CACHE', 'false', array('raw' => true, 'add' => false, 'normalize' => true));
|
843 |
+
DUPX_Log::info('UPDATE WP_CACHE '.DUPX_Log::varToString(false));
|
844 |
+
}
|
845 |
+
}
|
846 |
+
|
847 |
+
// Cache: [ ] Keep Home Path
|
848 |
+
if ($this->post['cache_path']) {
|
849 |
+
if ($confTransformer->exists('constant', 'WPCACHEHOME')) {
|
850 |
+
$wpcachehome_const_val = $confTransformer->get_value('constant', 'WPCACHEHOME');
|
851 |
+
$wpcachehome_const_val = DUPX_U::wp_normalize_path($wpcachehome_const_val);
|
852 |
+
$wpcachehome_new_const_val = str_replace($this->post['path_old'], $this->post['path_new'], $wpcachehome_const_val, $strReplaced);
|
853 |
+
if ($strReplaced > 0) {
|
854 |
+
$confTransformer->update('constant', 'WPCACHEHOME', $wpcachehome_new_const_val, array('normalize' => true));
|
855 |
+
DUPX_Log::info('UPDATE WPCACHEHOME '.DUPX_Log::varToString($wpcachehome_new_const_val));
|
856 |
+
}
|
857 |
+
}
|
858 |
+
} else {
|
859 |
+
$confTransformer->remove('constant', 'WPCACHEHOME');
|
860 |
+
DUPX_Log::info('REMOVE WPCACHEHOME');
|
861 |
+
}
|
862 |
+
|
863 |
+
if ($GLOBALS['DUPX_AC']->is_outer_root_wp_content_dir) {
|
864 |
+
if (empty($GLOBALS['DUPX_AC']->wp_content_dir_base_name)) {
|
865 |
+
$ret = $confTransformer->remove('constant', 'WP_CONTENT_DIR');
|
866 |
+
DUPX_Log::info('REMOVE WP_CONTENT_DIR');
|
867 |
+
// sometimes WP_CONTENT_DIR const removal failed, so we need to update them
|
868 |
+
if (false === $ret) {
|
869 |
+
$wpContentDir = "dirname(__FILE__).'/wp-content'";
|
870 |
+
$confTransformer->update('constant', 'WP_CONTENT_DIR', $wpContentDir, array('raw' => true, 'normalize' => true));
|
871 |
+
DUPX_Log::info('UPDATE WP_CONTENT_DIR '.DUPX_Log::varToString($wpContentDir));
|
872 |
+
}
|
873 |
+
} else {
|
874 |
+
$wpContentDir = "dirname(__FILE__).'/".$GLOBALS['DUPX_AC']->wp_content_dir_base_name."'";
|
875 |
+
$confTransformer->update('constant', 'WP_CONTENT_DIR', $wpContentDir, array('raw' => true, 'normalize' => true));
|
876 |
+
DUPX_Log::info('UPDATE WP_CONTENT_DIR '.DUPX_Log::varToString($wpContentDir));
|
877 |
+
}
|
878 |
+
} elseif ($confTransformer->exists('constant', 'WP_CONTENT_DIR')) {
|
879 |
+
$wp_content_dir_const_val = $confTransformer->get_value('constant', 'WP_CONTENT_DIR');
|
880 |
+
$wp_content_dir_const_val = DUPX_U::wp_normalize_path($wp_content_dir_const_val);
|
881 |
+
$new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wp_content_dir_const_val, $strReplaced);
|
882 |
+
if ($strReplaced > 0) {
|
883 |
+
$confTransformer->update('constant', 'WP_CONTENT_DIR', $new_path, array('normalize' => true));
|
884 |
+
DUPX_Log::info('UPDATE WP_CONTENT_DIR '.DUPX_Log::varToString($new_path));
|
885 |
+
}
|
886 |
+
}
|
887 |
+
|
888 |
+
//WP_CONTENT_URL
|
889 |
+
// '/' added to prevent word boundary with domains that have the same root path
|
890 |
+
if ($GLOBALS['DUPX_AC']->is_outer_root_wp_content_dir) {
|
891 |
+
if (empty($GLOBALS['DUPX_AC']->wp_content_dir_base_name)) {
|
892 |
+
$ret = $confTransformer->remove('constant', 'WP_CONTENT_URL');
|
893 |
+
DUPX_Log::info('REMOVE WP_CONTENT_URL');
|
894 |
+
// sometimes WP_CONTENT_DIR const removal failed, so we need to update them
|
895 |
+
if (false === $ret) {
|
896 |
+
$new_url = $this->post['url_new'].'/wp-content';
|
897 |
+
$confTransformer->update('constant', 'WP_CONTENT_URL', $new_url, array('raw' => true, 'normalize' => true));
|
898 |
+
DUPX_Log::info('UPDATE WP_CONTENT_URL '.DUPX_Log::varToString($new_url));
|
899 |
+
}
|
900 |
+
} else {
|
901 |
+
$new_url = $this->post['url_new'].'/'.$GLOBALS['DUPX_AC']->wp_content_dir_base_name;
|
902 |
+
$confTransformer->update('constant', 'WP_CONTENT_URL', $new_url, array('normalize' => true));
|
903 |
+
DUPX_Log::info('UPDATE WP_CONTENT_URL '.DUPX_Log::varToString($new_url));
|
904 |
+
}
|
905 |
+
} elseif ($confTransformer->exists('constant', 'WP_CONTENT_URL')) {
|
906 |
+
$wp_content_url_const_val = $confTransformer->get_value('constant', 'WP_CONTENT_URL');
|
907 |
+
$new_path = str_replace($this->post['url_old'].'/', $this->post['url_new'].'/', $wp_content_url_const_val, $strReplaced);
|
908 |
+
if ($strReplaced > 0) {
|
909 |
+
$confTransformer->update('constant', 'WP_CONTENT_URL', $new_path, array('normalize' => true));
|
910 |
+
DUPX_Log::info('UPDATE WP_CONTENT_URL '.DUPX_Log::varToString($new_path));
|
911 |
+
}
|
912 |
+
}
|
913 |
+
|
914 |
+
//WP_TEMP_DIR
|
915 |
+
if ($confTransformer->exists('constant', 'WP_TEMP_DIR')) {
|
916 |
+
$wp_temp_dir_const_val = $confTransformer->get_value('constant', 'WP_TEMP_DIR');
|
917 |
+
$wp_temp_dir_const_val = DUPX_U::wp_normalize_path($wp_temp_dir_const_val);
|
918 |
+
$new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wp_temp_dir_const_val, $strReplaced);
|
919 |
+
if ($strReplaced > 0) {
|
920 |
+
$confTransformer->update('constant', 'WP_TEMP_DIR', $new_path, array('normalize' => true));
|
921 |
+
DUPX_Log::info('UPDATE WP_TEMP_DIR '.DUPX_Log::varToString($new_path));
|
922 |
+
}
|
923 |
+
}
|
924 |
+
|
925 |
+
// WP_PLUGIN_DIR
|
926 |
+
if ($confTransformer->exists('constant', 'WP_PLUGIN_DIR')) {
|
927 |
+
$wp_plugin_dir_const_val = $confTransformer->get_value('constant', 'WP_PLUGIN_DIR');
|
928 |
+
$wp_plugin_dir_const_val = DUPX_U::wp_normalize_path($wp_plugin_dir_const_val);
|
929 |
+
$new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wp_plugin_dir_const_val, $strReplaced);
|
930 |
+
if ($strReplaced > 0) {
|
931 |
+
$confTransformer->update('constant', 'WP_PLUGIN_DIR', $new_path, array('normalize' => true));
|
932 |
+
DUPX_Log::info('UPDATE WP_PLUGIN_DIR '.DUPX_Log::varToString($new_path));
|
933 |
+
}
|
934 |
+
}
|
935 |
+
|
936 |
+
// WP_PLUGIN_URL
|
937 |
+
if ($confTransformer->exists('constant', 'WP_PLUGIN_URL')) {
|
938 |
+
$wp_plugin_url_const_val = $confTransformer->get_value('constant', 'WP_PLUGIN_URL');
|
939 |
+
$new_path = str_replace($this->post['url_old'].'/', $this->post['url_new'].'/', $wp_plugin_url_const_val, $strReplaced);
|
940 |
+
if ($strReplaced > 0) {
|
941 |
+
$confTransformer->update('constant', 'WP_PLUGIN_URL', $new_path, array('normalize' => true));
|
942 |
+
DUPX_Log::info('UPDATE WP_PLUGIN_URL '.DUPX_Log::varToString($new_path));
|
943 |
+
}
|
944 |
+
}
|
945 |
+
|
946 |
+
// WPMU_PLUGIN_DIR
|
947 |
+
if ($confTransformer->exists('constant', 'WPMU_PLUGIN_DIR')) {
|
948 |
+
$wpmu_plugin_dir_const_val = $confTransformer->get_value('constant', 'WPMU_PLUGIN_DIR');
|
949 |
+
$wpmu_plugin_dir_const_val = DUPX_U::wp_normalize_path($wpmu_plugin_dir_const_val);
|
950 |
+
$new_path = str_replace($this->post['path_old'], $this->post['path_new'], $wpmu_plugin_dir_const_val, $strReplaced);
|
951 |
+
if ($strReplaced > 0) {
|
952 |
+
$confTransformer->update('constant', 'WPMU_PLUGIN_DIR', $new_path, array('normalize' => true));
|
953 |
+
DUPX_Log::info('UPDATE WPMU_PLUGIN_DIR '.DUPX_Log::varToString($new_path));
|
954 |
+
}
|
955 |
+
}
|
956 |
+
|
957 |
+
// WPMU_PLUGIN_URL
|
958 |
+
if ($confTransformer->exists('constant', 'WPMU_PLUGIN_URL')) {
|
959 |
+
$wpmu_plugin_url_const_val = $confTransformer->get_value('constant', 'WPMU_PLUGIN_URL');
|
960 |
+
$new_path = str_replace($this->post['url_old'].'/', $this->post['url_new'].'/', $wpmu_plugin_url_const_val, $strReplaced);
|
961 |
+
if ($strReplaced > 0) {
|
962 |
+
$confTransformer->update('constant', 'WPMU_PLUGIN_URL', $new_path, array('normalize' => true));
|
963 |
+
DUPX_Log::info('UPDATE WPMU_PLUGIN_URL '.DUPX_Log::varToString($new_path));
|
964 |
+
}
|
965 |
+
}
|
966 |
+
DUPX_Log::info("\n*** UPDATED WP CONFIG FILE ***");
|
967 |
+
} else {
|
968 |
+
DUPX_Log::info("WP-CONFIG ARK FILE NOT FOUND");
|
969 |
+
DUPX_Log::info("WP-CONFIG ARK FILE:\n - 'dup-wp-config-arc__[HASH].txt'");
|
970 |
+
DUPX_Log::info("SKIP FILE UPDATES\n");
|
971 |
+
|
972 |
+
$shortMsg = 'wp-config.php not found';
|
973 |
+
$longMsg = <<<LONGMSG
|
974 |
+
Error updating wp-config file.<br>
|
975 |
+
The installation is finished but check the wp-config.php file and manually update the incorrect values.
|
976 |
+
LONGMSG;
|
977 |
+
/* $nManager->addNextStepNotice(array(
|
978 |
+
'shortMsg' => $shortMsg,
|
979 |
+
'level' => DUPX_NOTICE_ITEM::CRITICAL,
|
980 |
+
|
981 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception'); */
|
982 |
+
$nManager->addFinalReportNotice(array(
|
983 |
+
'shortMsg' => $shortMsg,
|
984 |
+
'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
|
985 |
+
'longMsg' => $longMsg,
|
986 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
|
987 |
+
'sections' => 'general'
|
988 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'wp-config-transformer-exception');
|
989 |
+
}
|
990 |
+
} catch (Exception $e) {
|
991 |
+
$shortMsg = 'wp-config.php transformer:'.$e->getMessage();
|
992 |
+
$longMsg = <<<LONGMSG
|
993 |
+
Error updating wp-config file.<br>
|
994 |
+
The installation is finished but check the wp-config.php file and manually update the incorrect values.
|
995 |
+
LONGMSG;
|
996 |
+
/* $nManager->addNextStepNotice(array(
|
997 |
+
'shortMsg' => $shortMsg,
|
998 |
+
'level' => DUPX_NOTICE_ITEM::CRITICAL,
|
999 |
+
|
1000 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception'); */
|
1001 |
+
$nManager->addFinalReportNotice(array(
|
1002 |
+
'shortMsg' => $shortMsg,
|
1003 |
+
'level' => DUPX_NOTICE_ITEM::CRITICAL,
|
1004 |
+
'longMsg' => $longMsg,
|
1005 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
|
1006 |
+
'sections' => 'general'
|
1007 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'wp-config-transformer-exception');
|
1008 |
+
|
1009 |
+
DUPX_Log::info("WP-CONFIG TRANSFORMER EXCEPTION\n".$e->getTraceAsString());
|
1010 |
+
}
|
1011 |
+
DUPX_Log::resetIndent();
|
1012 |
+
}
|
1013 |
+
|
1014 |
+
public function htaccessUpdate()
|
1015 |
+
{
|
1016 |
+
$this->getPost();
|
1017 |
+
self::logSectionHeader('HTACCESS UPDATE MODE: '.DUPX_LOG::varToString($this->post['config_mode']), __FUNCTION__, __LINE__);
|
1018 |
+
|
1019 |
+
|
1020 |
+
switch ($this->post['config_mode']) {
|
1021 |
+
case 'NEW':
|
1022 |
+
DUPX_ServerConfig::createNewConfigs();
|
1023 |
+
break;
|
1024 |
+
case 'RESTORE':
|
1025 |
+
DUPX_ServerConfig::renameOrigConfigs();
|
1026 |
+
DUPX_Log::info("\nWARNING: Retaining the original .htaccess or web.config files may cause");
|
1027 |
+
DUPX_Log::info("issues with the initial setup of your site. If you run into issues with the install");
|
1028 |
+
DUPX_Log::info("process choose 'Create New' for the 'Config Files' options");
|
1029 |
+
break;
|
1030 |
+
case 'IGNORE':
|
1031 |
+
DUPX_Log::info("\nWARNING: Choosing the option to ignore the .htaccess, web.config and .user.ini files");
|
1032 |
+
DUPX_Log::info("can lead to install issues. The 'Ignore All' option is designed for advanced users.");
|
1033 |
+
break;
|
1034 |
+
}
|
1035 |
+
}
|
1036 |
+
|
1037 |
+
public function generalUpdateAndCleanup()
|
1038 |
+
{
|
1039 |
+
self::logSectionHeader('GENERAL UPDATES & CLEANUP', __FUNCTION__, __LINE__);
|
1040 |
+
// make sure dbConnection is inizialized
|
1041 |
+
$this->dbConnection();
|
1042 |
+
|
1043 |
+
$blog_name = mysqli_real_escape_string($this->dbh, $this->post['blogname']);
|
1044 |
+
$plugin_list = $this->post['plugins'];
|
1045 |
+
|
1046 |
+
if (!in_array('duplicator-pro/duplicator.php', $plugin_list)) {
|
1047 |
+
$plugin_list[] = 'duplicator-pro/duplicator.php';
|
1048 |
+
}
|
1049 |
+
$serial_plugin_list = @serialize($plugin_list);
|
1050 |
+
|
1051 |
+
/** FINAL UPDATES: Must happen after the global replace to prevent double pathing
|
1052 |
+
http://xyz.com/abc01 will become http://xyz.com/abc0101 with trailing data */
|
1053 |
+
mysqli_query($this->dbh,
|
1054 |
+
"UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $blog_name)."' WHERE option_name = 'blogname' ");
|
1055 |
+
mysqli_query($this->dbh,
|
1056 |
+
"UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $serial_plugin_list)."' WHERE option_name = 'active_plugins' ");
|
1057 |
+
mysqli_query($this->dbh,
|
1058 |
+
"UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($this->dbh, $this->post['url_new'])."' WHERE option_name = 'home' ");
|
1059 |
+
mysqli_query($this->dbh,
|
1060 |
+
"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' ");
|
1061 |
+
mysqli_query($this->dbh,
|
1062 |
+
"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,
|
1063 |
+
$this->post['exe_safe_mode'])."','duplicator_pro_exe_safe_mode')");
|
1064 |
+
//Reset the postguid data
|
1065 |
+
if ($this->post['postguid']) {
|
1066 |
+
mysqli_query($this->dbh,
|
1067 |
+
"UPDATE `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."posts` SET guid = REPLACE(guid, '".mysqli_real_escape_string($this->dbh, $this->post['url_new'])."', '".mysqli_real_escape_string($this->dbh,
|
1068 |
+
$this->post['url_old'])."')");
|
1069 |
+
$update_guid = @mysqli_affected_rows($this->dbh) or 0;
|
1070 |
+
DUPX_Log::info("Reverted '{$update_guid}' post guid columns back to '{$this->post['url_old']}'");
|
1071 |
+
}
|
1072 |
+
}
|
1073 |
+
|
1074 |
+
public function noticeTest()
|
1075 |
+
{
|
1076 |
+
self::logSectionHeader('NOTICES TEST', __FUNCTION__, __LINE__);
|
1077 |
+
// make sure dbConnection is inizialized
|
1078 |
+
$this->dbConnection();
|
1079 |
+
|
1080 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
1081 |
+
if (file_exists($this->getWpconfigArkPath())) {
|
1082 |
+
$wpconfig_ark_contents = file_get_contents($this->getWpconfigArkPath());
|
1083 |
+
$config_vars = array('WPCACHEHOME', 'COOKIE_DOMAIN', 'WP_SITEURL', 'WP_HOME', 'WP_TEMP_DIR');
|
1084 |
+
$config_found = DUPX_U::getListValues($config_vars, $wpconfig_ark_contents);
|
1085 |
+
|
1086 |
+
//Files
|
1087 |
+
if (!empty($config_found)) {
|
1088 |
+
$msg = "WP-CONFIG NOTICE: The wp-config.php has following values set [".implode(", ", $config_found)."]. \n";
|
1089 |
+
$msg .= "Please validate these values are correct by opening the file and checking the values.\n";
|
1090 |
+
$msg .= "See the codex link for more details: https://codex.wordpress.org/Editing_wp-config.php";
|
1091 |
+
// old system
|
1092 |
+
$this->report['warnlist'][] = $msg;
|
1093 |
+
DUPX_Log::info($msg);
|
1094 |
+
|
1095 |
+
$nManager->addFinalReportNotice(array(
|
1096 |
+
'shortMsg' => 'wp-config notice',
|
1097 |
+
'level' => DUPX_NOTICE_ITEM::NOTICE,
|
1098 |
+
'longMsg' => $msg,
|
1099 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE,
|
1100 |
+
'sections' => 'general'
|
1101 |
+
));
|
1102 |
+
}
|
1103 |
+
|
1104 |
+
//-- Finally, back up the old wp-config and rename the new one
|
1105 |
+
$wpconfig_path = "{$GLOBALS['DUPX_ROOT']}/wp-config.php";
|
1106 |
+
if ($this->getWpconfigArkPath() !== $wpconfig_path) {
|
1107 |
+
if (copy($this->getWpconfigArkPath(), $wpconfig_path) === false) {
|
1108 |
+
DUPX_LOG::info(
|
1109 |
+
'COPY SOURCE: '.DUPX_LOG::varToString($this->getWpconfigArkPath())."\n".
|
1110 |
+
"COPY DEST:".DUPX_LOG::varToString($wpconfig_path), DUPX_Log::LV_DEBUG);
|
1111 |
+
DUPX_Log::error("ERROR: Unable to copy 'dup-wp-config-arc__[HASH].txt' to 'wp-config.php'.\n".
|
1112 |
+
"Check server permissions for more details see FAQ: https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-055-q");
|
1113 |
+
}
|
1114 |
+
}
|
1115 |
+
} else {
|
1116 |
+
$msg = "WP-CONFIG NOTICE: <b>wp-config.php not found.</b><br><br>";
|
1117 |
+
$msg .= "No action on the wp-config was possible.<br>";
|
1118 |
+
$msg .= "Be sure to insert a properly modified wp-config for correct wordpress operation.";
|
1119 |
+
$this->report['warnlist'][] = $msg;
|
1120 |
+
|
1121 |
+
$nManager->addFinalReportNotice(array(
|
1122 |
+
'shortMsg' => 'wp-config not found',
|
1123 |
+
'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
|
1124 |
+
'longMsg' => $msg,
|
1125 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML,
|
1126 |
+
'sections' => 'general'
|
1127 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'wp-config-not-found');
|
1128 |
+
|
1129 |
+
DUPX_Log::info($msg);
|
1130 |
+
}
|
1131 |
+
|
1132 |
+
//Database
|
1133 |
+
$result = @mysqli_query($this->dbh,
|
1134 |
+
"SELECT option_value FROM `".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE option_name IN ('upload_url_path','upload_path')");
|
1135 |
+
if ($result) {
|
1136 |
+
while ($row = mysqli_fetch_row($result)) {
|
1137 |
+
if (strlen($row[0])) {
|
1138 |
+
$msg = "MEDIA SETTINGS NOTICE: The table '".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options' has at least one the following values ['upload_url_path','upload_path'] \n";
|
1139 |
+
$msg .= "set please validate settings. These settings can be changed in the wp-admin by going to /wp-admin/options.php'";
|
1140 |
+
|
1141 |
+
$this->report['warnlist'][] = $msg;
|
1142 |
+
DUPX_Log::info($msg);
|
1143 |
+
|
1144 |
+
$nManager->addFinalReportNotice(array(
|
1145 |
+
'shortMsg' => 'Media settings notice',
|
1146 |
+
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
1147 |
+
'longMsg' => $msg,
|
1148 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_PRE,
|
1149 |
+
'sections' => 'general'
|
1150 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE, 'media-settings-notice');
|
1151 |
+
|
1152 |
+
break;
|
1153 |
+
}
|
1154 |
+
}
|
1155 |
+
}
|
1156 |
+
|
1157 |
+
$sql = "INSERT into ".mysqli_real_escape_string($this->dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options (option_name, option_value) VALUES ('duplicator_pro_migration', '1');";
|
1158 |
+
@mysqli_query($this->dbh, $sql);
|
1159 |
+
|
1160 |
+
if (empty($this->report['warnlist'])) {
|
1161 |
+
DUPX_Log::info("No General Notices Found\n");
|
1162 |
+
}
|
1163 |
+
}
|
1164 |
+
|
1165 |
+
public function cleanupTmpFiles()
|
1166 |
+
{
|
1167 |
+
self::logSectionHeader('CLEANUP TMP FILES', __FUNCTION__, __LINE__);
|
1168 |
+
// make sure post data is inizialized
|
1169 |
+
$this->getPost();
|
1170 |
+
|
1171 |
+
//Cleanup any tmp files a developer may have forgotten about
|
1172 |
+
//Lets be proactive for the developer just in case
|
1173 |
+
$wpconfig_path_bak = "{$GLOBALS['DUPX_ROOT']}/wp-config.bak";
|
1174 |
+
$wpconfig_path_old = "{$GLOBALS['DUPX_ROOT']}/wp-config.old";
|
1175 |
+
$wpconfig_path_org = "{$GLOBALS['DUPX_ROOT']}/wp-config.org";
|
1176 |
+
$wpconfig_path_orig = "{$GLOBALS['DUPX_ROOT']}/wp-config.orig";
|
1177 |
+
$wpconfig_safe_check = array($wpconfig_path_bak, $wpconfig_path_old, $wpconfig_path_org, $wpconfig_path_orig);
|
1178 |
+
foreach ($wpconfig_safe_check as $file) {
|
1179 |
+
if (file_exists($file)) {
|
1180 |
+
$tmp_newfile = $file.uniqid('_');
|
1181 |
+
if (rename($file, $tmp_newfile) === false) {
|
1182 |
+
DUPX_Log::info("WARNING: Unable to rename '{$file}' to '{$tmp_newfile}'");
|
1183 |
+
}
|
1184 |
+
}
|
1185 |
+
}
|
1186 |
+
}
|
1187 |
+
|
1188 |
+
public function finalReportNotices()
|
1189 |
+
{
|
1190 |
+
self::logSectionHeader('FINAL REPORT NOTICES', __FUNCTION__, __LINE__);
|
1191 |
+
|
1192 |
+
$this->wpConfigFinalReport();
|
1193 |
+
$this->htaccessFinalReport();
|
1194 |
+
}
|
1195 |
+
|
1196 |
+
private function htaccessFinalReport()
|
1197 |
+
{
|
1198 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
1199 |
+
|
1200 |
+
$orig = file_get_contents($this->getOrigHtaccessPath());
|
1201 |
+
$new = file_get_contents($GLOBALS['DUPX_ROOT'].'/.htaccess');
|
1202 |
+
|
1203 |
+
$lightBoxContent = '<div class="row-cols-2">'.
|
1204 |
+
'<div class="col col-1"><b>Original .htaccess</b><pre>'.htmlspecialchars($orig).'</pre></div>'.
|
1205 |
+
'<div class="col col-2"><b>New .htaccess</b><pre>'.htmlspecialchars($new).'</pre></div>'.
|
1206 |
+
'</div>';
|
1207 |
+
$longMsg = DUPX_U_Html::getLigthBox('.htaccess changes', 'HTACCESS COMPARE', $lightBoxContent, false);
|
1208 |
+
|
1209 |
+
$nManager->addFinalReportNotice(array(
|
1210 |
+
'shortMsg' => 'htaccess changes',
|
1211 |
+
'level' => DUPX_NOTICE_ITEM::INFO,
|
1212 |
+
'longMsg' => $longMsg,
|
1213 |
+
'sections' => 'changes',
|
1214 |
+
'open' => true,
|
1215 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML
|
1216 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'htaccess-changes');
|
1217 |
+
}
|
1218 |
+
|
1219 |
+
private function wpConfigFinalReport()
|
1220 |
+
{
|
1221 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
1222 |
+
|
1223 |
+
if (($orig = file_get_contents($this->getOrigWpConfigPath())) === false) {
|
1224 |
+
$orig = 'Can read origin wp-config.php file';
|
1225 |
+
} else {
|
1226 |
+
$orig = $this->obscureWpConfig($orig);
|
1227 |
+
}
|
1228 |
+
|
1229 |
+
if (($new = file_get_contents($GLOBALS['DUPX_ROOT'].'/wp-config.php')) === false) {
|
1230 |
+
$new = 'Can read wp-config.php file';
|
1231 |
+
} else {
|
1232 |
+
$new = $this->obscureWpConfig($new);
|
1233 |
+
}
|
1234 |
+
|
1235 |
+
$lightBoxContent = '<div class="row-cols-2">'.
|
1236 |
+
'<div class="col col-1"><b>Original wp-config.php</b><pre>'.htmlspecialchars($orig).'</pre></div>'.
|
1237 |
+
'<div class="col col-2"><b>New wp-config.php</b><pre>'.htmlspecialchars($new).'</pre></div>'.
|
1238 |
+
'</div>';
|
1239 |
+
$longMsg = DUPX_U_Html::getLigthBox('wp-config.php changes', 'WP-CONFIG.PHP COMPARE', $lightBoxContent, false);
|
1240 |
+
|
1241 |
+
$nManager->addFinalReportNotice(array(
|
1242 |
+
'shortMsg' => 'wp-config.php changes',
|
1243 |
+
'level' => DUPX_NOTICE_ITEM::INFO,
|
1244 |
+
'longMsg' => $longMsg,
|
1245 |
+
'sections' => 'changes',
|
1246 |
+
'open' => true,
|
1247 |
+
'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML
|
1248 |
+
), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'wp-config-changes');
|
1249 |
+
}
|
1250 |
+
|
1251 |
+
private function obscureWpConfig($src)
|
1252 |
+
{
|
1253 |
+
$transformer = new WPConfigTransformerSrc($src);
|
1254 |
+
$obsKeys = array(
|
1255 |
+
'DB_NAME',
|
1256 |
+
'DB_USER',
|
1257 |
+
'DB_HOST',
|
1258 |
+
'DB_PASSWORD',
|
1259 |
+
'AUTH_KEY',
|
1260 |
+
'SECURE_AUTH_KEY',
|
1261 |
+
'LOGGED_IN_KEY',
|
1262 |
+
'NONCE_KEY',
|
1263 |
+
'AUTH_SALT',
|
1264 |
+
'SECURE_AUTH_SALT',
|
1265 |
+
'LOGGED_IN_SALT',
|
1266 |
+
'NONCE_SALT');
|
1267 |
+
|
1268 |
+
foreach ($obsKeys as $key) {
|
1269 |
+
if ($transformer->exists('constant', $key)) {
|
1270 |
+
$transformer->update('constant', $key, '**OBSCURED**');
|
1271 |
+
}
|
1272 |
+
}
|
1273 |
+
|
1274 |
+
return $transformer->getSrc();
|
1275 |
+
}
|
1276 |
+
|
1277 |
+
public function complete()
|
1278 |
+
{
|
1279 |
+
// make sure post data is inizialized
|
1280 |
+
$this->getPost();
|
1281 |
+
$this->closeDbConnection();
|
1282 |
+
|
1283 |
+
$ajax3_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $this->timeStart);
|
1284 |
+
DUPX_Log::info("\nSTEP-3 COMPLETE @ ".@date('h:i:s')." - RUNTIME: {$ajax3_sum} \n\n");
|
1285 |
+
|
1286 |
+
$this->fullReport = true;
|
1287 |
+
$this->report['pass'] = 1;
|
1288 |
+
$this->report['chunk'] = 0;
|
1289 |
+
$this->report['chunkPos'] = null;
|
1290 |
+
$this->report['progress_perc'] = 100;
|
1291 |
+
// error_reporting($ajax3_error_level);
|
1292 |
+
}
|
1293 |
+
|
1294 |
+
public function error($message)
|
1295 |
+
{
|
1296 |
+
// make sure post data is inizialized
|
1297 |
+
$this->getPost();
|
1298 |
+
|
1299 |
+
$this->closeDbConnection();
|
1300 |
+
|
1301 |
+
$ajax3_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $this->timeStart);
|
1302 |
+
DUPX_Log::info("\nSTEP-3 ERROR @ ".@date('h:i:s')." - RUNTIME: {$ajax3_sum} \n\n");
|
1303 |
+
|
1304 |
+
$this->report['pass'] = -1;
|
1305 |
+
$this->report['chunk'] = 0;
|
1306 |
+
$this->report['chunkPos'] = null;
|
1307 |
+
$this->report['error_message'] = $message;
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
protected function __clone()
|
1311 |
+
{
|
1312 |
+
|
1313 |
+
}
|
1314 |
+
|
1315 |
+
public function __wakeup()
|
1316 |
+
{
|
1317 |
+
throw new Exception("Cannot unserialize singleton");
|
1318 |
+
}
|
1319 |
+
}
|
installer/dup-installer/classes/class.view.php
CHANGED
@@ -1,73 +1,73 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
*
|
4 |
-
* Standard: PSR-2
|
5 |
-
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
6 |
-
*
|
7 |
-
* @package SC\DUPX
|
8 |
-
*
|
9 |
-
*/
|
10 |
-
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
11 |
-
|
12 |
-
/**
|
13 |
-
* View functions
|
14 |
-
*/
|
15 |
-
class DUPX_View_Funcs
|
16 |
-
{
|
17 |
-
|
18 |
-
public static function installerLogLink()
|
19 |
-
{
|
20 |
-
$log_url = $GLOBALS['DUPX_ROOT_URL'].'/'.$GLOBALS["LOG_FILE_NAME"].'?now='.DUPX_U::esc_attr($GLOBALS['NOW_TIME']);
|
21 |
-
DUPX_U_Html::getLightBoxIframe('installer-log.txt', 'installer-log.txt', $log_url, true, true);
|
22 |
-
}
|
23 |
-
|
24 |
-
public static function getHelpLink($section = '')
|
25 |
-
{
|
26 |
-
switch ($section) {
|
27 |
-
case "secure" :
|
28 |
-
$helpOpenSection = 'section-security';
|
29 |
-
break;
|
30 |
-
case "step1" :
|
31 |
-
$helpOpenSection = 'section-step-1';
|
32 |
-
break;
|
33 |
-
case "step2" :
|
34 |
-
$helpOpenSection = 'section-step-2';
|
35 |
-
break;
|
36 |
-
case "step3" :
|
37 |
-
$helpOpenSection = 'section-step-3';
|
38 |
-
break;
|
39 |
-
case "step4" :
|
40 |
-
$helpOpenSection = 'section-step-4';
|
41 |
-
break;
|
42 |
-
case "help" :
|
43 |
-
default :
|
44 |
-
$helpOpenSection = '';
|
45 |
-
}
|
46 |
-
|
47 |
-
return "?view=help".
|
48 |
-
"&archive={$GLOBALS['FW_ENCODED_PACKAGE_PATH']}".
|
49 |
-
"&bootloader={$GLOBALS['BOOTLOADER_NAME']}&".
|
50 |
-
"basic".
|
51 |
-
'&open_section='.$helpOpenSection;
|
52 |
-
}
|
53 |
-
|
54 |
-
public static function helpLink($section, $linkLabel = 'Help')
|
55 |
-
{
|
56 |
-
$help_url = self::getHelpLink($section);
|
57 |
-
DUPX_U_Html::getLightBoxIframe($linkLabel, 'HELP', $help_url);
|
58 |
-
}
|
59 |
-
|
60 |
-
public static function helpLockLink()
|
61 |
-
{
|
62 |
-
if ($GLOBALS['DUPX_AC']->secure_on) {
|
63 |
-
self::helpLink('secure', '<i class="fa fa-lock fa-xs"></i>');
|
64 |
-
} else {
|
65 |
-
self::helpLink('secure', '<i class="fa fa-unlock-alt fa-xs"></i>');
|
66 |
-
}
|
67 |
-
}
|
68 |
-
|
69 |
-
public static function helpIconLink($section)
|
70 |
-
{
|
71 |
-
self::helpLink($section, '<i class="fas fa-question-circle fa-sm"></i>');
|
72 |
-
}
|
73 |
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
*
|
4 |
+
* Standard: PSR-2
|
5 |
+
* @link http://www.php-fig.org/psr/psr-2 Full Documentation
|
6 |
+
*
|
7 |
+
* @package SC\DUPX
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* View functions
|
14 |
+
*/
|
15 |
+
class DUPX_View_Funcs
|
16 |
+
{
|
17 |
+
|
18 |
+
public static function installerLogLink()
|
19 |
+
{
|
20 |
+
$log_url = $GLOBALS['DUPX_ROOT_URL'].'/'.$GLOBALS["LOG_FILE_NAME"].'?now='.DUPX_U::esc_attr($GLOBALS['NOW_TIME']);
|
21 |
+
DUPX_U_Html::getLightBoxIframe('dup-installer-log.txt', 'installer-log.txt', $log_url, true, true);
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function getHelpLink($section = '')
|
25 |
+
{
|
26 |
+
switch ($section) {
|
27 |
+
case "secure" :
|
28 |
+
$helpOpenSection = 'section-security';
|
29 |
+
break;
|
30 |
+
case "step1" :
|
31 |
+
$helpOpenSection = 'section-step-1';
|
32 |
+
break;
|
33 |
+
case "step2" :
|
34 |
+
$helpOpenSection = 'section-step-2';
|
35 |
+
break;
|
36 |
+
case "step3" :
|
37 |
+
$helpOpenSection = 'section-step-3';
|
38 |
+
break;
|
39 |
+
case "step4" :
|
40 |
+
$helpOpenSection = 'section-step-4';
|
41 |
+
break;
|
42 |
+
case "help" :
|
43 |
+
default :
|
44 |
+
$helpOpenSection = '';
|
45 |
+
}
|
46 |
+
|
47 |
+
return "?view=help".
|
48 |
+
"&archive={$GLOBALS['FW_ENCODED_PACKAGE_PATH']}".
|
49 |
+
"&bootloader={$GLOBALS['BOOTLOADER_NAME']}&".
|
50 |
+
"basic".
|
51 |
+
'&open_section='.$helpOpenSection;
|
52 |
+
}
|
53 |
+
|
54 |
+
public static function helpLink($section, $linkLabel = 'Help')
|
55 |
+
{
|
56 |
+
$help_url = self::getHelpLink($section);
|
57 |
+
DUPX_U_Html::getLightBoxIframe($linkLabel, 'HELP', $help_url);
|
58 |
+
}
|
59 |
+
|
60 |
+
public static function helpLockLink()
|
61 |
+
{
|
62 |
+
if ($GLOBALS['DUPX_AC']->secure_on) {
|
63 |
+
self::helpLink('secure', '<i class="fa fa-lock fa-xs"></i>');
|
64 |
+
} else {
|
65 |
+
self::helpLink('secure', '<i class="fa fa-unlock-alt fa-xs"></i>');
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
public static function helpIconLink($section)
|
70 |
+
{
|
71 |
+
self::helpLink($section, '<i class="fas fa-question-circle fa-sm"></i>');
|
72 |
+
}
|
73 |
}
|
installer/dup-installer/classes/config/class.boot.php
CHANGED
@@ -88,6 +88,7 @@ class DUPX_Boot
|
|
88 |
require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.notices.manager.php');
|
89 |
require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.html.php');
|
90 |
require_once($GLOBALS['DUPX_INIT'].'/classes/config/class.constants.php');
|
|
|
91 |
}
|
92 |
|
93 |
public static function initArchiveAndLog()
|
88 |
require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.notices.manager.php');
|
89 |
require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.html.php');
|
90 |
require_once($GLOBALS['DUPX_INIT'].'/classes/config/class.constants.php');
|
91 |
+
require_once($GLOBALS['DUPX_INIT'].'/ctrls/ctrl.base.php');
|
92 |
}
|
93 |
|
94 |
public static function initArchiveAndLog()
|
installer/dup-installer/classes/config/class.conf.srv.php
CHANGED
@@ -276,20 +276,24 @@ HTACCESS;
|
|
276 |
break;
|
277 |
}
|
278 |
|
279 |
-
if (is_dir(self::$rootPath)){
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
|
|
|
|
|
|
|
|
291 |
|
292 |
-
|
293 |
}
|
294 |
|
295 |
/**
|
@@ -317,198 +321,109 @@ HTACCESS;
|
|
317 |
break;
|
318 |
}
|
319 |
}
|
320 |
-
|
321 |
-
/**
|
322 |
-
*
|
323 |
-
* @staticvar string $path
|
324 |
-
* @return string
|
325 |
-
*/
|
326 |
-
public static function getWpconfigArkPath()
|
327 |
-
{
|
328 |
-
static $path = null;
|
329 |
-
if (is_null($path)) {
|
330 |
-
$path = $GLOBALS['DUPX_AC']->installSiteOverwriteOn ? $GLOBALS['DUPX_ROOT'].'/dup-wp-config-arc__'.$GLOBALS['DUPX_AC']->package_hash.'.txt' : $GLOBALS['DUPX_ROOT'].'/wp-config.php';
|
331 |
-
}
|
332 |
-
return $path;
|
333 |
-
}
|
334 |
|
335 |
/**
|
|
|
336 |
*
|
337 |
-
* @
|
338 |
* @return string
|
339 |
*/
|
340 |
-
|
341 |
{
|
342 |
-
|
343 |
-
if (
|
344 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
}
|
346 |
-
return
|
347 |
}
|
348 |
|
349 |
/**
|
|
|
350 |
*
|
351 |
-
* @
|
352 |
-
* @
|
353 |
-
*/
|
354 |
-
public static function getOrigWpConfigPath()
|
355 |
-
{
|
356 |
-
static $path = null;
|
357 |
-
if (is_null($path)) {
|
358 |
-
$path = $GLOBALS['DUPX_INIT'].'/dup-orig-wp-config__'.$GLOBALS['DUPX_AC']->package_hash.'.txt';
|
359 |
-
}
|
360 |
-
return $path;
|
361 |
-
}
|
362 |
-
|
363 |
-
/**
|
364 |
*
|
365 |
-
* @
|
366 |
-
* @return string
|
367 |
*/
|
368 |
-
public static function
|
369 |
{
|
370 |
-
|
371 |
-
|
372 |
-
|
|
|
373 |
}
|
374 |
-
|
|
|
375 |
}
|
376 |
|
377 |
/**
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
|
|
|
|
|
|
|
|
|
|
382 |
{
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
}
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
$htOrigPath = self::getOrigHtaccessPath();
|
404 |
-
$htArkPath = self::getHtaccessArkPath();
|
405 |
-
|
406 |
-
if (file_exists($htOrigPath)) {
|
407 |
-
if (!@unlink($htOrigPath)) {
|
408 |
-
DUPX_Log::info('Can\'t delete copy of htaccess orig file');
|
409 |
}
|
410 |
}
|
411 |
|
412 |
-
if (!file_exists($htArkPath)) {
|
413 |
-
DUPX_Log::info('htaccess ark file don\' exists');
|
414 |
-
}
|
415 |
|
416 |
-
if (
|
417 |
-
$
|
418 |
-
DUPX_Log::info("COPY ERROR: ".$errors['type']."\n".$errors['message']);
|
419 |
} else {
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
435 |
-
|
436 |
-
$orig = file_get_contents(self::getOrigHtaccessPath());
|
437 |
-
$new = file_get_contents($GLOBALS['DUPX_ROOT'].'/.htaccess');
|
438 |
-
|
439 |
-
$lightBoxContent = '<div class="row-cols-2">'.
|
440 |
-
'<div class="col col-1" style="background-color:#fff7f7"><b style="color:maroon"><i class="fas fa-sticky-note"></i> Original .htaccess</b><pre>'.htmlspecialchars($orig).'</pre></div>'.
|
441 |
-
'<div class="col col-2" style="background-color:#f7fdf1"><b style="color:green"><i class="far fa-sticky-note"></i> New .htaccess</b><pre>'.htmlspecialchars($new).'</pre></div>'.
|
442 |
-
'</div>';
|
443 |
-
$longMsg = DUPX_U_Html::getLigthBox('.htaccess changes', 'HTACCESS COMPARE', $lightBoxContent, false);
|
444 |
-
|
445 |
-
$nManager->addFinalReportNotice(array(
|
446 |
-
'shortMsg' => 'htaccess changes',
|
447 |
-
'level' => DUPX_NOTICE_ITEM::INFO,
|
448 |
-
'longMsg' => $longMsg,
|
449 |
-
'sections' => 'changes',
|
450 |
-
'open' => true,
|
451 |
-
'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML
|
452 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'htaccess-changes');
|
453 |
-
}
|
454 |
-
|
455 |
-
private static function wpConfigFinalReport()
|
456 |
-
{
|
457 |
-
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
458 |
-
|
459 |
-
if (($orig = file_get_contents(self::getOrigWpConfigPath())) === false) {
|
460 |
-
$orig = 'Can read origin wp-config.php file';
|
461 |
-
} else {
|
462 |
-
$orig = self::obscureWpConfig($orig);
|
463 |
}
|
464 |
|
465 |
-
if (($
|
466 |
-
|
467 |
} else {
|
468 |
-
|
469 |
}
|
470 |
-
|
471 |
-
$lightBoxContent = '<div class="row-cols-2">'.
|
472 |
-
'<div class="col col-1" style="background-color:#fff7f7"><b style="color:maroon"><i class="fas fa-sticky-note"></i> Original wp-config.php</b><pre class="s4-diff-viewer">'.htmlspecialchars($orig).'</pre></div>'.
|
473 |
-
'<div class="col col-2" style="background-color:#f7fdf1"><b style="color:green"><i class="far fa-sticky-note"></i> New wp-config.php</b><pre class="s4-diff-viewer">'.htmlspecialchars($new).'</pre></div>'.
|
474 |
-
'</div>';
|
475 |
-
$longMsg = DUPX_U_Html::getLigthBox('wp-config.php changes', 'WP-CONFIG.PHP COMPARE', $lightBoxContent, false);
|
476 |
-
|
477 |
-
$nManager->addFinalReportNotice(array(
|
478 |
-
'shortMsg' => 'wp-config.php changes',
|
479 |
-
'level' => DUPX_NOTICE_ITEM::INFO,
|
480 |
-
'longMsg' => $longMsg,
|
481 |
-
'sections' => 'changes',
|
482 |
-
'open' => true,
|
483 |
-
'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML
|
484 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE, 'wp-config-changes');
|
485 |
-
}
|
486 |
-
|
487 |
-
private static function obscureWpConfig($src)
|
488 |
-
{
|
489 |
-
$transformer = new WPConfigTransformerSrc($src);
|
490 |
-
$obsKeys = array(
|
491 |
-
'DB_NAME',
|
492 |
-
'DB_USER',
|
493 |
-
'DB_HOST',
|
494 |
-
'DB_PASSWORD',
|
495 |
-
'AUTH_KEY',
|
496 |
-
'SECURE_AUTH_KEY',
|
497 |
-
'LOGGED_IN_KEY',
|
498 |
-
'NONCE_KEY',
|
499 |
-
'AUTH_SALT',
|
500 |
-
'SECURE_AUTH_SALT',
|
501 |
-
'LOGGED_IN_SALT',
|
502 |
-
'NONCE_SALT');
|
503 |
-
|
504 |
-
foreach ($obsKeys as $key) {
|
505 |
-
if ($transformer->exists('constant', $key)) {
|
506 |
-
$transformer->update('constant', $key, '**OBSCURED**');
|
507 |
-
}
|
508 |
-
}
|
509 |
-
|
510 |
-
return $transformer->getSrc();
|
511 |
}
|
512 |
}
|
513 |
-
|
514 |
DUPX_ServerConfig::init();
|
276 |
break;
|
277 |
}
|
278 |
|
279 |
+
if (is_dir(self::$rootPath)) {
|
280 |
+
$dir = new DirectoryIterator(self::$rootPath);
|
281 |
+
foreach ($dir as $file) {
|
282 |
+
if ($file->isDot()) {
|
283 |
+
continue;
|
284 |
+
}
|
285 |
+
if ($file->isFile()) {
|
286 |
+
$name = $file->getFilename();
|
287 |
+
if (strpos($name, '-duplicator.bak')) {
|
288 |
+
if (preg_match($pattern, $name)) {
|
289 |
+
return true;
|
290 |
+
}
|
291 |
+
}
|
292 |
+
}
|
293 |
+
}
|
294 |
+
}
|
295 |
|
296 |
+
return false;
|
297 |
}
|
298 |
|
299 |
/**
|
321 |
break;
|
322 |
}
|
323 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
324 |
|
325 |
/**
|
326 |
+
* Get AddHadler line from existing WP .htaccess file
|
327 |
*
|
328 |
+
* @param $path string root path
|
329 |
* @return string
|
330 |
*/
|
331 |
+
private static function getOldHtaccessAddhandlerLine($path)
|
332 |
{
|
333 |
+
$backupHtaccessPath = $path.'/.htaccess-'.$GLOBALS['DUPX_AC']->package_hash.'.orig';
|
334 |
+
if (file_exists($backupHtaccessPath)) {
|
335 |
+
$htaccessContent = file_get_contents($backupHtaccessPath);
|
336 |
+
if (!empty($htaccessContent)) {
|
337 |
+
// match and trim non commented line "AddHandler application/x-httpd-XXXX .php" case insenstive
|
338 |
+
$re = '/^[\s\t]*[^#]?[\s\t]*(AddHandler[\s\t]+.+\.php[ \t]?.*?)[\s\t]*$/mi';
|
339 |
+
$matches = array();
|
340 |
+
if (preg_match($re, $htaccessContent, $matches)) {
|
341 |
+
return "\n".$matches[1];
|
342 |
+
}
|
343 |
+
}
|
344 |
}
|
345 |
+
return '';
|
346 |
}
|
347 |
|
348 |
/**
|
349 |
+
* Copies the code in htaccess.orig to .htaccess
|
350 |
*
|
351 |
+
* @param $path The root path to the location of the server config files
|
352 |
+
* @param $new_htaccess_name New name of htaccess (either .htaccess or a backup name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
*
|
354 |
+
* @return bool Returns true if the .htaccess file was retained successfully
|
|
|
355 |
*/
|
356 |
+
public static function renameHtaccess($path, $new_htaccess_name)
|
357 |
{
|
358 |
+
$status = false;
|
359 |
+
|
360 |
+
if (!@rename($path.'/htaccess.orig', $path.'/'.$new_htaccess_name)) {
|
361 |
+
$status = true;
|
362 |
}
|
363 |
+
|
364 |
+
return $status;
|
365 |
}
|
366 |
|
367 |
/**
|
368 |
+
* Sets up the web config file based on the inputs from the installer forms.
|
369 |
+
*
|
370 |
+
* @param int $mu_mode Is this site a specific multi-site mode
|
371 |
+
* @param object $dbh The database connection handle for this request
|
372 |
+
* @param string $path The path to the config file
|
373 |
+
*
|
374 |
+
* @return null
|
375 |
+
*/
|
376 |
+
public static function setup($mu_mode, $mu_generation, $dbh, $path)
|
377 |
{
|
378 |
+
DUPX_Log::info("\nWEB SERVER CONFIGURATION FILE UPDATED:");
|
379 |
+
|
380 |
+
$timestamp = date("Y-m-d H:i:s");
|
381 |
+
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
382 |
+
$newdata = parse_url($post_url_new);
|
383 |
+
$newpath = DUPX_U::addSlash(isset($newdata['path']) ? $newdata['path'] : "");
|
384 |
+
$update_msg = "# This file was updated by Duplicator Pro on {$timestamp}.\n";
|
385 |
+
$update_msg .= (file_exists("{$path}/.htaccess")) ? "# See htaccess.orig for the .htaccess original file." : "";
|
386 |
+
$update_msg .= self::getOldHtaccessAddhandlerLine($path);
|
387 |
+
|
388 |
+
|
389 |
+
// no multisite
|
390 |
+
$empty_htaccess = false;
|
391 |
+
$query_result = @mysqli_query($dbh, "SELECT option_value FROM `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` WHERE option_name = 'permalink_structure' ");
|
392 |
+
|
393 |
+
if ($query_result) {
|
394 |
+
$row = @mysqli_fetch_array($query_result);
|
395 |
+
if ($row != null) {
|
396 |
+
$permalink_structure = trim($row[0]);
|
397 |
+
$empty_htaccess = empty($permalink_structure);
|
|
|
|
|
|
|
|
|
|
|
|
|
398 |
}
|
399 |
}
|
400 |
|
|
|
|
|
|
|
401 |
|
402 |
+
if ($empty_htaccess) {
|
403 |
+
$tmp_htaccess = '';
|
|
|
404 |
} else {
|
405 |
+
$tmp_htaccess = <<<HTACCESS
|
406 |
+
{$update_msg}
|
407 |
+
# BEGIN WordPress
|
408 |
+
<IfModule mod_rewrite.c>
|
409 |
+
RewriteEngine On
|
410 |
+
RewriteBase {$newpath}
|
411 |
+
RewriteRule ^index\.php$ - [L]
|
412 |
+
RewriteCond %{REQUEST_FILENAME} !-f
|
413 |
+
RewriteCond %{REQUEST_FILENAME} !-d
|
414 |
+
RewriteRule . {$newpath}index.php [L]
|
415 |
+
</IfModule>
|
416 |
+
# END WordPress
|
417 |
+
HTACCESS;
|
418 |
+
DUPX_Log::info("- Preparing .htaccess file with basic setup.");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
419 |
}
|
420 |
|
421 |
+
if (@file_put_contents("{$path}/.htaccess", $tmp_htaccess) === FALSE) {
|
422 |
+
DUPX_Log::info("WARNING: Unable to update the .htaccess file! Please check the permission on the root directory and make sure the .htaccess exists.");
|
423 |
} else {
|
424 |
+
DUPX_Log::info("- Successfully updated the .htaccess file setting.");
|
425 |
}
|
426 |
+
@chmod("{$path}/.htaccess", 0644);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
427 |
}
|
428 |
}
|
|
|
429 |
DUPX_ServerConfig::init();
|
installer/dup-installer/classes/config/class.constants.php
CHANGED
@@ -12,6 +12,14 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
12 |
*/
|
13 |
class DUPX_Constants
|
14 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
/**
|
16 |
* Init method used to auto initialize the global params
|
17 |
*
|
@@ -36,6 +44,7 @@ class DUPX_Constants
|
|
36 |
//DATABASE SETUP: all time in seconds
|
37 |
//max_allowed_packet: max value 1073741824 (1268MB) see my.ini
|
38 |
$GLOBALS['DB_MAX_TIME'] = 5000;
|
|
|
39 |
$GLOBALS['DB_MAX_PACKETS'] = 268435456;
|
40 |
$GLOBALS['DBCHARSET_DEFAULT'] = 'utf8';
|
41 |
$GLOBALS['DBCOLLATE_DEFAULT'] = 'utf8_general_ci';
|
@@ -78,9 +87,9 @@ class DUPX_Constants
|
|
78 |
$GLOBALS['LOG_FILE_PATH'] = $GLOBALS['DUPX_INIT'] . '/' . $GLOBALS["LOG_FILE_NAME"];
|
79 |
$GLOBALS["NOTICES_FILE_NAME"] = "dup-installer-notices__{$GLOBALS['PACKAGE_HASH']}.json";
|
80 |
$GLOBALS["NOTICES_FILE_PATH"] = $GLOBALS['DUPX_INIT'] . '/' . $GLOBALS["NOTICES_FILE_NAME"];
|
81 |
-
$GLOBALS['CHOWN_ROOT_PATH'] =
|
82 |
-
$GLOBALS['CHOWN_LOG_PATH'] =
|
83 |
-
$GLOBALS['CHOWN_NOTICES_PATH'] =
|
84 |
$GLOBALS['URL_SSL'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? true : false;
|
85 |
$GLOBALS['URL_PATH'] = ($GLOBALS['URL_SSL']) ? "https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}" : "http://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
|
86 |
$GLOBALS['PHP_MEMORY_LIMIT'] = ini_get('memory_limit') === false ? 'n/a' : ini_get('memory_limit');
|
@@ -99,7 +108,13 @@ class DUPX_Constants
|
|
99 |
$GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_PATH'], "a+");
|
100 |
}
|
101 |
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
if (!defined('MAX_STRLEN_SERIALIZED_CHECK')) { define('MAX_STRLEN_SERIALIZED_CHECK', 2000000); }
|
105 |
}
|
12 |
*/
|
13 |
class DUPX_Constants
|
14 |
{
|
15 |
+
const DEFAULT_MAX_STRLEN_SERIALIZED_CHECK_IN_M = 4; // 0 no limit
|
16 |
+
|
17 |
+
/**
|
18 |
+
*
|
19 |
+
* @var int
|
20 |
+
*/
|
21 |
+
public static $maxStrlenSerializeCheck = self::DEFAULT_MAX_STRLEN_SERIALIZED_CHECK;
|
22 |
+
|
23 |
/**
|
24 |
* Init method used to auto initialize the global params
|
25 |
*
|
44 |
//DATABASE SETUP: all time in seconds
|
45 |
//max_allowed_packet: max value 1073741824 (1268MB) see my.ini
|
46 |
$GLOBALS['DB_MAX_TIME'] = 5000;
|
47 |
+
$GLOBALS['DATABASE_PAGE_SIZE'] = 3500;
|
48 |
$GLOBALS['DB_MAX_PACKETS'] = 268435456;
|
49 |
$GLOBALS['DBCHARSET_DEFAULT'] = 'utf8';
|
50 |
$GLOBALS['DBCOLLATE_DEFAULT'] = 'utf8_general_ci';
|
87 |
$GLOBALS['LOG_FILE_PATH'] = $GLOBALS['DUPX_INIT'] . '/' . $GLOBALS["LOG_FILE_NAME"];
|
88 |
$GLOBALS["NOTICES_FILE_NAME"] = "dup-installer-notices__{$GLOBALS['PACKAGE_HASH']}.json";
|
89 |
$GLOBALS["NOTICES_FILE_PATH"] = $GLOBALS['DUPX_INIT'] . '/' . $GLOBALS["NOTICES_FILE_NAME"];
|
90 |
+
$GLOBALS['CHOWN_ROOT_PATH'] = DupLiteSnapLibIOU::chmod("{$GLOBALS['CURRENT_ROOT_PATH']}", 'u+rwx');
|
91 |
+
$GLOBALS['CHOWN_LOG_PATH'] = DupLiteSnapLibIOU::chmod("{$GLOBALS['LOG_FILE_PATH']}", 'u+rw');
|
92 |
+
$GLOBALS['CHOWN_NOTICES_PATH'] = DupLiteSnapLibIOU::chmod("{$GLOBALS['NOTICES_FILE_PATH']}", 'u+rw');
|
93 |
$GLOBALS['URL_SSL'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? true : false;
|
94 |
$GLOBALS['URL_PATH'] = ($GLOBALS['URL_SSL']) ? "https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}" : "http://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
|
95 |
$GLOBALS['PHP_MEMORY_LIMIT'] = ini_get('memory_limit') === false ? 'n/a' : ini_get('memory_limit');
|
108 |
$GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_PATH'], "a+");
|
109 |
}
|
110 |
|
111 |
+
// for ngrok url and Local by Flywheel Live URL
|
112 |
+
if (isset($_SERVER['HTTP_X_ORIGINAL_HOST'])) {
|
113 |
+
$host = $_SERVER['HTTP_X_ORIGINAL_HOST'];
|
114 |
+
} else {
|
115 |
+
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];//WAS SERVER_NAME and caused problems on some boxes
|
116 |
+
}
|
117 |
+
$GLOBALS['HOST_NAME'] = $host;
|
118 |
|
119 |
if (!defined('MAX_STRLEN_SERIALIZED_CHECK')) { define('MAX_STRLEN_SERIALIZED_CHECK', 2000000); }
|
120 |
}
|
installer/dup-installer/classes/utilities/class.u.php
CHANGED
@@ -122,13 +122,11 @@ class DUPX_U
|
|
122 |
}
|
123 |
|
124 |
// If the destination directory does not exist create it
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
}
|
131 |
-
|
132 |
// Open the source directory to read in files
|
133 |
$iterator = new DirectoryIterator($src);
|
134 |
|
@@ -1781,5 +1779,38 @@ class DUPX_U
|
|
1781 |
}
|
1782 |
return $result;
|
1783 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1784 |
}
|
1785 |
DUPX_U::init();
|
122 |
}
|
123 |
|
124 |
// If the destination directory does not exist create it
|
125 |
+
if (!DupLiteSnapLibIOU::dirWriteCheckOrMkdir($dest, 'u+rwx')) {
|
126 |
+
// If the destination directory could not be created stop processing
|
127 |
+
return false;
|
128 |
+
}
|
129 |
+
|
|
|
|
|
130 |
// Open the source directory to read in files
|
131 |
$iterator = new DirectoryIterator($src);
|
132 |
|
1779 |
}
|
1780 |
return $result;
|
1781 |
}
|
1782 |
+
|
1783 |
+
/**
|
1784 |
+
*
|
1785 |
+
* @param array $input // es $_POST $_GET $_REQUEST
|
1786 |
+
* @param string $key // key of array to check
|
1787 |
+
* @param array $options // array('default' => null, default value to return if key don't exist
|
1788 |
+
* 'trim' => false // if true trim sanitize value
|
1789 |
+
* )
|
1790 |
+
* @return type
|
1791 |
+
*/
|
1792 |
+
public static function isset_sanitize($input, $key, $options = array())
|
1793 |
+
{
|
1794 |
+
$opt = array_merge(array('default' => null, 'trim' => false), $options);
|
1795 |
+
if (isset($input[$key])) {
|
1796 |
+
$result = DUPX_U::sanitize_text_field($input[$key]);
|
1797 |
+
if ($opt['trim']) {
|
1798 |
+
$result = trim($result);
|
1799 |
+
}
|
1800 |
+
return $result;
|
1801 |
+
} else {
|
1802 |
+
return $opt['default'];
|
1803 |
+
}
|
1804 |
+
}
|
1805 |
+
|
1806 |
+
public static function boolToStr($input)
|
1807 |
+
{
|
1808 |
+
return $input ? 'true' : 'false';
|
1809 |
+
}
|
1810 |
+
|
1811 |
+
public static function boolToEnable($input)
|
1812 |
+
{
|
1813 |
+
return $input ? 'enable' : 'disable';
|
1814 |
+
}
|
1815 |
}
|
1816 |
DUPX_U::init();
|
installer/dup-installer/classes/utilities/class.u.search.reaplce.manager.php
ADDED
@@ -0,0 +1,611 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Search and reaplace 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 |
+
* Search and replace manager
|
15 |
+
* singleton class
|
16 |
+
*/
|
17 |
+
final class DUPX_S_R_MANAGER
|
18 |
+
{
|
19 |
+
const GLOBAL_SCOPE_KEY = '___!GLOBAL!___!SCOPE!___';
|
20 |
+
|
21 |
+
/**
|
22 |
+
*
|
23 |
+
* @var DUPX_S_R_MANAGER
|
24 |
+
*/
|
25 |
+
private static $instance = null;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* full list items not sorted
|
29 |
+
* @var DUPX_S_R_ITEM[]
|
30 |
+
*/
|
31 |
+
private $items = array();
|
32 |
+
|
33 |
+
/**
|
34 |
+
* items sorted by priority and scope
|
35 |
+
* [
|
36 |
+
* 10 => [
|
37 |
+
* '___!GLOBAL!___!SCOPE!___' => [
|
38 |
+
* DUPX_S_R_ITEM
|
39 |
+
* DUPX_S_R_ITEM
|
40 |
+
* DUPX_S_R_ITEM
|
41 |
+
* ],
|
42 |
+
* 'scope_one' => [
|
43 |
+
* DUPX_S_R_ITEM
|
44 |
+
* DUPX_S_R_ITEM
|
45 |
+
* ]
|
46 |
+
* ],
|
47 |
+
* 20 => [
|
48 |
+
* .
|
49 |
+
* .
|
50 |
+
* .
|
51 |
+
* ]
|
52 |
+
* ]
|
53 |
+
*
|
54 |
+
* @var array
|
55 |
+
*/
|
56 |
+
private $prorityScopeItems = array();
|
57 |
+
|
58 |
+
/**
|
59 |
+
*
|
60 |
+
* @return DUPX_S_R_MANAGER
|
61 |
+
*/
|
62 |
+
public static function getInstance()
|
63 |
+
{
|
64 |
+
if (is_null(self::$instance)) {
|
65 |
+
self::$instance = new self();
|
66 |
+
}
|
67 |
+
|
68 |
+
return self::$instance;
|
69 |
+
}
|
70 |
+
|
71 |
+
private function __construct()
|
72 |
+
{
|
73 |
+
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
*
|
78 |
+
* @return array
|
79 |
+
*/
|
80 |
+
public function getArrayData()
|
81 |
+
{
|
82 |
+
$data = array();
|
83 |
+
|
84 |
+
foreach ($this->items as $item) {
|
85 |
+
$data[] = $item->toArray();
|
86 |
+
}
|
87 |
+
|
88 |
+
return $data;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
*
|
93 |
+
* @param array $json
|
94 |
+
*/
|
95 |
+
public function setFromArrayData($data)
|
96 |
+
{
|
97 |
+
|
98 |
+
foreach ($data as $itemArray) {
|
99 |
+
$new_item = DUPX_S_R_ITEM::getItemFromArray($itemArray);
|
100 |
+
$this->setNewItem($new_item);
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
*
|
106 |
+
* @param string $search
|
107 |
+
* @param string $replace
|
108 |
+
* @param string $type // item type DUPX_S_R_ITEM::[TYPE_STRING|TYPE_URL|TYPE_URL_NORMALIZE_DOMAIN|TYPE_PATH]
|
109 |
+
* @param int $prority // lower first
|
110 |
+
* @param bool|string|string[] $scope // true = global scope | false = never | string signle scope | string[] scope list
|
111 |
+
*
|
112 |
+
* @return boolean|DUPX_S_R_ITEM // false if fail or new DUPX_S_R_ITEM
|
113 |
+
*/
|
114 |
+
public function addItem($search, $replace, $type = DUPX_S_R_ITEM::TYPE_STRING, $prority = 10, $scope = true)
|
115 |
+
{
|
116 |
+
if (strlen((string) $search) == 0) {
|
117 |
+
return false;
|
118 |
+
}
|
119 |
+
|
120 |
+
if (is_bool($scope)) {
|
121 |
+
$scope = $scope ? self::GLOBAL_SCOPE_KEY : '';
|
122 |
+
}
|
123 |
+
DUPX_Log::info(
|
124 |
+
'ADD SEARCH AND REPLACE ITEM'."\n".
|
125 |
+
'Search:"'.$search.'" Replace:"'.$replace.'" Type:"'.$type.'" Prority:"'.$prority.'" Scope:"'.$scope, 2);
|
126 |
+
$new_item = new DUPX_S_R_ITEM($search, $replace, $type, $prority, $scope);
|
127 |
+
|
128 |
+
return $this->setNewItem($new_item);
|
129 |
+
}
|
130 |
+
|
131 |
+
/**
|
132 |
+
*
|
133 |
+
* @param DUPX_S_R_ITEM $new_item
|
134 |
+
*
|
135 |
+
* @return boolean|DUPX_S_R_ITEM // false if fail or new DUPX_S_R_ITEM
|
136 |
+
*/
|
137 |
+
private function setNewItem($new_item)
|
138 |
+
{
|
139 |
+
$this->items[$new_item->getId()] = $new_item;
|
140 |
+
|
141 |
+
// create priority array
|
142 |
+
if (!isset($this->prorityScopeItems[$new_item->prority])) {
|
143 |
+
$this->prorityScopeItems[$new_item->prority] = array();
|
144 |
+
|
145 |
+
// sort by priority
|
146 |
+
ksort($this->prorityScopeItems);
|
147 |
+
}
|
148 |
+
|
149 |
+
// create scope list
|
150 |
+
foreach ($new_item->scope as $scope) {
|
151 |
+
if (!isset($this->prorityScopeItems[$new_item->prority][$scope])) {
|
152 |
+
$this->prorityScopeItems[$new_item->prority][$scope] = array();
|
153 |
+
}
|
154 |
+
$this->prorityScopeItems[$new_item->prority][$scope][] = $new_item;
|
155 |
+
}
|
156 |
+
|
157 |
+
return $new_item;
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* get all search and reaple items by scpoe
|
162 |
+
*
|
163 |
+
* @param null|string $scope if scope is empty get only global scope
|
164 |
+
* @return DUPX_S_R_ITEM[]
|
165 |
+
*/
|
166 |
+
private function getSearchReplaceItems($scope = null, $globalScope = true)
|
167 |
+
{
|
168 |
+
$items_list = array();
|
169 |
+
foreach ($this->prorityScopeItems as $priority => $priority_list) {
|
170 |
+
// get scope list
|
171 |
+
if (!empty($scope) && isset($priority_list[$scope])) {
|
172 |
+
foreach ($priority_list[$scope] as $item) {
|
173 |
+
$items_list[] = $item;
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
// get global scope
|
178 |
+
if ($globalScope && isset($priority_list[self::GLOBAL_SCOPE_KEY])) {
|
179 |
+
foreach ($priority_list[self::GLOBAL_SCOPE_KEY] as $item) {
|
180 |
+
$items_list[] = $item;
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
|
185 |
+
return $items_list;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* get replace list by scope
|
190 |
+
* result
|
191 |
+
* [
|
192 |
+
* ['search' => ...,'replace' => ...]
|
193 |
+
* ['search' => ...,'replace' => ...]
|
194 |
+
* ]
|
195 |
+
*
|
196 |
+
* @param null|string $scope if scope is empty get only global scope
|
197 |
+
* @param bool $unique_search If true it eliminates the double searches leaving the one with lower priority.
|
198 |
+
*
|
199 |
+
* @return array
|
200 |
+
*/
|
201 |
+
public function getSearchReplaceList($scope = null, $unique_search = true, $globalScope = true)
|
202 |
+
{
|
203 |
+
DUPX_Log::info('-- SEARCH LIST -- SCOPE: '.DUPX_Log::varToString($scope), DUPX_Log::LV_DEBUG);
|
204 |
+
|
205 |
+
$items_list = $this->getSearchReplaceItems($scope, $globalScope);
|
206 |
+
DUPX_Log::info('-- SEARCH LIST ITEMS --'."\n".print_r($items_list, true), DUPX_Log::LV_HARD_DEBUG);
|
207 |
+
|
208 |
+
if ($unique_search) {
|
209 |
+
$items_list = self::uniqueSearchListItem($items_list);
|
210 |
+
DUPX_Log::info('-- UNIQUE LIST ITEMS --'."\n".print_r($items_list, true), DUPX_Log::LV_HARD_DEBUG);
|
211 |
+
}
|
212 |
+
$result = array();
|
213 |
+
|
214 |
+
foreach ($items_list as $item) {
|
215 |
+
$result = array_merge($result, $item->getPairsSearchReplace());
|
216 |
+
}
|
217 |
+
|
218 |
+
foreach ($result as $index => $c_sr) {
|
219 |
+
DUPX_Log::info(
|
220 |
+
'SEARCH'.str_pad($index + 1, 3, ' ', STR_PAD_LEFT).":".
|
221 |
+
str_pad(DUPX_Log::varToString($c_sr['search'])." ", 50, '=', STR_PAD_RIGHT).
|
222 |
+
"=> ".
|
223 |
+
DUPX_Log::varToString($c_sr['replace']));
|
224 |
+
}
|
225 |
+
|
226 |
+
return $result;
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* remove duplicated search strings.
|
231 |
+
* Leave the object at lower priority
|
232 |
+
*
|
233 |
+
* @param DUPX_S_R_ITEM[] $list
|
234 |
+
* @return boolean|DUPX_S_R_ITEM[]
|
235 |
+
*/
|
236 |
+
private static function uniqueSearchListItem($list)
|
237 |
+
{
|
238 |
+
$search_strings = array();
|
239 |
+
$result = array();
|
240 |
+
|
241 |
+
if (!is_array($list)) {
|
242 |
+
return false;
|
243 |
+
}
|
244 |
+
|
245 |
+
foreach ($list as $item) {
|
246 |
+
if (!in_array($item->search, $search_strings)) {
|
247 |
+
$result[] = $item;
|
248 |
+
$search_strings[] = $item->search;
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
return $result;
|
253 |
+
}
|
254 |
+
|
255 |
+
private function __clone()
|
256 |
+
{
|
257 |
+
|
258 |
+
}
|
259 |
+
|
260 |
+
private function __wakeup()
|
261 |
+
{
|
262 |
+
|
263 |
+
}
|
264 |
+
}
|
265 |
+
|
266 |
+
/**
|
267 |
+
* search and replace item use in manager to creat the search and replace list.
|
268 |
+
*/
|
269 |
+
class DUPX_S_R_ITEM
|
270 |
+
{
|
271 |
+
private static $uniqueIdCount = 0;
|
272 |
+
|
273 |
+
const TYPE_STRING = 'str';
|
274 |
+
const TYPE_URL = 'url';
|
275 |
+
const TYPE_URL_NORMALIZE_DOMAIN = 'urlnd';
|
276 |
+
const TYPE_PATH = 'path';
|
277 |
+
|
278 |
+
/**
|
279 |
+
*
|
280 |
+
* @var int
|
281 |
+
*/
|
282 |
+
private $id = 0;
|
283 |
+
|
284 |
+
/**
|
285 |
+
*
|
286 |
+
* @var int prority lower first
|
287 |
+
*/
|
288 |
+
public $prority = 10;
|
289 |
+
|
290 |
+
/**
|
291 |
+
*
|
292 |
+
* @var string[] scope list
|
293 |
+
*/
|
294 |
+
public $scope = array();
|
295 |
+
|
296 |
+
/**
|
297 |
+
*
|
298 |
+
* @var string type of string
|
299 |
+
*/
|
300 |
+
public $type = self::TYPE_STRING;
|
301 |
+
|
302 |
+
/**
|
303 |
+
*
|
304 |
+
* @var string search string
|
305 |
+
*/
|
306 |
+
public $search = '';
|
307 |
+
|
308 |
+
/**
|
309 |
+
*
|
310 |
+
* @var string replace string
|
311 |
+
*/
|
312 |
+
public $replace = '';
|
313 |
+
|
314 |
+
/**
|
315 |
+
*
|
316 |
+
* @param string $search
|
317 |
+
* @param string $replace
|
318 |
+
* @param string $type
|
319 |
+
* @param int $prority
|
320 |
+
* @param string|string[] $scope if empty never used
|
321 |
+
*/
|
322 |
+
public function __construct($search, $replace, $type = DUPX_S_R_ITEM::TYPE_STRING, $prority = 10, $scope = array())
|
323 |
+
{
|
324 |
+
if (!is_array($scope)) {
|
325 |
+
$this->scope = empty($scope) ? array() : array((string) $scope);
|
326 |
+
} else {
|
327 |
+
$this->scope = $scope;
|
328 |
+
}
|
329 |
+
$this->prority = (int) $prority;
|
330 |
+
switch ($type) {
|
331 |
+
case DUPX_S_R_ITEM::TYPE_URL:
|
332 |
+
case DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN:
|
333 |
+
$this->search = rtrim($search, '/');
|
334 |
+
$this->replace = rtrim($replace, '/');
|
335 |
+
break;
|
336 |
+
case DUPX_S_R_ITEM::TYPE_PATH:
|
337 |
+
case DUPX_S_R_ITEM::TYPE_STRING:
|
338 |
+
default:
|
339 |
+
$this->search = (string) $search;
|
340 |
+
$this->replace = (string) $replace;
|
341 |
+
break;
|
342 |
+
}
|
343 |
+
$this->type = $type;
|
344 |
+
$this->id = self::$uniqueIdCount;
|
345 |
+
self::$uniqueIdCount ++;
|
346 |
+
}
|
347 |
+
|
348 |
+
public function toArray()
|
349 |
+
{
|
350 |
+
return array(
|
351 |
+
'id' => $this->id,
|
352 |
+
'prority' => $this->prority,
|
353 |
+
'scope' => $this->scope,
|
354 |
+
'type' => $this->type,
|
355 |
+
'search' => $this->search,
|
356 |
+
'replace' => $this->replace
|
357 |
+
);
|
358 |
+
}
|
359 |
+
|
360 |
+
public static function getItemFromArray($array)
|
361 |
+
{
|
362 |
+
$result = new self($array['search'], $array['replace'], $array['type'], $array['prority'], $array['scope']);
|
363 |
+
return $result;
|
364 |
+
}
|
365 |
+
|
366 |
+
/**
|
367 |
+
* return search an replace string
|
368 |
+
*
|
369 |
+
* result
|
370 |
+
* [
|
371 |
+
* ['search' => ...,'replace' => ...]
|
372 |
+
* ['search' => ...,'replace' => ...]
|
373 |
+
* ]
|
374 |
+
*
|
375 |
+
* @return array
|
376 |
+
*/
|
377 |
+
public function getPairsSearchReplace()
|
378 |
+
{
|
379 |
+
switch ($this->type) {
|
380 |
+
case self::TYPE_URL:
|
381 |
+
return self::searchReplaceUrl($this->search, $this->replace);
|
382 |
+
case self::TYPE_URL_NORMALIZE_DOMAIN:
|
383 |
+
return self::searchReplaceUrl($this->search, $this->replace, true, true);
|
384 |
+
case self::TYPE_PATH:
|
385 |
+
return self::searchReplacePath($this->search, $this->replace);
|
386 |
+
case self::TYPE_STRING:
|
387 |
+
default:
|
388 |
+
return self::searchReplaceWithEncodings($this->search, $this->replace);
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Get search and replace strings with encodings
|
394 |
+
* prevents unnecessary substitution like when search and reaplace are the same.
|
395 |
+
*
|
396 |
+
* result
|
397 |
+
* [
|
398 |
+
* ['search' => ...,'replace' => ...]
|
399 |
+
* ['search' => ...,'replace' => ...]
|
400 |
+
* ]
|
401 |
+
*
|
402 |
+
* @param string $search
|
403 |
+
* @param string $replace
|
404 |
+
* @param bool $json add json encode string
|
405 |
+
* @param bool $urlencode add urlencode string
|
406 |
+
*
|
407 |
+
* @return array pairs search and replace
|
408 |
+
*/
|
409 |
+
public static function searchReplaceWithEncodings($search, $replace, $json = true, $urlencode = true)
|
410 |
+
{
|
411 |
+
$result = array();
|
412 |
+
if ($search != $replace) {
|
413 |
+
$result[] = array('search' => $search, 'replace' => $replace);
|
414 |
+
} else {
|
415 |
+
return array();
|
416 |
+
}
|
417 |
+
|
418 |
+
// JSON ENCODE
|
419 |
+
if ($json) {
|
420 |
+
$search_json = str_replace('"', "", json_encode($search));
|
421 |
+
$replace_json = str_replace('"', "", json_encode($replace));
|
422 |
+
|
423 |
+
if ($search != $search_json && $search_json != $replace_json) {
|
424 |
+
$result[] = array('search' => $search_json, 'replace' => $replace_json);
|
425 |
+
}
|
426 |
+
}
|
427 |
+
|
428 |
+
// URL ENCODE
|
429 |
+
if ($urlencode) {
|
430 |
+
$search_urlencode = urlencode($search);
|
431 |
+
$replace_urlencode = urlencode($replace);
|
432 |
+
|
433 |
+
if ($search != $search_urlencode && $search_urlencode != $replace_urlencode) {
|
434 |
+
$result[] = array('search' => $search_urlencode, 'replace' => $replace_urlencode);
|
435 |
+
}
|
436 |
+
}
|
437 |
+
|
438 |
+
return $result;
|
439 |
+
}
|
440 |
+
|
441 |
+
/**
|
442 |
+
* Add replace strings to substitute old url to new url
|
443 |
+
* 1) no protocol old url to no protocol new url (es. //www.hold.url => //www.new.url)
|
444 |
+
* 2) wrong protocol new url to right protocol new url (es. http://www.new.url => https://www.new.url)
|
445 |
+
*
|
446 |
+
* result
|
447 |
+
* [
|
448 |
+
* ['search' => ...,'replace' => ...]
|
449 |
+
* ['search' => ...,'replace' => ...]
|
450 |
+
* ]
|
451 |
+
*
|
452 |
+
* @param string $search_url
|
453 |
+
* @param string $replace_url
|
454 |
+
* @param bool $force_new_protocol if true force http or https protocol (work only if replace url have http or https scheme)
|
455 |
+
*
|
456 |
+
* @return array
|
457 |
+
*/
|
458 |
+
public static function searchReplaceUrl($search_url, $replace_url, $force_new_protocol = true, $normalizeWww = false)
|
459 |
+
{
|
460 |
+
if (($parse_search_url = parse_url($search_url)) !== false && isset($parse_search_url['scheme'])) {
|
461 |
+
$search_url_raw = substr($search_url, strlen($parse_search_url['scheme']) + 1);
|
462 |
+
} else {
|
463 |
+
$search_url_raw = $search_url;
|
464 |
+
}
|
465 |
+
|
466 |
+
if (($parse_replace_url = parse_url($replace_url)) !== false && isset($parse_replace_url['scheme'])) {
|
467 |
+
$replace_url_raw = substr($replace_url, strlen($parse_replace_url['scheme']) + 1);
|
468 |
+
} else {
|
469 |
+
$replace_url_raw = $replace_url;
|
470 |
+
}
|
471 |
+
//SEARCH WITH NO PROTOCOL: RAW "//"
|
472 |
+
$result = self::searchReplaceWithEncodings($search_url_raw, $replace_url_raw);
|
473 |
+
|
474 |
+
// NORMALIZE source www
|
475 |
+
if ($normalizeWww && self::domainCanNormalized($search_url_raw)) {
|
476 |
+
if (self::isWww($search_url_raw)) {
|
477 |
+
$fromDomain = '//'.substr($search_url_raw , strlen('//www.'));
|
478 |
+
} else {
|
479 |
+
$fromDomain = '//www.'.substr($search_url_raw , strlen('//'));
|
480 |
+
}
|
481 |
+
|
482 |
+
// prevent double subsition for subdiv problems.
|
483 |
+
if (strpos($replace_url_raw, $fromDomain) !== 0) {
|
484 |
+
$result = array_merge($result, self::searchReplaceWithEncodings($fromDomain, $replace_url_raw));
|
485 |
+
}
|
486 |
+
}
|
487 |
+
|
488 |
+
// NORMALIZE source protocol
|
489 |
+
if ($force_new_protocol && $parse_replace_url !== false && isset($parse_replace_url['scheme'])) {
|
490 |
+
//FORCE NEW PROTOCOL [HTTP / HTTPS]
|
491 |
+
switch ($parse_replace_url['scheme']) {
|
492 |
+
case 'http':
|
493 |
+
$replace_url_wrong_protocol = 'https:'.$replace_url_raw;
|
494 |
+
break;
|
495 |
+
case 'https':
|
496 |
+
$replace_url_wrong_protocol = 'http:'.$replace_url_raw;
|
497 |
+
break;
|
498 |
+
default:
|
499 |
+
$replace_url_wrong_protocol = '';
|
500 |
+
break;
|
501 |
+
}
|
502 |
+
|
503 |
+
if (!empty($replace_url_wrong_protocol)) {
|
504 |
+
$result = array_merge($result, self::searchReplaceWithEncodings($replace_url_wrong_protocol, $replace_url));
|
505 |
+
}
|
506 |
+
}
|
507 |
+
|
508 |
+
return $result;
|
509 |
+
}
|
510 |
+
|
511 |
+
/**
|
512 |
+
* result
|
513 |
+
* [
|
514 |
+
* ['search' => ...,'replace' => ...]
|
515 |
+
* ['search' => ...,'replace' => ...]
|
516 |
+
* ]
|
517 |
+
*
|
518 |
+
* @param string $search_path
|
519 |
+
* @param string $replace_path
|
520 |
+
*
|
521 |
+
* @return array
|
522 |
+
*/
|
523 |
+
public static function searchReplacePath($search_path, $replace_path)
|
524 |
+
{
|
525 |
+
$result = self::searchReplaceWithEncodings($search_path, $replace_path);
|
526 |
+
|
527 |
+
$search_path_unsetSafe = rtrim(DUPX_U::unsetSafePath($search_path), '\\');
|
528 |
+
$replace_path_unsetSafe = rtrim($replace_path, '/');
|
529 |
+
$result = array_merge($result, self::searchReplaceWithEncodings($search_path_unsetSafe, $replace_path_unsetSafe));
|
530 |
+
|
531 |
+
return $result;
|
532 |
+
}
|
533 |
+
|
534 |
+
/**
|
535 |
+
* get unique item id
|
536 |
+
*
|
537 |
+
* @return int
|
538 |
+
*/
|
539 |
+
public function getId()
|
540 |
+
{
|
541 |
+
return $this->id;
|
542 |
+
}
|
543 |
+
|
544 |
+
/**
|
545 |
+
* @param $url string The URL whichs domain you want to get
|
546 |
+
* @return string The domain part of the given URL
|
547 |
+
* www.myurl.co.uk => myurl.co.uk
|
548 |
+
* www.google.com => google.com
|
549 |
+
* my.test.myurl.co.uk => myurl.co.uk
|
550 |
+
* www.myurl.localweb => myurl.localweb
|
551 |
+
*
|
552 |
+
*/
|
553 |
+
public static function getDomain($url)
|
554 |
+
{
|
555 |
+
$pieces = parse_url($url);
|
556 |
+
$domain = isset($pieces['host']) ? $pieces['host'] : '';
|
557 |
+
$regs = null;
|
558 |
+
if (strpos($domain, ".") !== false) {
|
559 |
+
if (preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $domain, $regs)) {
|
560 |
+
return $regs['domain'];
|
561 |
+
} else {
|
562 |
+
$exDomain = explode('.', $domain);
|
563 |
+
return implode('.', array_slice($exDomain, -2, 2));
|
564 |
+
}
|
565 |
+
} else {
|
566 |
+
return $domain;
|
567 |
+
}
|
568 |
+
}
|
569 |
+
|
570 |
+
public static function domainCanNormalized($url)
|
571 |
+
{
|
572 |
+
$pieces = parse_url($url);
|
573 |
+
|
574 |
+
if (!isset($pieces['host'])) {
|
575 |
+
return false;
|
576 |
+
}
|
577 |
+
|
578 |
+
if (strpos($pieces['host'], ".") === false) {
|
579 |
+
return false;
|
580 |
+
}
|
581 |
+
|
582 |
+
$dLevels = explode('.', $pieces['host']);
|
583 |
+
if ($dLevels[0] == 'www') {
|
584 |
+
return true;
|
585 |
+
}
|
586 |
+
|
587 |
+
switch (count($dLevels)) {
|
588 |
+
case 1:
|
589 |
+
return false;
|
590 |
+
case 2:
|
591 |
+
return true;
|
592 |
+
case 3:
|
593 |
+
if (preg_match('/(?P<domain>[a-z0-9][a-z0-9\-]{1,63}\.[a-z\.]{2,6})$/i', $pieces['host'], $regs)) {
|
594 |
+
return $regs['domain'] == $pieces['host'];
|
595 |
+
}
|
596 |
+
return false;
|
597 |
+
default:
|
598 |
+
return false;
|
599 |
+
}
|
600 |
+
}
|
601 |
+
|
602 |
+
public static function isWww($url)
|
603 |
+
{
|
604 |
+
$pieces = parse_url($url);
|
605 |
+
if (!isset($pieces['host'])) {
|
606 |
+
return false;
|
607 |
+
} else {
|
608 |
+
return strpos($pieces['host'], 'www.') === 0;
|
609 |
+
}
|
610 |
+
}
|
611 |
+
}
|
installer/dup-installer/ctrls/ctrl.base.php
CHANGED
@@ -13,9 +13,8 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
13 |
//Enum used to define the various test statues
|
14 |
final class DUPX_CTRL_Status
|
15 |
{
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
}
|
20 |
|
21 |
/**
|
@@ -23,10 +22,10 @@ final class DUPX_CTRL_Status
|
|
23 |
*/
|
24 |
class DUPX_CTRL_Report
|
25 |
{
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
|
31 |
}
|
32 |
|
@@ -35,39 +34,41 @@ class DUPX_CTRL_Report
|
|
35 |
*/
|
36 |
class DUPX_CTRL_Out
|
37 |
{
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
private $timeEnd;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Init this instance of the object
|
46 |
-
*/
|
47 |
-
public function __construct()
|
48 |
-
{
|
49 |
-
$this->report = new DUPX_CTRL_Report();
|
50 |
-
$this->payload = null;
|
51 |
-
$this->startProcessTime();
|
52 |
-
}
|
53 |
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
return $this->report->runTime;
|
64 |
-
}
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
|
|
|
|
|
|
|
73 |
}
|
13 |
//Enum used to define the various test statues
|
14 |
final class DUPX_CTRL_Status
|
15 |
{
|
16 |
+
const FAILED = 0;
|
17 |
+
const SUCCESS = 1;
|
|
|
18 |
}
|
19 |
|
20 |
/**
|
22 |
*/
|
23 |
class DUPX_CTRL_Report
|
24 |
{
|
25 |
+
//Properties
|
26 |
+
public $runTime;
|
27 |
+
public $outputType = 'JSON';
|
28 |
+
public $status;
|
29 |
|
30 |
}
|
31 |
|
34 |
*/
|
35 |
class DUPX_CTRL_Out
|
36 |
{
|
37 |
+
public $report = null;
|
38 |
+
public $payload = null;
|
39 |
+
private $timeStart;
|
40 |
+
private $timeEnd;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
+
/**
|
43 |
+
* Init this instance of the object
|
44 |
+
*/
|
45 |
+
public function __construct()
|
46 |
+
{
|
47 |
+
$this->report = new DUPX_CTRL_Report();
|
48 |
+
$this->payload = null;
|
49 |
+
$this->startProcessTime();
|
50 |
+
}
|
51 |
|
52 |
+
public function startProcessTime()
|
53 |
+
{
|
54 |
+
$this->timeStart = $this->microtimeFloat();
|
55 |
+
}
|
|
|
|
|
56 |
|
57 |
+
public function getProcessTime()
|
58 |
+
{
|
59 |
+
$this->timeEnd = $this->microtimeFloat();
|
60 |
+
$this->report->runTime = $this->timeEnd - $this->timeStart;
|
61 |
+
return $this->report->runTime;
|
62 |
+
}
|
63 |
|
64 |
+
private function microtimeFloat()
|
65 |
+
{
|
66 |
+
list($usec, $sec) = explode(" ", microtime());
|
67 |
+
return ((float) $usec + (float) $sec);
|
68 |
+
}
|
69 |
+
}
|
70 |
|
71 |
+
class DUPX_CTRL
|
72 |
+
{
|
73 |
+
const NAME_MAX_SERIALIZE_STRLEN_IN_M = 'mstrlim';
|
74 |
}
|
installer/dup-installer/ctrls/ctrl.s1.php
CHANGED
@@ -5,12 +5,10 @@ defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
5 |
/* @var $GLOBALS['DUPX_AC'] DUPX_ArchiveConfig */
|
6 |
|
7 |
//OPTIONS
|
8 |
-
$base_file_perms_value = (isset($_POST['file_perms_value'])) ? $_POST['file_perms_value'] : 'not set';
|
9 |
-
$base_dir_perms_value = (isset($_POST['dir_perms_value'])) ? $_POST['dir_perms_value'] : 'not set';
|
10 |
$_POST['set_file_perms'] = (isset($_POST['set_file_perms'])) ? 1 : 0;
|
11 |
$_POST['set_dir_perms'] = (isset($_POST['set_dir_perms'])) ? 1 : 0;
|
12 |
-
$_POST['file_perms_value'] = (isset($_POST['file_perms_value'])) ?
|
13 |
-
$_POST['dir_perms_value'] = (isset($_POST['dir_perms_value'])) ?
|
14 |
$_POST['zip_filetime'] = (isset($_POST['zip_filetime'])) ? $_POST['zip_filetime'] : 'current';
|
15 |
$_POST['config_mode'] = (isset($_POST['config_mode'])) ? $_POST['config_mode'] : 'NEW';
|
16 |
$_POST['archive_engine'] = (isset($_POST['archive_engine'])) ? $_POST['archive_engine'] : 'manual';
|
@@ -81,52 +79,58 @@ DUPX_Log::info("* VERSION: {$GLOBALS['DUPX_AC']->version_dup}");
|
|
81 |
DUPX_Log::info('* NOTICE: Do NOT post to public sites or forums!!');
|
82 |
DUPX_Log::info("********************************************************************************");
|
83 |
|
84 |
-
$colSize
|
85 |
-
$
|
86 |
-
$
|
87 |
-
|
88 |
-
str_pad(str_pad('
|
89 |
-
str_pad('
|
90 |
-
str_pad('
|
91 |
-
str_pad('
|
92 |
-
str_pad('
|
93 |
-
str_pad('DB
|
94 |
-
str_pad('DB
|
95 |
-
str_pad('DB
|
|
|
96 |
"********************************************************************************";
|
97 |
DUPX_Log::info($log);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
|
99 |
-
DUPX_Log::info("
|
100 |
-
DUPX_Log::info("
|
101 |
-
DUPX_Log::info(
|
102 |
-
DUPX_Log::info(
|
103 |
-
DUPX_Log::info(
|
104 |
-
DUPX_Log::info(
|
105 |
-
DUPX_Log::info(
|
106 |
-
DUPX_Log::info(
|
107 |
-
DUPX_Log::info(
|
|
|
|
|
|
|
108 |
|
109 |
$log = "--------------------------------------\n";
|
110 |
$log .= "POST DATA\n";
|
111 |
$log .= "--------------------------------------\n";
|
112 |
$log .= print_r($POST_LOG, true);
|
113 |
-
DUPX_Log::info($log,
|
114 |
-
|
115 |
-
|
116 |
-
$log = "--------------------------------------\n";
|
117 |
-
$log .= "PRE-EXTRACT-CHECKS\n";
|
118 |
-
$log .= "--------------------------------------";
|
119 |
-
DUPX_Log::info($log);
|
120 |
-
DUPX_ServerConfig::beforeExtractionSetup();
|
121 |
-
|
122 |
|
123 |
-
$log = "--------------------------------------\n";
|
124 |
$log .= "ARCHIVE SETUP\n";
|
125 |
$log .= "--------------------------------------\n";
|
126 |
-
$log .=
|
127 |
-
$log .=
|
128 |
-
|
129 |
|
|
|
|
|
130 |
|
131 |
$target = $root_path;
|
132 |
|
@@ -142,9 +146,9 @@ switch ($post_archive_engine) {
|
|
142 |
//-----------------------
|
143 |
//SHELL EXEC
|
144 |
case 'shellexec_unzip':
|
145 |
-
|
146 |
$shell_exec_path = DUPX_Server::get_unzip_filepath();
|
147 |
-
|
148 |
|
149 |
$command = escapeshellcmd($shell_exec_path)." -o -qq ".escapeshellarg($archive_path)." -d ".escapeshellarg($target)." 2>&1";
|
150 |
if ($_POST['zip_filetime'] == 'original') {
|
@@ -165,7 +169,7 @@ switch ($post_archive_engine) {
|
|
165 |
//-----------------------
|
166 |
//ZIP-ARCHIVE
|
167 |
case 'ziparchive':
|
168 |
-
DUPX_Log::info("
|
169 |
|
170 |
if (!class_exists('ZipArchive')) {
|
171 |
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.");
|
@@ -193,15 +197,13 @@ switch ($post_archive_engine) {
|
|
193 |
|
194 |
for($i = 0; $i < $zip->numFiles; $i++) {
|
195 |
$extract_filename = $zip->getNameIndex($i);
|
196 |
-
|
197 |
-
// skip dup-installer folder. Alrady extracted in bootstrap
|
198 |
-
if (strpos($extract_filename , $dupInstallerZipPath) === 0) {
|
199 |
-
continue;
|
200 |
-
}
|
201 |
|
202 |
-
// skip
|
203 |
-
if (
|
204 |
-
|
|
|
|
|
|
|
205 |
continue;
|
206 |
}
|
207 |
|
@@ -236,7 +238,7 @@ switch ($post_archive_engine) {
|
|
236 |
'sections' => array('files'),
|
237 |
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
|
238 |
} else {
|
239 |
-
DUPX_Log::info("DONE: "
|
240 |
}
|
241 |
} catch (Exception $ex) {
|
242 |
if (DupLiteSnapLibUtilWp::isWpCore($extract_filename, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
|
@@ -365,40 +367,41 @@ if ($_POST['set_file_perms'] || $_POST['set_dir_perms']) {
|
|
365 |
function getChildren()
|
366 |
{
|
367 |
try {
|
368 |
-
return new IgnorantRecursiveDirectoryIterator($this->getPathname());
|
369 |
} catch (UnexpectedValueException $e) {
|
370 |
return new RecursiveArrayIterator(array());
|
371 |
}
|
372 |
}
|
373 |
}
|
374 |
|
375 |
-
|
376 |
-
DUPX_Log::info(" -DIRS: '{$base_dir_perms_value}'");
|
377 |
-
DUPX_Log::info(" -FILES: '{$base_file_perms_value}'");
|
378 |
-
$set_file_perms = $_POST['set_file_perms'];
|
379 |
$set_dir_perms = $_POST['set_dir_perms'];
|
380 |
$set_file_mtime = ($_POST['zip_filetime'] == 'current');
|
381 |
$file_perms_value = $_POST['file_perms_value'] ? $_POST['file_perms_value'] : 0755;
|
382 |
$dir_perms_value = $_POST['dir_perms_value'] ? $_POST['dir_perms_value'] : 0644;
|
383 |
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
if ($set_file_perms && is_file($name)) {
|
388 |
|
389 |
-
|
390 |
-
DUPX_Log::info("Permissions setting on file '{$name}' failed");
|
391 |
-
}
|
392 |
-
} else if ($set_dir_perms && is_dir($name)) {
|
393 |
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
402 |
} else {
|
403 |
DUPX_Log::info("\nPERMISSION UPDATES: None Applied");
|
404 |
}
|
5 |
/* @var $GLOBALS['DUPX_AC'] DUPX_ArchiveConfig */
|
6 |
|
7 |
//OPTIONS
|
|
|
|
|
8 |
$_POST['set_file_perms'] = (isset($_POST['set_file_perms'])) ? 1 : 0;
|
9 |
$_POST['set_dir_perms'] = (isset($_POST['set_dir_perms'])) ? 1 : 0;
|
10 |
+
$_POST['file_perms_value'] = (isset($_POST['file_perms_value'])) ? DUPX_U::sanitize_text_field($_POST['file_perms_value']) : 0755;
|
11 |
+
$_POST['dir_perms_value'] = (isset($_POST['dir_perms_value'])) ? DUPX_U::sanitize_text_field($_POST['dir_perms_value']) : 0644;
|
12 |
$_POST['zip_filetime'] = (isset($_POST['zip_filetime'])) ? $_POST['zip_filetime'] : 'current';
|
13 |
$_POST['config_mode'] = (isset($_POST['config_mode'])) ? $_POST['config_mode'] : 'NEW';
|
14 |
$_POST['archive_engine'] = (isset($_POST['archive_engine'])) ? $_POST['archive_engine'] : 'manual';
|
79 |
DUPX_Log::info('* NOTICE: Do NOT post to public sites or forums!!');
|
80 |
DUPX_Log::info("********************************************************************************");
|
81 |
|
82 |
+
$colSize = 60;
|
83 |
+
$labelPadSize = 20;
|
84 |
+
$os = defined('PHP_OS') ? PHP_OS : 'unknown';
|
85 |
+
$log = str_pad(str_pad('PACKAGE INFO', $labelPadSize, '_', STR_PAD_RIGHT).' '.'CURRENT SERVER', $colSize, ' ', STR_PAD_RIGHT).'|'.'ORIGINAL SERVER'."\n".
|
86 |
+
str_pad(str_pad('PHP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_php, $colSize, ' ', STR_PAD_RIGHT).'|'.phpversion()."\n".
|
87 |
+
str_pad(str_pad('OS', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_os, $colSize, ' ', STR_PAD_RIGHT).'|'.$os."\n".
|
88 |
+
str_pad('CREATED', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->created."\n".
|
89 |
+
str_pad('WP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_wp."\n".
|
90 |
+
str_pad('DUP VERSION', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_dup."\n".
|
91 |
+
str_pad('DB', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->version_db."\n".
|
92 |
+
str_pad('DB TABLES', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesFinalCount."\n".
|
93 |
+
str_pad('DB ROWS', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesRowCount."\n".
|
94 |
+
str_pad('DB FILE SIZE', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['DUPX_AC']->dbInfo->tablesSizeOnDisk."\n".
|
95 |
"********************************************************************************";
|
96 |
DUPX_Log::info($log);
|
97 |
+
DUPX_Log::info("SERVER INFO");
|
98 |
+
DUPX_Log::info(str_pad('PHP', $labelPadSize, '_', STR_PAD_RIGHT).': '.phpversion().' | SAPI: '.php_sapi_name());
|
99 |
+
DUPX_Log::info(str_pad('PHP MEMORY', $labelPadSize, '_', STR_PAD_RIGHT).': '.$GLOBALS['PHP_MEMORY_LIMIT'].' | SUHOSIN: '.$GLOBALS['PHP_SUHOSIN_ON']);
|
100 |
+
DUPX_Log::info(str_pad('SERVER', $labelPadSize, '_', STR_PAD_RIGHT).': '.$_SERVER['SERVER_SOFTWARE']);
|
101 |
+
DUPX_Log::info(str_pad('DOC ROOT', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($root_path));
|
102 |
+
DUPX_Log::info(str_pad('DOC ROOT 755', $labelPadSize, '_', STR_PAD_RIGHT).': '.var_export($GLOBALS['CHOWN_ROOT_PATH'], true));
|
103 |
+
DUPX_Log::info(str_pad('LOG FILE 644', $labelPadSize, '_', STR_PAD_RIGHT).': '.var_export($GLOBALS['CHOWN_LOG_PATH'], true));
|
104 |
+
DUPX_Log::info(str_pad('REQUEST URL', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($GLOBALS['URL_PATH']));
|
105 |
|
106 |
+
DUPX_Log::info("********************************************************************************");
|
107 |
+
DUPX_Log::info("USER INPUTS");
|
108 |
+
DUPX_Log::info(str_pad('ARCHIVE ENGINE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['archive_engine']));
|
109 |
+
DUPX_Log::info(str_pad('SET DIR PERMS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['set_dir_perms']));
|
110 |
+
DUPX_Log::info(str_pad('DIR PERMS VALUE', $labelPadSize, '_', STR_PAD_RIGHT).': '.decoct($_POST['dir_perms_value']));
|
111 |
+
DUPX_Log::info(str_pad('SET FILE PERMS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['set_file_perms'] ));
|
112 |
+
DUPX_Log::info(str_pad('FILE PERMS VALUE', $labelPadSize, '_', STR_PAD_RIGHT).': '.decoct($_POST['file_perms_value']));
|
113 |
+
DUPX_Log::info(str_pad('SAFE MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['exe_safe_mode']));
|
114 |
+
DUPX_Log::info(str_pad('LOGGING', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['logging']));
|
115 |
+
DUPX_Log::info(str_pad('CONFIG MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['config_mode']));
|
116 |
+
DUPX_Log::info(str_pad('FILE TIME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['zip_filetime']));
|
117 |
+
DUPX_Log::info("********************************************************************************\n");
|
118 |
|
119 |
$log = "--------------------------------------\n";
|
120 |
$log .= "POST DATA\n";
|
121 |
$log .= "--------------------------------------\n";
|
122 |
$log .= print_r($POST_LOG, true);
|
123 |
+
DUPX_Log::info($log, DUPX_Log::LV_DEBUG);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
|
125 |
+
$log = "\n--------------------------------------\n";
|
126 |
$log .= "ARCHIVE SETUP\n";
|
127 |
$log .= "--------------------------------------\n";
|
128 |
+
$log .= str_pad('NAME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($GLOBALS['FW_PACKAGE_NAME'])."\n";
|
129 |
+
$log .= str_pad('SIZE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_U::readableByteSize(@filesize($GLOBALS['FW_PACKAGE_PATH']));
|
130 |
+
DUPX_Log::info($log."\n", DUPX_Log::LV_DEFAULT, true);
|
131 |
|
132 |
+
DUPX_Log::info('PRE-EXTRACT-CHECKS');
|
133 |
+
DUPX_ServerConfig::beforeExtractionSetup();
|
134 |
|
135 |
$target = $root_path;
|
136 |
|
146 |
//-----------------------
|
147 |
//SHELL EXEC
|
148 |
case 'shellexec_unzip':
|
149 |
+
DUPX_Log::info("\n\nSTART ZIP FILE EXTRACTION SHELLEXEC >>> ");
|
150 |
$shell_exec_path = DUPX_Server::get_unzip_filepath();
|
151 |
+
|
152 |
|
153 |
$command = escapeshellcmd($shell_exec_path)." -o -qq ".escapeshellarg($archive_path)." -d ".escapeshellarg($target)." 2>&1";
|
154 |
if ($_POST['zip_filetime'] == 'original') {
|
169 |
//-----------------------
|
170 |
//ZIP-ARCHIVE
|
171 |
case 'ziparchive':
|
172 |
+
DUPX_Log::info("\n\nSTART ZIP FILE EXTRACTION STANDARD >>> ");
|
173 |
|
174 |
if (!class_exists('ZipArchive')) {
|
175 |
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.");
|
197 |
|
198 |
for($i = 0; $i < $zip->numFiles; $i++) {
|
199 |
$extract_filename = $zip->getNameIndex($i);
|
|
|
|
|
|
|
|
|
|
|
200 |
|
201 |
+
// skip dup-installer folder. Alrady extracted in bootstrap
|
202 |
+
if (
|
203 |
+
(strpos($extract_filename, $dupInstallerZipPath) === 0) ||
|
204 |
+
(!empty($dupInstallerFolder) && strpos($extract_filename , $dupInstallerFolder) !== 0)
|
205 |
+
) {
|
206 |
+
DUPX_Log::info("SKIPPING NOT IN ZIPATH:\"".DUPX_Log::varToString($extract_filename)."\"" , DUPX_Log::LV_DETAILED);
|
207 |
continue;
|
208 |
}
|
209 |
|
238 |
'sections' => array('files'),
|
239 |
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager);
|
240 |
} else {
|
241 |
+
DUPX_Log::info("FILE EXTRACTION DONE: ".DUPX_Log::varToString($extract_filename), DUPX_Log::LV_HARD_DEBUG);
|
242 |
}
|
243 |
} catch (Exception $ex) {
|
244 |
if (DupLiteSnapLibUtilWp::isWpCore($extract_filename, DupLiteSnapLibUtilWp::PATH_RELATIVE)) {
|
367 |
function getChildren()
|
368 |
{
|
369 |
try {
|
370 |
+
return new IgnorantRecursiveDirectoryIterator($this->getPathname(), RecursiveDirectoryIterator::SKIP_DOTS);
|
371 |
} catch (UnexpectedValueException $e) {
|
372 |
return new RecursiveArrayIterator(array());
|
373 |
}
|
374 |
}
|
375 |
}
|
376 |
|
377 |
+
$set_file_perms = $_POST['set_file_perms'];
|
|
|
|
|
|
|
378 |
$set_dir_perms = $_POST['set_dir_perms'];
|
379 |
$set_file_mtime = ($_POST['zip_filetime'] == 'current');
|
380 |
$file_perms_value = $_POST['file_perms_value'] ? $_POST['file_perms_value'] : 0755;
|
381 |
$dir_perms_value = $_POST['dir_perms_value'] ? $_POST['dir_perms_value'] : 0644;
|
382 |
|
383 |
+
DUPX_Log::info("PERMISSION UPDATES:");
|
384 |
+
DUPX_Log::info(" -DIRS: '{$dir_perms_value}'");
|
385 |
+
DUPX_Log::info(" -FILES: '{$file_perms_value}'");
|
|
|
386 |
|
387 |
+
$objects = new RecursiveIteratorIterator(new IgnorantRecursiveDirectoryIterator($root_path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST);
|
|
|
|
|
|
|
388 |
|
389 |
+
foreach ($objects as $name => $object) {
|
390 |
+
if ($set_file_perms && is_file($name)) {
|
391 |
+
DUPX_Log::info("SET PERMISSION: ".DUPX_Log::varToString($name).'[MODE:'.$file_perms_value.']', DUPX_Log::LV_HARD_DEBUG);
|
392 |
+
if (!DupLiteSnapLibIOU::chmod($name, $file_perms_value)) {
|
393 |
+
DUPX_Log::info("Permissions setting on file '{$name}' failed");
|
394 |
+
}
|
395 |
+
} else if ($set_dir_perms && is_dir($name)) {
|
396 |
+
DUPX_Log::info("SET PERMISSION: ".DUPX_Log::varToString($name).'[MODE:'.$dir_perms_value.']', DUPX_Log::LV_HARD_DEBUG);
|
397 |
+
if (!DupLiteSnapLibIOU::chmod($name, $dir_perms_value)) {
|
398 |
+
DUPX_Log::info("Permissions setting on directory '{$name}' failed");
|
399 |
+
}
|
400 |
+
}
|
401 |
+
if ($set_file_mtime) {
|
402 |
+
@touch($name);
|
403 |
+
}
|
404 |
+
}
|
405 |
} else {
|
406 |
DUPX_Log::info("\nPERMISSION UPDATES: None Applied");
|
407 |
}
|
installer/dup-installer/ctrls/ctrl.s2.base.php
CHANGED
@@ -102,6 +102,25 @@ if($not_yet_logged){
|
|
102 |
DUPX_Log::info('* STEP-2 START @ '.@date('h:i:s'));
|
103 |
DUPX_Log::info('* NOTICE: Do NOT post to public sites or forums!!');
|
104 |
DUPX_Log::info("********************************************************************************");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
$POST_LOG = $_POST;
|
106 |
unset($POST_LOG['dbpass']);
|
107 |
ksort($POST_LOG);
|
@@ -109,7 +128,8 @@ if($not_yet_logged){
|
|
109 |
$log .= "POST DATA\n";
|
110 |
$log .= "--------------------------------------\n";
|
111 |
$log .= print_r($POST_LOG, true);
|
112 |
-
DUPX_Log::info($log,
|
|
|
113 |
}
|
114 |
|
115 |
|
102 |
DUPX_Log::info('* STEP-2 START @ '.@date('h:i:s'));
|
103 |
DUPX_Log::info('* NOTICE: Do NOT post to public sites or forums!!');
|
104 |
DUPX_Log::info("********************************************************************************");
|
105 |
+
|
106 |
+
$labelPadSize = 20;
|
107 |
+
DUPX_Log::info("USER INPUTS");
|
108 |
+
DUPX_Log::info(str_pad('VIEW MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['view_mode']));
|
109 |
+
DUPX_Log::info(str_pad('DB ACTION', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbaction']));
|
110 |
+
DUPX_Log::info(str_pad('DB HOST', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**'));
|
111 |
+
DUPX_Log::info(str_pad('DB NAME', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**'));
|
112 |
+
DUPX_Log::info(str_pad('DB PASS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**'));
|
113 |
+
DUPX_Log::info(str_pad('DB PORT', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString('**OBSCURED**'));
|
114 |
+
DUPX_Log::info(str_pad('NON-BREAKING SPACES', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbnbsp']));
|
115 |
+
DUPX_Log::info(str_pad('MYSQL MODE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbmysqlmode']));
|
116 |
+
DUPX_Log::info(str_pad('MYSQL MODE OPTS', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbmysqlmode_opts']));
|
117 |
+
DUPX_Log::info(str_pad('CHARSET', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbcharset']));
|
118 |
+
DUPX_Log::info(str_pad('COLLATE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbcollate']));
|
119 |
+
DUPX_Log::info(str_pad('COLLATE FB', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbcollatefb']));
|
120 |
+
DUPX_Log::info(str_pad('VIEW CREATION', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbobj_views']));
|
121 |
+
DUPX_Log::info(str_pad('STORED PROCEDURE', $labelPadSize, '_', STR_PAD_RIGHT).': '.DUPX_Log::varToString($_POST['dbobj_procs']));
|
122 |
+
DUPX_Log::info("********************************************************************************\n");
|
123 |
+
|
124 |
$POST_LOG = $_POST;
|
125 |
unset($POST_LOG['dbpass']);
|
126 |
ksort($POST_LOG);
|
128 |
$log .= "POST DATA\n";
|
129 |
$log .= "--------------------------------------\n";
|
130 |
$log .= print_r($POST_LOG, true);
|
131 |
+
DUPX_Log::info($log, DUPX_Log::LV_DEBUG, true);
|
132 |
+
|
133 |
}
|
134 |
|
135 |
|
installer/dup-installer/ctrls/ctrl.s3.php
CHANGED
@@ -1,671 +1,50 @@
|
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
-
/** IDE HELPERS */
|
4 |
-
/* @var $GLOBALS['DUPX_AC'] DUPX_ArchiveConfig */
|
5 |
|
6 |
//-- START OF ACTION STEP 3: Update the database
|
7 |
require_once($GLOBALS['DUPX_INIT'].'/classes/config/class.archive.config.php');
|
8 |
require_once($GLOBALS['DUPX_INIT'].'/lib/config/class.wp.config.tranformer.php');
|
9 |
require_once($GLOBALS['DUPX_INIT'].'/lib/config/class.wp.config.tranformer.src.php');
|
|
|
|
|
10 |
|
11 |
/** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
|
12 |
cause errors in the JSON data Here we hide the status so warning level is reset at it at the end */
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
$_POST['postguid'] = isset($_POST['postguid']) && $_POST['postguid'] == 1 ? 1 : 0;
|
20 |
-
$_POST['fullsearch'] = isset($_POST['fullsearch']) && $_POST['fullsearch'] == 1 ? 1 : 0;
|
21 |
-
$_POST['path_old'] = isset($_POST['path_old']) ? trim($_POST['path_old']) : null;
|
22 |
-
$_POST['path_new'] = isset($_POST['path_new']) ? trim($_POST['path_new']) : null;
|
23 |
-
$_POST['siteurl'] = isset($_POST['siteurl']) ? rtrim(trim($_POST['siteurl']), '/') : null;
|
24 |
-
$_POST['tables'] = isset($_POST['tables']) && is_array($_POST['tables']) ? array_map('stripcslashes', $_POST['tables']) : array();
|
25 |
-
|
26 |
-
if (isset($_POST['url_old'])) {
|
27 |
-
$post_url_old = DUPX_U::sanitize_text_field($_POST['url_old']);
|
28 |
-
$_POST['url_old'] = trim($post_url_old);
|
29 |
-
} else {
|
30 |
-
$_POST['url_old'] = null;
|
31 |
-
}
|
32 |
-
|
33 |
-
if (isset($_POST['url_new'])) {
|
34 |
-
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
35 |
-
$_POST['url_new'] = isset($_POST['url_new']) ? rtrim(trim($post_url_new), '/') : null;
|
36 |
-
} else {
|
37 |
-
$_POST['url_new'] = null;
|
38 |
-
}
|
39 |
-
|
40 |
-
$_POST['ssl_admin'] = isset($_POST['ssl_admin']) ? true : false;
|
41 |
-
$_POST['exe_safe_mode'] = isset($_POST['exe_safe_mode']) ? $_POST['exe_safe_mode'] : 0;
|
42 |
-
$_POST['config_mode'] = (isset($_POST['config_mode'])) ? $_POST['config_mode'] : 'NEW';
|
43 |
-
$replace_mail = filter_input(INPUT_POST, 'search_replace_email_domain', FILTER_VALIDATE_BOOLEAN);
|
44 |
-
|
45 |
-
|
46 |
-
//MYSQL CONNECTION
|
47 |
-
$dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname']);
|
48 |
-
$dbConnError = (mysqli_connect_error()) ? 'Error: '.mysqli_connect_error() : 'Unable to Connect';
|
49 |
-
|
50 |
-
if (!$dbh) {
|
51 |
-
$msg = "Unable to connect with the following parameters: <br/> <b>HOST:</b> {$_POST['dbhost']}<br/> <b>DATABASE:</b> {$_POST['dbname']}<br/>";
|
52 |
-
$msg .= "<b>Connection Error:</b> ".htmlentities($dbConnError);
|
53 |
-
DUPX_Log::error($msg);
|
54 |
-
}
|
55 |
-
|
56 |
-
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
57 |
-
|
58 |
-
$charset_server = @mysqli_character_set_name($dbh);
|
59 |
-
@mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME']));
|
60 |
-
DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);
|
61 |
-
$charset_client = @mysqli_character_set_name($dbh);
|
62 |
-
|
63 |
-
//LOGGING
|
64 |
-
$date = @date('h:i:s');
|
65 |
-
$log = <<<LOG
|
66 |
-
\n\n
|
67 |
-
********************************************************************************
|
68 |
-
DUPLICATOR-LITE INSTALL-LOG
|
69 |
-
STEP-3 START @ {$date}
|
70 |
-
NOTICE: Do NOT post to public sites or forums
|
71 |
-
********************************************************************************
|
72 |
-
CHARSET SERVER:\t{$charset_server}
|
73 |
-
CHARSET CLIENT:\t{$charset_client}\n
|
74 |
-
LOG;
|
75 |
-
DUPX_Log::info($log);
|
76 |
-
|
77 |
-
$POST_LOG = $_POST;
|
78 |
-
unset($POST_LOG['tables']);
|
79 |
-
unset($POST_LOG['plugins']);
|
80 |
-
unset($POST_LOG['dbpass']);
|
81 |
-
ksort($POST_LOG);
|
82 |
-
|
83 |
-
//Detailed logging
|
84 |
-
$log = "--------------------------------------\n";
|
85 |
-
$log .= "POST DATA\n";
|
86 |
-
$log .= "--------------------------------------\n";
|
87 |
-
$log .= print_r($POST_LOG, true);
|
88 |
-
$log .= "--------------------------------------\n";
|
89 |
-
$log .= "TABLES TO SCAN\n";
|
90 |
-
$log .= "--------------------------------------\n";
|
91 |
-
$log .= (isset($_POST['tables']) && count($_POST['tables']) > 0) ? print_r($_POST['tables'], true) : 'No tables selected to update';
|
92 |
-
$log .= "--------------------------------------\n";
|
93 |
-
$log .= "KEEP PLUGINS ACTIVE\n";
|
94 |
-
$log .= "--------------------------------------\n";
|
95 |
-
$log .= (isset($_POST['plugins']) && count($_POST['plugins']) > 0) ? print_r($_POST['plugins'], true) : 'No plugins selected for activation';
|
96 |
-
DUPX_Log::info($log, 2);
|
97 |
-
|
98 |
-
|
99 |
-
//===============================================
|
100 |
-
//UPDATE ENGINE
|
101 |
-
//===============================================
|
102 |
-
$log = "--------------------------------------\n";
|
103 |
-
$log .= "SERIALIZER ENGINE\n";
|
104 |
-
$log .= "[*] scan every column\n";
|
105 |
-
$log .= "[~] scan only text columns\n";
|
106 |
-
$log .= "[^] no searchable columns\n";
|
107 |
-
$log .= "--------------------------------------";
|
108 |
-
DUPX_Log::info($log);
|
109 |
-
|
110 |
-
//===============================================
|
111 |
-
// INIZIALIZE WP_CONFIG TRANSFORMER
|
112 |
-
//===============================================
|
113 |
-
$root_path = $GLOBALS['DUPX_ROOT'];
|
114 |
-
$wpconfig_ark_path = DUPX_ServerConfig::getWpconfigArkPath();
|
115 |
-
DUPX_ServerConfig::copyOriginalConfigFiles();
|
116 |
-
|
117 |
-
$config_transformer = null;
|
118 |
-
if (is_readable($wpconfig_ark_path)) {
|
119 |
-
$config_transformer = new WPConfigTransformer($wpconfig_ark_path);
|
120 |
-
}
|
121 |
-
|
122 |
-
//===============================================
|
123 |
-
// SEARCH AND REPLACE STRINGS
|
124 |
-
//===============================================
|
125 |
-
|
126 |
-
//CUSTOM REPLACE -> REPLACE LIST
|
127 |
-
if (isset($_POST['search'])) {
|
128 |
-
$search_count = count($_POST['search']);
|
129 |
-
if ($search_count > 0) {
|
130 |
-
for ($search_index = 0; $search_index < $search_count; $search_index++) {
|
131 |
-
$search_for = $_POST['search'][$search_index];
|
132 |
-
$replace_with = $_POST['replace'][$search_index];
|
133 |
-
|
134 |
-
if (trim($search_for) != '') {
|
135 |
-
DUPX_U::queueReplacementWithEncodings($search_for, $replace_with);
|
136 |
-
}
|
137 |
-
}
|
138 |
-
}
|
139 |
-
}
|
140 |
-
|
141 |
-
// DIRS PATHS
|
142 |
-
DUPX_U::queueReplacementWithEncodings($_POST['path_old'] , $_POST['path_new'] );
|
143 |
-
$path_old_unsetSafe = rtrim(DUPX_U::unsetSafePath($_POST['path_old']), '\\');
|
144 |
-
$path_new_unsetSafe = rtrim($_POST['path_new'], '/');
|
145 |
-
DUPX_U::queueReplacementWithEncodings($path_old_unsetSafe , $path_new_unsetSafe );
|
146 |
-
|
147 |
-
// URLS
|
148 |
-
// url from _POST
|
149 |
-
$old_urls_list = array(
|
150 |
-
$_POST['url_old']
|
151 |
-
);
|
152 |
-
|
153 |
try {
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
|
|
174 |
}
|
175 |
-
} catch(Exception $e) {
|
176 |
-
DUPX_Log::info('CONTINUE EXCEPTION: '.$exceptionError->getMessage());
|
177 |
-
DUPX_Log::info('TRACE:');
|
178 |
-
DUPX_Log::info($exceptionError->getTraceAsString());
|
179 |
-
}
|
180 |
-
|
181 |
-
$at_new_domain = '@'.DUPX_U::getDomain($_POST['url_new']);
|
182 |
-
|
183 |
-
$old_urls_list = array_unique ($old_urls_list);
|
184 |
-
foreach ($old_urls_list as $old_url) {
|
185 |
-
DUPX_U::replacmentUrlOldToNew($old_url, $_POST['url_new']);
|
186 |
-
|
187 |
-
if ($replace_mail) {
|
188 |
-
$at_old_domain = '@'.DUPX_U::getDomain($old_url);
|
189 |
-
|
190 |
-
if ($at_new_domain !== $at_old_domain) {
|
191 |
-
DUPX_U::queueReplacementWithEncodings($at_old_domain, $at_new_domain);
|
192 |
-
}
|
193 |
-
}
|
194 |
-
}
|
195 |
-
|
196 |
-
/*=============================================================
|
197 |
-
* REMOVE TRAILING SLASH LOGIC:
|
198 |
-
* In many cases the trailing slash of a url or path causes issues in some
|
199 |
-
* enviroments; so by default all trailing slashes have been removed.
|
200 |
-
* This has worked well for several years. However, there are some edge
|
201 |
-
* cases where removing the trailing slash will cause issues such that
|
202 |
-
* the following will happen:
|
203 |
-
http://www.mysite.com >>>> http://C:/xampp/apache/htdocs/.mysite.com
|
204 |
-
* So the edge case array is a place older for these types of issues.
|
205 |
-
*/
|
206 |
-
$GLOBALS['REPLACE_LIST_EDGE_CASES'] = array('/www/');
|
207 |
-
$_dupx_tmp_replace_list = $GLOBALS['REPLACE_LIST'];
|
208 |
-
foreach ($_dupx_tmp_replace_list as $key => $val) {
|
209 |
-
foreach ($GLOBALS['REPLACE_LIST_EDGE_CASES'] as $skip_val) {
|
210 |
-
$search = $GLOBALS['REPLACE_LIST'][$key]['search'];
|
211 |
-
$replace = $GLOBALS['REPLACE_LIST'][$key]['replace'];
|
212 |
-
if (strcmp($skip_val, $search) !== 0) {
|
213 |
-
$GLOBALS['REPLACE_LIST'][$key]['search'] = rtrim($search, '\/');
|
214 |
-
$GLOBALS['REPLACE_LIST'][$key]['replace'] = rtrim($replace, '\/');
|
215 |
-
} else {
|
216 |
-
DUPX_Log::info("NOTICE: Edge case for path trimming detected on {$skip_val}");
|
217 |
-
}
|
218 |
-
}
|
219 |
-
}
|
220 |
-
|
221 |
-
DUPX_Log::info("Final replace list: \n". print_r($GLOBALS['REPLACE_LIST'], true), 2);
|
222 |
-
$report = DUPX_UpdateEngine::load($dbh, $GLOBALS['REPLACE_LIST'], $_POST['tables'], $_POST['fullsearch']);
|
223 |
-
|
224 |
-
//BUILD JSON RESPONSE
|
225 |
-
$JSON = array();
|
226 |
-
$JSON['step1'] = json_decode(urldecode($_POST['json']));
|
227 |
-
$JSON['step3'] = $report;
|
228 |
-
$JSON['step3']['warn_all'] = 0;
|
229 |
-
$JSON['step3']['warnlist'] = array();
|
230 |
-
|
231 |
-
DUPX_UpdateEngine::logStats($report);
|
232 |
-
DUPX_UpdateEngine::logErrors($report);
|
233 |
-
|
234 |
-
//===============================================
|
235 |
-
//CREATE NEW ADMIN USER
|
236 |
-
//===============================================
|
237 |
-
if (strlen($_POST['wp_username']) >= 4 && strlen($_POST['wp_password']) >= 6) {
|
238 |
-
|
239 |
-
$post_wp_username = $_POST['wp_username'];
|
240 |
-
$post_wp_password = $_POST['wp_password'];
|
241 |
-
$post_wp_mail = $_POST['wp_mail'];
|
242 |
-
$post_wp_nickname = $_POST['wp_nickname'];
|
243 |
-
if (empty($post_wp_nickname)) {
|
244 |
-
$post_wp_nickname = $post_wp_username;
|
245 |
-
}
|
246 |
-
$post_wp_first_name = $_POST['wp_first_name'];
|
247 |
-
$post_wp_last_name = $_POST['wp_last_name'];
|
248 |
-
|
249 |
-
$post_wp_username = mysqli_real_escape_string($dbh, $post_wp_username);
|
250 |
-
$post_wp_password = mysqli_real_escape_string($dbh, $post_wp_password);
|
251 |
-
|
252 |
-
$post_wp_mail = mysqli_real_escape_string($dbh, $post_wp_mail);
|
253 |
-
$post_wp_nickname = mysqli_real_escape_string($dbh, $post_wp_nickname);
|
254 |
-
$post_wp_first_name = mysqli_real_escape_string($dbh, $post_wp_first_name);
|
255 |
-
$post_wp_last_name = mysqli_real_escape_string($dbh, $post_wp_last_name);
|
256 |
-
|
257 |
-
$newuser_check = mysqli_query($dbh, "SELECT COUNT(*) AS count FROM `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."users` WHERE user_login = '{$post_wp_username}' ");
|
258 |
-
$newuser_row = mysqli_fetch_row($newuser_check);
|
259 |
-
$newuser_count = is_null($newuser_row) ? 0 : $newuser_row[0];
|
260 |
-
|
261 |
-
if ($newuser_count == 0) {
|
262 |
-
|
263 |
-
$newuser_datetime = @date("Y-m-d H:i:s");
|
264 |
-
$newuser_security = mysqli_real_escape_string($dbh, 'a:1:{s:13:"administrator";s:1:"1";}');
|
265 |
-
|
266 |
-
$newuser1 = @mysqli_query($dbh,
|
267 |
-
"INSERT INTO `{$GLOBALS['DUPX_AC']->wp_tableprefix}users`
|
268 |
-
(`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_registered`, `user_activation_key`, `user_status`, `display_name`)
|
269 |
-
VALUES ('{$post_wp_username}', MD5('{$post_wp_password}'), '{$post_wp_username}', '{$post_wp_mail}', '{$newuser_datetime}', '', '0', '{$post_wp_username}')");
|
270 |
-
|
271 |
-
$newuser1_insert_id = mysqli_insert_id($dbh);
|
272 |
-
|
273 |
-
$newuser2 = @mysqli_query($dbh,
|
274 |
-
"INSERT INTO `{$GLOBALS['DUPX_AC']->wp_tableprefix}usermeta`
|
275 |
-
(`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', '".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."capabilities', '{$newuser_security}')");
|
276 |
-
|
277 |
-
$newuser3 = @mysqli_query($dbh,
|
278 |
-
"INSERT INTO `{$GLOBALS['DUPX_AC']->wp_tableprefix}usermeta`
|
279 |
-
(`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', '{$GLOBALS['DUPX_AC']->wp_tableprefix}user_level', '10')");
|
280 |
-
|
281 |
-
//Misc Meta-Data Settings:
|
282 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'rich_editing', 'true')");
|
283 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'admin_color', 'fresh')");
|
284 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'nickname', '{$post_wp_nickname}')");
|
285 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'first_name', '{$post_wp_first_name}')");
|
286 |
-
@mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser1_insert_id}', 'last_name', '{$post_wp_last_name}')");
|
287 |
-
|
288 |
-
DUPX_Log::info("\nNEW WP-ADMIN USER:");
|
289 |
-
if ($newuser1 && $newuser_test2 && $newuser3) {
|
290 |
-
DUPX_Log::info("- New username '{$post_wp_username}' was created successfully allong with MU usermeta.");
|
291 |
-
} elseif ($newuser1) {
|
292 |
-
DUPX_Log::info("- New username '{$post_wp_username}' was created successfully.");
|
293 |
-
} else {
|
294 |
-
$newuser_warnmsg = "- Failed to create the user '{$post_wp_username}' \n ";
|
295 |
-
$JSON['step3']['warnlist'][] = $newuser_warnmsg;
|
296 |
-
|
297 |
-
$nManager->addFinalReportNotice(array(
|
298 |
-
'shortMsg' => 'New admin user create error',
|
299 |
-
'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
|
300 |
-
'longMsg' => $newuser_warnmsg,
|
301 |
-
'sections' => 'general'
|
302 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE , 'new-user-create-error');
|
303 |
-
|
304 |
-
DUPX_Log::info($newuser_warnmsg);
|
305 |
-
}
|
306 |
-
} else {
|
307 |
-
$newuser_warnmsg = "\nNEW WP-ADMIN USER:\n - Username '{$post_wp_username}' already exists in the database. Unable to create new account.\n";
|
308 |
-
$JSON['step3']['warnlist'][] = $newuser_warnmsg;
|
309 |
-
|
310 |
-
$nManager->addFinalReportNotice(array(
|
311 |
-
'shortMsg' => 'New admin user create error',
|
312 |
-
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
313 |
-
'longMsg' => $newuser_warnmsg,
|
314 |
-
'sections' => 'general'
|
315 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE , 'new-user-create-error');
|
316 |
-
|
317 |
-
DUPX_Log::info($newuser_warnmsg);
|
318 |
-
}
|
319 |
-
}
|
320 |
|
321 |
-
|
322 |
-
//CONFIGURATION FILE UPDATES
|
323 |
-
//===============================================
|
324 |
-
DUPX_Log::info("\n====================================");
|
325 |
-
DUPX_Log::info('CONFIGURATION FILE UPDATES:');
|
326 |
-
DUPX_Log::info("====================================\n");
|
327 |
-
|
328 |
-
try {
|
329 |
-
if (file_exists($wpconfig_ark_path)) {
|
330 |
-
|
331 |
-
if (!is_writable($wpconfig_ark_path)) {
|
332 |
-
$err_log = "\nWARNING: Unable to update file permissions and write to dup-wp-config-arc__[HASH].txt. ";
|
333 |
-
$err_log .= "Check that the wp-config.php is in the archive.zip and check with your host or administrator to enable PHP to write to the wp-config.php file. ";
|
334 |
-
$err_log .= "If performing a 'Manual Extraction' please be sure to select the 'Manual Archive Extraction' option on step 1 under options.";
|
335 |
-
chmod($wpconfig_ark_path, 0644) ? DUPX_Log::info("File Permission Update: dup-wp-config-arc__[HASH].txt set to 0644") : DUPX_Log::error("{$err_log}");
|
336 |
-
}
|
337 |
-
|
338 |
-
$config_transformer->update('constant', 'WP_HOME', $_POST['url_new'], array('normalize' => true, 'add' => false));
|
339 |
-
$config_transformer->update('constant', 'WP_SITEURL', $_POST['url_new'], array('normalize' => true, 'add' => false));
|
340 |
-
|
341 |
-
//SSL CHECKS
|
342 |
-
if (isset($_POST['ssl_admin']) && $_POST['ssl_admin']) {
|
343 |
-
$config_transformer->update('constant', 'FORCE_SSL_ADMIN', 'true', array('raw' => true, 'normalize' => true));
|
344 |
-
} else {
|
345 |
-
$config_transformer->update('constant', 'FORCE_SSL_ADMIN', 'false', array('raw' => true, 'add' => false, 'normalize' => true));
|
346 |
-
}
|
347 |
-
|
348 |
-
if (isset($_POST['cache_wp']) && $_POST['cache_wp']) {
|
349 |
-
$config_transformer->update('constant', 'WP_CACHE', 'true', array('raw' => true, 'normalize' => true));
|
350 |
-
} else {
|
351 |
-
$config_transformer->update('constant', 'WP_CACHE', 'false', array('raw' => true, 'add' => false, 'normalize' => true));
|
352 |
-
}
|
353 |
-
|
354 |
-
// Cache: [ ] Keep Home Path
|
355 |
-
if (isset($_POST['cache_path']) && $_POST['cache_path']) {
|
356 |
-
if ($config_transformer->exists('constant', 'WPCACHEHOME')) {
|
357 |
-
$wpcachehome_const_val = $config_transformer->get_value('constant', 'WPCACHEHOME');
|
358 |
-
$wpcachehome_const_val = DUPX_U::wp_normalize_path($wpcachehome_const_val);
|
359 |
-
$wpcachehome_new_const_val = str_replace($_POST['path_old'], $_POST['path_new'], $wpcachehome_const_val, $count);
|
360 |
-
if ($count > 0) {
|
361 |
-
$config_transformer->update('constant', 'WPCACHEHOME', $wpcachehome_new_const_val, array('normalize' => true));
|
362 |
-
}
|
363 |
-
}
|
364 |
-
} else {
|
365 |
-
$config_transformer->remove('constant', 'WPCACHEHOME');
|
366 |
-
}
|
367 |
-
|
368 |
-
if ($GLOBALS['DUPX_AC']->is_outer_root_wp_content_dir) {
|
369 |
-
$config_transformer->remove('constant', 'WP_CONTENT_DIR');
|
370 |
-
} elseif ($config_transformer->exists('constant', 'WP_CONTENT_DIR')) {
|
371 |
-
$wp_content_dir_const_val = $config_transformer->get_value('constant', 'WP_CONTENT_DIR');
|
372 |
-
$wp_content_dir_const_val = DUPX_U::wp_normalize_path($wp_content_dir_const_val);
|
373 |
-
$new_path = str_replace($_POST['path_old'], $_POST['path_new'], $wp_content_dir_const_val, $count);
|
374 |
-
if ($count > 0) {
|
375 |
-
$config_transformer->update('constant', 'WP_CONTENT_DIR', $new_path, array('normalize' => true));
|
376 |
-
}
|
377 |
-
}
|
378 |
-
|
379 |
-
//WP_CONTENT_URL
|
380 |
-
// '/' added to prevent word boundary with domains that have the same root path
|
381 |
-
if ($GLOBALS['DUPX_AC']->is_outer_root_wp_content_dir) {
|
382 |
-
$config_transformer->remove('constant', 'WP_CONTENT_URL');
|
383 |
-
} elseif ($config_transformer->exists('constant', 'WP_CONTENT_URL')) {
|
384 |
-
$wp_content_url_const_val = $config_transformer->get_value('constant', 'WP_CONTENT_URL');
|
385 |
-
$new_path = str_replace($_POST['url_old'] . '/', $_POST['url_new'] . '/', $wp_content_url_const_val, $count);
|
386 |
-
if ($count > 0) {
|
387 |
-
$config_transformer->update('constant', 'WP_CONTENT_URL', $new_path, array('normalize' => true));
|
388 |
-
}
|
389 |
-
}
|
390 |
-
|
391 |
-
//WP_TEMP_DIR
|
392 |
-
if ($config_transformer->exists('constant', 'WP_TEMP_DIR')) {
|
393 |
-
$wp_temp_dir_const_val = $config_transformer->get_value('constant', 'WP_TEMP_DIR');
|
394 |
-
$wp_temp_dir_const_val = DUPX_U::wp_normalize_path($wp_temp_dir_const_val);
|
395 |
-
$new_path = str_replace($_POST['path_old'], $_POST['path_new'], $wp_temp_dir_const_val, $count);
|
396 |
-
if ($count > 0) {
|
397 |
-
$config_transformer->update('constant', 'WP_TEMP_DIR', $new_path, array('normalize' => true));
|
398 |
-
}
|
399 |
-
}
|
400 |
-
|
401 |
-
// WP_PLUGIN_DIR
|
402 |
-
if ($config_transformer->exists('constant', 'WP_PLUGIN_DIR')) {
|
403 |
-
$wp_plugin_dir_const_val = $config_transformer->get_value('constant', 'WP_PLUGIN_DIR');
|
404 |
-
$wp_plugin_dir_const_val = DUPX_U::wp_normalize_path($wp_plugin_dir_const_val);
|
405 |
-
$new_path = str_replace($_POST['path_old'], $_POST['path_new'], $wp_plugin_dir_const_val, $count);
|
406 |
-
if ($count > 0) {
|
407 |
-
$config_transformer->update('constant', 'WP_PLUGIN_DIR', $new_path, array('normalize' => true));
|
408 |
-
}
|
409 |
-
}
|
410 |
-
|
411 |
-
// WP_PLUGIN_URL
|
412 |
-
if ($config_transformer->exists('constant', 'WP_PLUGIN_URL')) {
|
413 |
-
$wp_plugin_url_const_val = $config_transformer->get_value('constant', 'WP_PLUGIN_URL');
|
414 |
-
$new_path = str_replace($_POST['url_old'] . '/', $_POST['url_new'] . '/', $wp_plugin_url_const_val, $count);
|
415 |
-
if ($count > 0) {
|
416 |
-
$config_transformer->update('constant', 'WP_PLUGIN_URL', $new_path, array('normalize' => true));
|
417 |
-
}
|
418 |
-
}
|
419 |
-
|
420 |
-
// WPMU_PLUGIN_DIR
|
421 |
-
if ($config_transformer->exists('constant', 'WPMU_PLUGIN_DIR')) {
|
422 |
-
$wpmu_plugin_dir_const_val = $config_transformer->get_value('constant', 'WPMU_PLUGIN_DIR');
|
423 |
-
$wpmu_plugin_dir_const_val = DUPX_U::wp_normalize_path($wpmu_plugin_dir_const_val);
|
424 |
-
$new_path = str_replace($_POST['path_old'], $_POST['path_new'], $wpmu_plugin_dir_const_val, $count);
|
425 |
-
if ($count > 0) {
|
426 |
-
$config_transformer->update('constant', 'WPMU_PLUGIN_DIR', $new_path, array('normalize' => true));
|
427 |
-
}
|
428 |
-
}
|
429 |
-
|
430 |
-
// WPMU_PLUGIN_URL
|
431 |
-
if ($config_transformer->exists('constant', 'WPMU_PLUGIN_URL')) {
|
432 |
-
$wpmu_plugin_url_const_val = $config_transformer->get_value('constant', 'WPMU_PLUGIN_URL');
|
433 |
-
$new_path = str_replace($_POST['url_old'] . '/', $_POST['url_new'] . '/', $wpmu_plugin_url_const_val, $count);
|
434 |
-
if ($count > 0) {
|
435 |
-
$config_transformer->update('constant', 'WPMU_PLUGIN_URL', $new_path, array('normalize' => true));
|
436 |
-
}
|
437 |
-
}
|
438 |
-
|
439 |
-
// COOKIE_DOMAIN
|
440 |
-
if ($config_transformer->exists('constant', 'COOKIE_DOMAIN')) {
|
441 |
-
|
442 |
-
$post_url_old = DUPX_U::sanitize_text_field($_POST['url_old']);
|
443 |
-
$post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']);
|
444 |
-
|
445 |
-
$parsed_post_url_old = parse_url($post_url_old);
|
446 |
-
$parsed_post_url_new = parse_url($post_url_new);
|
447 |
-
|
448 |
-
$old_cookie_domain = $parsed_post_url_old['host'];
|
449 |
-
$new_cookie_domain = $parsed_post_url_new['host'];
|
450 |
-
|
451 |
-
$const_val = $config_transformer->get_value('constant', 'COOKIE_DOMAIN'); $old_cookie_domain = $parsed_post_url_old['host'];
|
452 |
-
$const_new_val= str_replace($old_cookie_domain, $new_cookie_domain, $const_val, $count);
|
453 |
-
|
454 |
-
if ($count > 0) {
|
455 |
-
$config_transformer->update('constant', 'COOKIE_DOMAIN', $const_new_val, array('normalize' => true));
|
456 |
-
}
|
457 |
-
}
|
458 |
-
|
459 |
-
$db_host = isset($_POST['dbhost']) ? DUPX_U::sanitize_text_field($_POST['dbhost']) : '';
|
460 |
-
$db_name = isset($_POST['dbname']) ? DUPX_U::sanitize_text_field($_POST['dbname']) : '';
|
461 |
-
$db_user = isset($_POST['dbuser']) ? DUPX_U::sanitize_text_field($_POST['dbuser']) : '';
|
462 |
-
$db_pass = isset($_POST['dbpass']) ? trim($_POST['dbpass']) : '';
|
463 |
-
$db_pass = DUPX_U::getEscapedGenericString($db_pass);
|
464 |
-
|
465 |
-
$config_transformer->update('constant', 'DB_NAME', $db_name);
|
466 |
-
$config_transformer->update('constant', 'DB_USER', $db_user);
|
467 |
-
$config_transformer->update('constant', 'DB_PASSWORD', $db_pass, array('raw' => true));
|
468 |
-
$config_transformer->update('constant', 'DB_HOST', $db_host);
|
469 |
-
|
470 |
-
DUPX_Log::info("UPDATED WP-CONFIG ARK FILE:\n - '{$wpconfig_ark_path}'");
|
471 |
-
|
472 |
-
} else {
|
473 |
-
DUPX_Log::info("AKR FILE NOT FOUND");
|
474 |
-
DUPX_Log::info("WP-CONFIG ARK FILE:\n - '{$wpconfig_ark_path}'");
|
475 |
-
DUPX_Log::info("SKIP FILE UPDATES\n");
|
476 |
-
|
477 |
-
$shortMsg = 'wp-config.php not found';
|
478 |
-
$longMsg = <<<LONGMSG
|
479 |
-
Error updating wp-config file.<br>
|
480 |
-
The installation is finished but check the wp-config.php file and manually update the incorrect values.
|
481 |
-
LONGMSG;
|
482 |
-
/* $nManager->addNextStepNotice(array(
|
483 |
-
'shortMsg' => $shortMsg,
|
484 |
-
'level' => DUPX_NOTICE_ITEM::CRITICAL,
|
485 |
-
|
486 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception');*/
|
487 |
-
$nManager->addFinalReportNotice(array(
|
488 |
-
'shortMsg' => $shortMsg,
|
489 |
-
'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
|
490 |
-
'longMsg' => $longMsg,
|
491 |
-
'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML,
|
492 |
-
'sections' => 'general'
|
493 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception');
|
494 |
-
|
495 |
-
}
|
496 |
} catch (Exception $e) {
|
497 |
-
$
|
498 |
-
$longMsg = <<<LONGMSG
|
499 |
-
Error updating wp-config file.<br>
|
500 |
-
The installation is finished but check the wp-config.php file and manually update the incorrect values.
|
501 |
-
LONGMSG;
|
502 |
-
/* $nManager->addNextStepNotice(array(
|
503 |
-
'shortMsg' => $shortMsg,
|
504 |
-
'level' => DUPX_NOTICE_ITEM::CRITICAL,
|
505 |
-
|
506 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception');*/
|
507 |
-
$nManager->addFinalReportNotice(array(
|
508 |
-
'shortMsg' => $shortMsg,
|
509 |
-
'level' => DUPX_NOTICE_ITEM::CRITICAL,
|
510 |
-
'longMsg' => $longMsg,
|
511 |
-
'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML,
|
512 |
-
'sections' => 'general'
|
513 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE , 'wp-config-transformer-exception');
|
514 |
-
}
|
515 |
-
|
516 |
-
switch ($_POST['config_mode']) {
|
517 |
-
case 'NEW':
|
518 |
-
DUPX_ServerConfig::createNewConfigs();
|
519 |
-
break;
|
520 |
-
case 'RESTORE':
|
521 |
-
DUPX_ServerConfig::renameOrigConfigs();
|
522 |
-
DUPX_Log::info("\nWARNING: Retaining the original .htaccess or web.config files may cause");
|
523 |
-
DUPX_Log::info("issues with the initial setup of your site. If you run into issues with the install");
|
524 |
-
DUPX_Log::info("process choose 'Create New' for the 'Config Files' options");
|
525 |
-
break;
|
526 |
-
case 'IGNORE':
|
527 |
-
DUPX_Log::info("\nWARNING: Choosing the option to ignore the .htaccess, web.config and .user.ini files");
|
528 |
-
DUPX_Log::info("can lead to install issues. The 'Ignore All' option is designed for advanced users.");
|
529 |
-
break;
|
530 |
}
|
531 |
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
//===============================================
|
536 |
-
//DUPX_Log::info("\n====================================");
|
537 |
-
//DUPX_Log::info('GENERAL UPDATES & CLEANUP:');
|
538 |
-
//DUPX_Log::info("====================================\n");
|
539 |
-
|
540 |
-
$blog_name = mysqli_real_escape_string($dbh, $_POST['blogname']);
|
541 |
-
$plugin_list = (isset($_POST['plugins'])) ? $_POST['plugins'] : array();
|
542 |
-
|
543 |
-
if (!in_array('duplicator/duplicator.php', $plugin_list)) {
|
544 |
-
$plugin_list[] = 'duplicator/duplicator.php';
|
545 |
-
}
|
546 |
-
$serial_plugin_list = @serialize($plugin_list);
|
547 |
-
$serial_plugin_list = mysqli_real_escape_string($dbh, $serial_plugin_list);
|
548 |
-
|
549 |
-
/** FINAL UPDATES: Must happen after the global replace to prevent double pathing
|
550 |
-
http://xyz.com/abc01 will become http://xyz.com/abc0101 with trailing data */
|
551 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '{$blog_name}' WHERE option_name = 'blogname' ");
|
552 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '{$serial_plugin_list}' WHERE option_name = 'active_plugins' ");
|
553 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($dbh, $_POST['url_new'])."' WHERE option_name = 'home' ");
|
554 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` SET option_value = '".mysqli_real_escape_string($dbh, $_POST['siteurl'])."' WHERE option_name = 'siteurl' ");
|
555 |
-
mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."options` (option_value, option_name) VALUES('".mysqli_real_escape_string($dbh, $_POST['exe_safe_mode'])."','duplicator_exe_safe_mode')");
|
556 |
-
//Reset the postguid data
|
557 |
-
if ($_POST['postguid']) {
|
558 |
-
mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['DUPX_AC']->wp_tableprefix)."posts` SET guid = REPLACE(guid, '".mysqli_real_escape_string($dbh, $_POST['url_new'])."', '".mysqli_real_escape_string($dbh, $_POST['url_old'])."')");
|
559 |
-
$update_guid = @mysqli_affected_rows($dbh) or 0;
|
560 |
-
DUPX_Log::info("Reverted '{$update_guid}' post guid columns back to '{$_POST['url_old']}'");
|
561 |
-
}
|
562 |
-
|
563 |
-
//===============================================
|
564 |
-
//NOTICES TESTS
|
565 |
-
//===============================================
|
566 |
-
DUPX_Log::info("\n====================================");
|
567 |
-
DUPX_Log::info("NOTICES");
|
568 |
-
DUPX_Log::info("====================================\n");
|
569 |
-
|
570 |
-
if (file_exists($wpconfig_ark_path)) {
|
571 |
-
$config_vars = array('WPCACHEHOME', 'COOKIE_DOMAIN', 'WP_SITEURL', 'WP_HOME', 'WP_TEMP_DIR');
|
572 |
-
$wpconfig_ark_contents = file_get_contents($wpconfig_ark_path);
|
573 |
-
$config_found = DUPX_U::getListValues($config_vars, $wpconfig_ark_contents);
|
574 |
-
|
575 |
-
//Files
|
576 |
-
if (! empty($config_found)) {
|
577 |
-
$msg = "WP-CONFIG NOTICE: The wp-config.php has following values set [".implode(", ", $config_found)."]. \n";
|
578 |
-
$msg .= "Please validate these values are correct by opening the file and checking the values.\n";
|
579 |
-
$msg .= "See the codex link for more details: https://codex.wordpress.org/Editing_wp-config.php";
|
580 |
-
$JSON['step3']['warnlist'][] = $msg;
|
581 |
-
DUPX_Log::info($msg);
|
582 |
-
|
583 |
-
$nManager->addFinalReportNotice(array(
|
584 |
-
'shortMsg' => 'wp-config notice',
|
585 |
-
'level' => DUPX_NOTICE_ITEM::NOTICE,
|
586 |
-
'longMsg' => $msg,
|
587 |
-
'sections' => 'general'
|
588 |
-
));
|
589 |
-
}
|
590 |
-
} else {
|
591 |
-
$msg = "WP-CONFIG NOTICE: <b>wp-config.php not found.</b><br><br>" ;
|
592 |
-
$msg .= "No action on the wp-config was possible.<br>";
|
593 |
-
$msg .= "Be sure to insert a properly modified wp-config for correct wordpress operation.";
|
594 |
-
$JSON['step3']['warnlist'][] = $msg;
|
595 |
-
|
596 |
-
$nManager->addFinalReportNotice(array(
|
597 |
-
'shortMsg' => 'wp-config not found',
|
598 |
-
'level' => DUPX_NOTICE_ITEM::HARD_WARNING,
|
599 |
-
'longMsg' => $msg,
|
600 |
-
'longMsgMode'=> DUPX_NOTICE_ITEM::MSG_MODE_HTML,
|
601 |
-
'sections' => 'general'
|
602 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE , 'wp-config-not-found');
|
603 |
-
|
604 |
-
DUPX_Log::info($msg);
|
605 |
-
}
|
606 |
-
|
607 |
-
//Database
|
608 |
-
$result = @mysqli_query($dbh, "SELECT option_value FROM `{$GLOBALS['DUPX_AC']->wp_tableprefix}options` WHERE option_name IN ('upload_url_path','upload_path')");
|
609 |
-
if ($result) {
|
610 |
-
while ($row = mysqli_fetch_row($result)) {
|
611 |
-
if (strlen($row[0])) {
|
612 |
-
$msg = "MEDIA SETTINGS NOTICE: The table '{$GLOBALS['DUPX_AC']->wp_tableprefix}options' has at least one the following values ['upload_url_path','upload_path'] \n";
|
613 |
-
$msg .= "set please validate settings. These settings can be changed in the wp-admin by going to /wp-admin/options.php'";
|
614 |
-
$JSON['step3']['warnlist'][] = $msg;
|
615 |
-
DUPX_Log::info($msg);
|
616 |
-
|
617 |
-
$nManager->addFinalReportNotice(array(
|
618 |
-
'shortMsg' => 'Media settings notice',
|
619 |
-
'level' => DUPX_NOTICE_ITEM::SOFT_WARNING,
|
620 |
-
'longMsg' => $msg,
|
621 |
-
'sections' => 'general'
|
622 |
-
), DUPX_NOTICE_MANAGER::ADD_UNIQUE_UPDATE , 'media-settings-notice');
|
623 |
-
|
624 |
-
break;
|
625 |
-
}
|
626 |
-
}
|
627 |
-
}
|
628 |
-
|
629 |
-
if (empty($JSON['step3']['warnlist'])) {
|
630 |
-
DUPX_Log::info("No General Notices Found\n");
|
631 |
-
}
|
632 |
-
|
633 |
-
$JSON['step3']['warn_all'] = empty($JSON['step3']['warnlist']) ? 0 : count($JSON['step3']['warnlist']);
|
634 |
-
|
635 |
-
mysqli_close($dbh);
|
636 |
-
|
637 |
-
|
638 |
-
//-- Finally, back up the old wp-config and rename the new one
|
639 |
-
if ($GLOBALS['DUPX_AC']->installSiteOverwriteOn) {
|
640 |
-
$wpconfig_path = "{$GLOBALS['DUPX_ROOT']}/wp-config.php";
|
641 |
-
if (copy($wpconfig_ark_path, $wpconfig_path) === false) {
|
642 |
-
DUPX_Log::error("ERROR: Unable to copy '{$root_path}/dup-wp-config-arc__[HASH].txt' to '{$wpconfig_path}'. "
|
643 |
-
. "Check server permissions for more details see FAQ: https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-055-q");
|
644 |
-
}
|
645 |
-
}
|
646 |
-
|
647 |
-
//Cleanup any tmp files a developer may have forgotten about
|
648 |
-
//Lets be proactive for the developer just in case
|
649 |
-
$wpconfig_path_bak = "{$GLOBALS['DUPX_ROOT']}/wp-config.bak";
|
650 |
-
$wpconfig_path_old = "{$GLOBALS['DUPX_ROOT']}/wp-config.old";
|
651 |
-
$wpconfig_path_org = "{$GLOBALS['DUPX_ROOT']}/wp-config.org";
|
652 |
-
$wpconfig_path_orig = "{$GLOBALS['DUPX_ROOT']}/wp-config.orig";
|
653 |
-
$wpconfig_safe_check = array($wpconfig_path_bak, $wpconfig_path_old, $wpconfig_path_org, $wpconfig_path_orig);
|
654 |
-
|
655 |
-
foreach ($wpconfig_safe_check as $file) {
|
656 |
-
if(file_exists($file)) {
|
657 |
-
$tmp_newfile = $file . uniqid('_');
|
658 |
-
if(rename($file, $tmp_newfile) === false) {
|
659 |
-
DUPX_Log::info("WARNING: Unable to rename '{$file}' to '{$tmp_newfile}'");
|
660 |
-
}
|
661 |
-
}
|
662 |
-
}
|
663 |
-
DUPX_ServerConfig::finalReportNotices();
|
664 |
-
$nManager->saveNotices();
|
665 |
-
|
666 |
-
$ajax3_sum = DUPX_U::elapsedTime(DUPX_U::getMicrotime(), $ajax3_start);
|
667 |
-
DUPX_Log::info("\nSTEP-3 COMPLETE @ ".@date('h:i:s')." - RUNTIME: {$ajax3_sum} \n\n");
|
668 |
-
|
669 |
-
$JSON['step3']['pass'] = 1;
|
670 |
-
error_reporting($ajax3_error_level);
|
671 |
-
die(DupLiteSnapLibUtil::wp_json_encode($JSON));
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
|
|
|
3 |
|
4 |
//-- START OF ACTION STEP 3: Update the database
|
5 |
require_once($GLOBALS['DUPX_INIT'].'/classes/config/class.archive.config.php');
|
6 |
require_once($GLOBALS['DUPX_INIT'].'/lib/config/class.wp.config.tranformer.php');
|
7 |
require_once($GLOBALS['DUPX_INIT'].'/lib/config/class.wp.config.tranformer.src.php');
|
8 |
+
require_once($GLOBALS['DUPX_INIT'].'/classes/utilities/class.u.search.reaplce.manager.php');
|
9 |
+
require_once($GLOBALS['DUPX_INIT'].'/classes/class.s3.func.php');
|
10 |
|
11 |
/** JSON RESPONSE: Most sites have warnings turned off by default, but if they're turned on the warnings
|
12 |
cause errors in the JSON data Here we hide the status so warning level is reset at it at the end */
|
13 |
+
// We have already removing warning from json resp
|
14 |
+
// It cause 500 internal server error so commenting out
|
15 |
+
/*
|
16 |
+
$ajax3_error_level = error_reporting();
|
17 |
+
error_reporting(E_ERROR);
|
18 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
try {
|
20 |
+
DUPX_Log::setThrowExceptionOnError(true);
|
21 |
+
|
22 |
+
$nManager = DUPX_NOTICE_MANAGER::getInstance();
|
23 |
+
$s3Func = DUPX_S3_Funcs::getInstance();
|
24 |
+
|
25 |
+
switch ($s3Func->getEngineMode()) {
|
26 |
+
case DUPX_S3_Funcs::MODE_NORMAL:
|
27 |
+
default:
|
28 |
+
$s3Func->initLog();
|
29 |
+
$s3Func->runSearchAndReplace();
|
30 |
+
|
31 |
+
$s3Func->removeLicenseKey();
|
32 |
+
$s3Func->createNewAdminUser();
|
33 |
+
$s3Func->configurationFileUpdate();
|
34 |
+
$s3Func->htaccessUpdate();
|
35 |
+
$s3Func->generalUpdateAndCleanup();
|
36 |
+
|
37 |
+
$s3Func->noticeTest();
|
38 |
+
$s3Func->cleanupTmpFiles();
|
39 |
+
$s3Func->finalReportNotices();
|
40 |
+
$s3Func->complete();
|
41 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
+
$nManager->saveNotices();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
} catch (Exception $e) {
|
45 |
+
$s3Func->error($e->getMessage());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
|
48 |
+
$json = $s3Func->getJsonReport();
|
49 |
+
DUPX_Log::close();
|
50 |
+
die(DupLiteSnapLibUtil::wp_json_encode($json));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
installer/dup-installer/index.php
CHANGED
@@ -1,6 +1,12 @@
|
|
1 |
<?php
|
2 |
$API['BaseRootPath'] = str_ireplace('dup-installer', '', dirname(__FILE__));
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
if (file_exists("{$API['BaseRootPath']}\installer.php"))
|
6 |
{
|
1 |
<?php
|
2 |
$API['BaseRootPath'] = str_ireplace('dup-installer', '', dirname(__FILE__));
|
3 |
+
// for ngrok url and Local by Flywheel Live URL
|
4 |
+
if (isset($_SERVER['HTTP_X_ORIGINAL_HOST'])) {
|
5 |
+
$host = $_SERVER['HTTP_X_ORIGINAL_HOST'];
|
6 |
+
} else {
|
7 |
+
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];//WAS SERVER_NAME and caused problems on some boxes
|
8 |
+
}
|
9 |
+
$API['BaseRootURL'] = '//' . $host . str_ireplace('dup-installer', '', dirname($_SERVER['PHP_SELF']));
|
10 |
|
11 |
if (file_exists("{$API['BaseRootPath']}\installer.php"))
|
12 |
{
|
installer/dup-installer/main.installer.php
CHANGED
@@ -183,7 +183,13 @@ try {
|
|
183 |
}
|
184 |
}
|
185 |
|
186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
$GLOBALS['NOW_TIME'] = @date("His");
|
188 |
|
189 |
if (!chdir($GLOBALS['DUPX_INIT'])) {
|
@@ -198,8 +204,6 @@ try {
|
|
198 |
DUPX_Log::error("An invalid request was made to '{$post_ctrl_action}'. In order to protect this request from unauthorized access please "
|
199 |
. "<a href='../{$GLOBALS['BOOTLOADER_NAME']}'>restart this install process</a>.");
|
200 |
}
|
201 |
-
require_once($GLOBALS['DUPX_INIT'].'/ctrls/ctrl.base.php');
|
202 |
-
|
203 |
//PASSWORD CHECK
|
204 |
if ($GLOBALS['DUPX_AC']->secure_on) {
|
205 |
$pass_hasher = new DUPX_PasswordHash(8, FALSE);
|
@@ -254,17 +258,16 @@ if (!empty($unespectOutput)) {
|
|
254 |
<title>Duplicator</title>
|
255 |
<link rel='stylesheet' href='assets/font-awesome/css/all.min.css' type='text/css' media='all' />
|
256 |
|
257 |
-
<link rel="apple-touch-icon" sizes="180x180" href="
|
258 |
-
<link rel="icon" type="image/png" sizes="32x32" href="
|
259 |
-
<link rel="icon" type="image/png" sizes="16x16" href="
|
260 |
-
<link rel="manifest" href="
|
261 |
-
<link rel="mask-icon" href="
|
262 |
-
<link rel="shortcut icon" href="
|
263 |
<meta name="msapplication-TileColor" content="#da532c">
|
264 |
-
<meta name="msapplication-config" content="
|
265 |
<meta name="theme-color" content="#ffffff">
|
266 |
|
267 |
-
<link rel='stylesheet' href='assets/font-awesome/css/font-awesome.min.css' type='text/css' media='all' />
|
268 |
<?php
|
269 |
require_once($GLOBALS['DUPX_INIT'] . '/assets/inc.libs.css.php');
|
270 |
require_once($GLOBALS['DUPX_INIT'] . '/assets/inc.css.php');
|
@@ -272,7 +275,7 @@ if (!empty($unespectOutput)) {
|
|
272 |
require_once($GLOBALS['DUPX_INIT'] . '/assets/inc.js.php');
|
273 |
?>
|
274 |
</head>
|
275 |
-
<body>
|
276 |
|
277 |
<div id="content">
|
278 |
|
@@ -320,6 +323,8 @@ if (!empty($unespectOutput)) {
|
|
320 |
//DUPX_NOTICE_MANAGER::testFinalReportFullMessages();
|
321 |
/****************************/
|
322 |
|
|
|
|
|
323 |
DUPX_NOTICE_MANAGER::getInstance()->displayStepMessages();
|
324 |
?>
|
325 |
|
183 |
}
|
184 |
}
|
185 |
|
186 |
+
// for ngrok url and Local by Flywheel Live URL
|
187 |
+
if (isset($_SERVER['HTTP_X_ORIGINAL_HOST'])) {
|
188 |
+
$host = $_SERVER['HTTP_X_ORIGINAL_HOST'];
|
189 |
+
} else {
|
190 |
+
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];//WAS SERVER_NAME and caused problems on some boxes
|
191 |
+
}
|
192 |
+
$GLOBALS['_CURRENT_URL_PATH'] = $host . dirname($_SERVER['PHP_SELF']);
|
193 |
$GLOBALS['NOW_TIME'] = @date("His");
|
194 |
|
195 |
if (!chdir($GLOBALS['DUPX_INIT'])) {
|
204 |
DUPX_Log::error("An invalid request was made to '{$post_ctrl_action}'. In order to protect this request from unauthorized access please "
|
205 |
. "<a href='../{$GLOBALS['BOOTLOADER_NAME']}'>restart this install process</a>.");
|
206 |
}
|
|
|
|
|
207 |
//PASSWORD CHECK
|
208 |
if ($GLOBALS['DUPX_AC']->secure_on) {
|
209 |
$pass_hasher = new DUPX_PasswordHash(8, FALSE);
|
258 |
<title>Duplicator</title>
|
259 |
<link rel='stylesheet' href='assets/font-awesome/css/all.min.css' type='text/css' media='all' />
|
260 |
|
261 |
+
<link rel="apple-touch-icon" sizes="180x180" href="favicon/lite01_apple-touch-icon.png">
|
262 |
+
<link rel="icon" type="image/png" sizes="32x32" href="favicon/lite01_favicon-32x32.png">
|
263 |
+
<link rel="icon" type="image/png" sizes="16x16" href="favicon/lite01_favicon-16x16.png">
|
264 |
+
<link rel="manifest" href="favicon/site.webmanifest">
|
265 |
+
<link rel="mask-icon" href="favicon/lite01_safari-pinned-tab.svg" color="#5bbad5">
|
266 |
+
<link rel="shortcut icon" href="favicon/lite01_favicon.ico">
|
267 |
<meta name="msapplication-TileColor" content="#da532c">
|
268 |
+
<meta name="msapplication-config" content="favicon/browserconfig.xml">
|
269 |
<meta name="theme-color" content="#ffffff">
|
270 |
|
|
|
271 |
<?php
|
272 |
require_once($GLOBALS['DUPX_INIT'] . '/assets/inc.libs.css.php');
|
273 |
require_once($GLOBALS['DUPX_INIT'] . '/assets/inc.css.php');
|
275 |
require_once($GLOBALS['DUPX_INIT'] . '/assets/inc.js.php');
|
276 |
?>
|
277 |
</head>
|
278 |
+
<body id="body-<?php echo $GLOBALS["VIEW"]; ?>" >
|
279 |
|
280 |
<div id="content">
|
281 |
|
323 |
//DUPX_NOTICE_MANAGER::testFinalReportFullMessages();
|
324 |
/****************************/
|
325 |
|
326 |
+
DUPX_NOTICE_MANAGER::getInstance()->nextStepLog();
|
327 |
+
// display and remove next step notices
|
328 |
DUPX_NOTICE_MANAGER::getInstance()->displayStepMessages();
|
329 |
?>
|
330 |
|
installer/dup-installer/views/view.help.php
CHANGED
@@ -1,12 +1,15 @@
|
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
-
//The help for both pro and lite are shared. Pro is where the master lives. Use the flag below to
|
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 |
<!-- =========================================
|
11 |
HELP FORM -->
|
12 |
<div id="main-help">
|
@@ -35,18 +38,18 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
35 |
|
36 |
<table class="help-opt">
|
37 |
<tr>
|
38 |
-
<th>Option</th>
|
39 |
<th>Details</th>
|
40 |
</tr>
|
41 |
<tr>
|
42 |
-
<td>Locked</td>
|
43 |
<td>
|
44 |
"Locked" means a password is protecting each step of the installer. This option is recommended on all installers
|
45 |
that are accessible via a public URL but not required.
|
46 |
</td>
|
47 |
</tr>
|
48 |
<tr>
|
49 |
-
<td>Unlocked</td>
|
50 |
<td>
|
51 |
"Unlocked" means that if your installer is on a public server that anyone can access it. This is a less secure way to run your installer. If you are running the
|
52 |
installer very quickly then removing all the installer files, then the chances of exposing it is going to be low depending on your sites access history.
|
@@ -82,25 +85,25 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
82 |
|
83 |
<table class="help-opt">
|
84 |
<tr>
|
85 |
-
<th>Option</th>
|
86 |
<th>Details</th>
|
87 |
</tr>
|
88 |
<tr>
|
89 |
-
<td>Standard Install</td>
|
90 |
<td>
|
91 |
This mode indicates that the installer and archive have been placed into an empty directory and the site is ready for a fresh/new redeployment.
|
92 |
This is the most common mode and the mode that has been around the longest.
|
93 |
</td>
|
94 |
</tr>
|
95 |
<tr>
|
96 |
-
<td>Standard Install <br/> Database Only</td>
|
97 |
<td>
|
98 |
This mode indicates that the installer and archive were manually moved or transferred to a location and that only the Database will be installed
|
99 |
at this location.
|
100 |
</td>
|
101 |
</tr>
|
102 |
<tr>
|
103 |
-
<td>Overwrite Install <sup>pro</sup></td>
|
104 |
<td>
|
105 |
This mode indicates that the installer was started in a location that contains an existing site. With this mode <b>the existing site will be overwritten</b> with
|
106 |
the contents of the archive.zip/daf and the database.sql file. This is an advanced option and users should be pre-paired to know that state of their database
|
@@ -108,7 +111,7 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
108 |
</td>
|
109 |
</tr>
|
110 |
<tr>
|
111 |
-
<td>Overwrite Install <br/> Database Only <sup>pro</sup></td>
|
112 |
<td>
|
113 |
This mode indicates that the installer was started in a location that contains an existing site. With this mode <b>the existing site will be overwritten</b> with
|
114 |
the contents of the database.sql file. This is an advanced option and users should be pre-paired to know that state of their database and site files ahead of time.
|
@@ -148,14 +151,14 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
148 |
The options for step 1 can help better prepare your site should your server need additional settings beyond most general configuration.
|
149 |
<table class="help-opt">
|
150 |
<tr>
|
151 |
-
<th>Option</th>
|
152 |
<th>Details</th>
|
153 |
</tr>
|
154 |
<tr>
|
155 |
<td colspan="2" class="section">General Options</td>
|
156 |
</tr>
|
157 |
<tr>
|
158 |
-
<td>Extraction</td>
|
159 |
<td>
|
160 |
<b>Manual Archive Extraction</b><br/>
|
161 |
Set the Extraction value to "Manual Archive Extraction" when the archive file has already been manually extracted on the server. This can be done through your hosts
|
@@ -175,7 +178,7 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
175 |
</td>
|
176 |
</tr>
|
177 |
<tr>
|
178 |
-
<td>Permissions</td>
|
179 |
<td>
|
180 |
<b>All Files:</b> Check the 'All Files' check-box and enter in the desired <a href="http://php.net/manual/en/function.chmod.php" target="_blank">chmod command</a>
|
181 |
to recursively set the octal value on all the files being extracted. Typically this value is 644 on most servers and hosts.
|
@@ -191,7 +194,7 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
191 |
<td colspan="2" class="section">Advanced Options</td>
|
192 |
</tr>
|
193 |
<tr>
|
194 |
-
<td>Safe Mode</td>
|
195 |
<td>
|
196 |
Safe mode is designed to configure the site with specific options at install time to help over come issues that may happen during the install were the site
|
197 |
is having issues. These options should only be used if you run into issues after you have tried to run an install.
|
@@ -205,7 +208,7 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
205 |
</td>
|
206 |
</tr>
|
207 |
<tr>
|
208 |
-
<td>Config Files </td>
|
209 |
<td>
|
210 |
When dealing with configuration files (.htaccess, web.config and .user.ini) the installer can apply different modes:
|
211 |
<br/><br/>
|
@@ -234,12 +237,12 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
234 |
</tr>
|
235 |
|
236 |
<tr>
|
237 |
-
<td>File Times</td>
|
238 |
<td>When the archive is extracted should it show the current date-time or keep the original time it had when it was built. This setting will be applied to
|
239 |
all files and directories.</td>
|
240 |
</tr>
|
241 |
<tr>
|
242 |
-
<td>Logging</td>
|
243 |
<td>
|
244 |
The level of detail that will be sent to the log file (installer-log.txt). The recommend setting for most installs should be 'Light'.
|
245 |
Note if you use Debug the amount of data written can be very large. Debug is only recommended for support.
|
@@ -280,27 +283,27 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
280 |
<i>The cPanel connectivity option is only available for Duplicator Pro.</i>
|
281 |
<table class="help-opt">
|
282 |
<tr>
|
283 |
-
<th>Option</th>
|
284 |
<th>Details</th>
|
285 |
</tr>
|
286 |
<tr>
|
287 |
-
<td>Host</td>
|
288 |
<td>This should be the primary domain account URL that is associated with your host. Most hosts will require you to register a primary domain name.
|
289 |
This should be the URL that you place in the host field. For example if your primary domain name is "mysite.com" then you would enter in
|
290 |
"https://mysite.com:2083". The port 2038 is the common port number that cPanel works on. If you do not know your primary domain name please contact your
|
291 |
hosting provider or server administrator.</td>
|
292 |
</tr>
|
293 |
<tr>
|
294 |
-
<td>Username</td>
|
295 |
<td>The cPanel username used to login to your cPanel account. <i>This is <b>not</b> the same thing as your WordPress administrator account</i>.
|
296 |
If your unsure of this name please contact your hosting provider or server administrator.</td>
|
297 |
</tr>
|
298 |
<tr>
|
299 |
-
<td>Password</td>
|
300 |
<td>The password of the cPanel user</td>
|
301 |
</tr>
|
302 |
<tr>
|
303 |
-
<td>Troubleshoot</td>
|
304 |
<td>
|
305 |
<b>Common cPanel Connection Issues:</b><br/>
|
306 |
- Your host does not use <a href="http://cpanel.com/" target="_blank">cPanel Software</a> <br/>
|
@@ -317,11 +320,11 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
317 |
The database setup options allow you to connect to an existing database or in the case of cPanel connect or create a new database.
|
318 |
<table class="help-opt">
|
319 |
<tr>
|
320 |
-
<th>Option</th>
|
321 |
<th>Details</th>
|
322 |
</tr>
|
323 |
<tr>
|
324 |
-
<td>Action</td>
|
325 |
<td>
|
326 |
<b>Create New Database:</b> Will attempt to create a new database if it does not exist. When using the 'Basic' option this option will not work on many
|
327 |
hosting providers as the ability to create new databases is normally locked down. If the database does not exist then you will need to login to your
|
@@ -345,23 +348,23 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
345 |
</td>
|
346 |
</tr>
|
347 |
<tr>
|
348 |
-
<td>Host</td>
|
349 |
<td>The name of the host server that the database resides on. Many times this will be 'localhost', however each hosting provider will have it's own naming
|
350 |
convention please check with your server administrator or host to valid for sure the name needed. To add a port number just append it to the host i.e.
|
351 |
'localhost:3306'.</td>
|
352 |
</tr>
|
353 |
<tr>
|
354 |
-
<td>Database</td>
|
355 |
<td>The name of the database to which this installation will connect and install the new tables and data into. Some hosts will require a prefix while others
|
356 |
do not. Be sure to know exactly how your host requires the database name to be entered.</td>
|
357 |
</tr>
|
358 |
<tr>
|
359 |
-
<td>User</td>
|
360 |
<td>The name of a MySQL database server user. This is special account that has privileges to access a database and can read from or write to that database.
|
361 |
<i>This is <b>not</b> the same thing as your WordPress administrator account</i>.</td>
|
362 |
</tr>
|
363 |
<tr>
|
364 |
-
<td>Password</td>
|
365 |
<td>The password of the MySQL database server user.</td>
|
366 |
</tr>
|
367 |
|
@@ -372,18 +375,18 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
372 |
<h3>Options</h3>
|
373 |
<table class="help-opt">
|
374 |
<tr>
|
375 |
-
<th>Option</th>
|
376 |
<th>Details</th>
|
377 |
</tr>
|
378 |
<tr>
|
379 |
-
<td>Prefix<sup>pro*</sup></td>
|
380 |
<td>By default, databases are prefixed with the cPanel account's username (for example, myusername_databasename). However you can ignore this option if
|
381 |
your host does not use the default cPanel username prefix schema. Check the 'Ignore cPanel Prefix' and the username prefixes will be ignored.
|
382 |
This will still require you to enter in the cPanels required setup prefix if they require one. The checkbox will be set to read-only if your host has
|
383 |
disabled prefix settings. Please see your host full requirements when using the cPanel options.</td>
|
384 |
</tr>
|
385 |
<tr>
|
386 |
-
<td>Legacy</td>
|
387 |
<td>When creating a database table, the Mysql version being used may not support the collation type of the Mysql version where the table was created.
|
388 |
In this scenario, the installer will fallback to a legacy collation type to try and create the table. This value should only be checked if you receive an error when
|
389 |
testing the database.
|
@@ -397,22 +400,22 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
397 |
</td>
|
398 |
</tr>
|
399 |
<tr>
|
400 |
-
<td>Spacing</td>
|
401 |
<td>The process will remove utf8 characters represented as 'xC2' 'xA0' and replace with a uniform space. Use this option if you find strange question
|
402 |
marks in you posts</td>
|
403 |
</tr>
|
404 |
<tr>
|
405 |
-
<td>Mode</td>
|
406 |
<td>The MySQL mode option will allow you to set the mode for this session. It is very useful when running into conversion issues. For a full overview please
|
407 |
see the <a href="https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html" target="_blank">MySQL mode documentation</a> specific to your version.</td>
|
408 |
</tr>
|
409 |
<tr>
|
410 |
-
<td>Charset</td>
|
411 |
<td>When the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your
|
412 |
databases character set should be.</td>
|
413 |
</tr>
|
414 |
<tr>
|
415 |
-
<td>Collation</td>
|
416 |
<td>When the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your
|
417 |
databases collation set should be.</td>
|
418 |
</tr>
|
@@ -425,18 +428,18 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
425 |
|
426 |
<table class="help-opt">
|
427 |
<tr>
|
428 |
-
<th>Option</th>
|
429 |
<th>Details</th>
|
430 |
</tr>
|
431 |
<tr>
|
432 |
-
<td>Test<br/>Database</td>
|
433 |
<td>
|
434 |
The 'Test Database' button will help validate if the connection parameters are correct for this server and help with details about any issues
|
435 |
that may arise.
|
436 |
</td>
|
437 |
</tr>
|
438 |
<tr>
|
439 |
-
<td>Troubleshoot</td>
|
440 |
<td>
|
441 |
<b>Common Database Connection Issues:</b><br/>
|
442 |
- Double check case sensitive values 'User', 'Password' & the 'Database Name' <br/>
|
@@ -481,78 +484,92 @@ $expandClass = $sectionId == $open_section ? 'open' : 'close';
|
|
481 |
<h3>Options</h3>
|
482 |
<table class="help-opt">
|
483 |
<tr>
|
484 |
-
<th>Option</th>
|
485 |
<th>Details</th>
|
486 |
</tr>
|
487 |
<tr>
|
488 |
<td colspan="2" class="section">New Admin Account</td>
|
489 |
</tr>
|
490 |
<tr>
|
491 |
-
<td>Username</td>
|
492 |
<td>A new WordPress username to create. This will create a new WordPress administrator account. Please note that usernames are not changeable from the within the UI.</td>
|
493 |
</tr>
|
494 |
<tr>
|
495 |
-
<td>Password</td>
|
496 |
<td>The new password for the new user. Must be at least 6 characters long.</td>
|
497 |
</tr>
|
498 |
<tr>
|
499 |
<td colspan="2" class="section">Scan Options</td>
|
500 |
</tr>
|
501 |
<tr>
|
502 |
-
<td>Cleanup <sup>pro</sup></td>
|
503 |
<td>The checkbox labeled Remove schedules & storage endpoints will empty the Duplicator schedule and storage settings. This is recommended to keep enabled so that you do not have unwanted schedules and storage options enabled.</td>
|
504 |
</tr>
|
505 |
<tr>
|
506 |
-
<td>Old URL</td>
|
507 |
<td>The old URL of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons</td>
|
508 |
</tr>
|
509 |
<tr>
|
510 |
-
<td>Old Path</td>
|
511 |
<td>The old path of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons</td>
|
512 |
</tr>
|
513 |
<tr>
|
514 |
-
<td>Site URL</td>
|
515 |
<td> For details see WordPress <a href="http://codex.wordpress.org/Changing_The_Site_URL" target="_blank">Site URL</a> & <a href="http://codex.wordpress.org/Giving_WordPress_Its_Own_Directory" target="_blank">Alternate Directory</a>. If you're not sure about this value then leave it the same as the new settings URL.</td>
|
516 |
</tr>
|
517 |
<tr>
|
518 |
-
<td>Scan Tables</td>
|
519 |
<td>Select the tables to be updated. This process will update all of the 'Old Settings' with the 'New Settings'. Hold down the 'ctrl key' to select/deselect multiple.</td>
|
520 |
</tr>
|
521 |
<tr>
|
522 |
-
<td>Activate Plugins</td>
|
523 |
<td>These plug-ins are the plug-ins that were activated when the package was created and represent the plug-ins that will be activated after the install.</td>
|
524 |
</tr>
|
525 |
<tr>
|
526 |
-
<td>Update email domains</td>
|
527 |
<td>The domain portion of all email addresses will be updated if this option is enabled.</td>
|
528 |
</tr>
|
529 |
<tr>
|
530 |
-
<td>Full Search</td>
|
531 |
<td>Full search forces a scan of every single cell in the database. If it is not checked then only text based columns are searched which makes the update process much faster.
|
532 |
Use this option if you have issues with data not updating correctly.</td>
|
533 |
</tr>
|
534 |
<tr>
|
535 |
-
<td>Post GUID</td>
|
536 |
<td>If your moving a site keep this value checked. For more details see the <a href="http://codex.wordpress.org/Changing_The_Site_URL#Important_GUID_Note" target="_blank">notes on GUIDS</a>. Changing values in the posts table GUID column can change RSS readers to evaluate that the posts are new and may show them in feeds again.</td>
|
537 |
</tr>
|
538 |
<tr>
|
539 |
-
<td>Cross search <sup>pro</sup></td>
|
540 |
<td>
|
541 |
This option enables the searching and replacing of subsite domains and paths that link to each other. <br>
|
542 |
Check this option if hyperlinks of at least one subsite point to another subsite.<br>
|
543 |
Uncheck this option there if there are at least <?php echo MAX_SITES_TO_DEFAULT_ENABLE_CORSS_SEARCH ?> subsites and no subsites hyperlinking to each other (Checking this option in this scenario would unnecessarily load your server).<br><br>
|
544 |
Check this option If you unsure if you need this option.<br></td>
|
545 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
546 |
<tr>
|
547 |
<td colspan="2" class="section">WP-Config File</td>
|
548 |
</tr>
|
549 |
<tr>
|
550 |
-
<td>Config SSL</td>
|
551 |
<td>Turn off SSL support for WordPress. This sets FORCE_SSL_ADMIN in your wp-config file to false if true, otherwise it will create the setting if not set. The "Enforce on Login"
|
552 |
will turn off SSL support for WordPress Logins.</td>
|
553 |
</tr>
|
554 |
<tr>
|
555 |
-
<td>Config Cache</td>
|
556 |
<td>Turn off Cache support for WordPress. This sets WP_CACHE in your wp-config file to false if true, otherwise it will create the setting if not set. The "Keep Home Path"
|
557 |
sets WPCACHEHOME in your wp-config file to nothing if true, otherwise nothing is changed.</td>
|
558 |
</tr>
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
+
//The help for both pro and lite are shared. Pro is where the master lives. Use the flag below to
|
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">
|
11 |
+
HELP
|
12 |
+
</div>
|
13 |
<!-- =========================================
|
14 |
HELP FORM -->
|
15 |
<div id="main-help">
|
38 |
|
39 |
<table class="help-opt">
|
40 |
<tr>
|
41 |
+
<th class="col-opt">Option</th>
|
42 |
<th>Details</th>
|
43 |
</tr>
|
44 |
<tr>
|
45 |
+
<td class="col-opt">Locked</td>
|
46 |
<td>
|
47 |
"Locked" means a password is protecting each step of the installer. This option is recommended on all installers
|
48 |
that are accessible via a public URL but not required.
|
49 |
</td>
|
50 |
</tr>
|
51 |
<tr>
|
52 |
+
<td class="col-opt">Unlocked</td>
|
53 |
<td>
|
54 |
"Unlocked" means that if your installer is on a public server that anyone can access it. This is a less secure way to run your installer. If you are running the
|
55 |
installer very quickly then removing all the installer files, then the chances of exposing it is going to be low depending on your sites access history.
|
85 |
|
86 |
<table class="help-opt">
|
87 |
<tr>
|
88 |
+
<th class="col-opt">Option</th>
|
89 |
<th>Details</th>
|
90 |
</tr>
|
91 |
<tr>
|
92 |
+
<td class="col-opt">Standard Install</td>
|
93 |
<td>
|
94 |
This mode indicates that the installer and archive have been placed into an empty directory and the site is ready for a fresh/new redeployment.
|
95 |
This is the most common mode and the mode that has been around the longest.
|
96 |
</td>
|
97 |
</tr>
|
98 |
<tr>
|
99 |
+
<td class="col-opt">Standard Install <br/> Database Only</td>
|
100 |
<td>
|
101 |
This mode indicates that the installer and archive were manually moved or transferred to a location and that only the Database will be installed
|
102 |
at this location.
|
103 |
</td>
|
104 |
</tr>
|
105 |
<tr>
|
106 |
+
<td class="col-opt">Overwrite Install <sup>pro</sup></td>
|
107 |
<td>
|
108 |
This mode indicates that the installer was started in a location that contains an existing site. With this mode <b>the existing site will be overwritten</b> with
|
109 |
the contents of the archive.zip/daf and the database.sql file. This is an advanced option and users should be pre-paired to know that state of their database
|
111 |
</td>
|
112 |
</tr>
|
113 |
<tr>
|
114 |
+
<td class="col-opt">Overwrite Install <br/> Database Only <sup>pro</sup></td>
|
115 |
<td>
|
116 |
This mode indicates that the installer was started in a location that contains an existing site. With this mode <b>the existing site will be overwritten</b> with
|
117 |
the contents of the database.sql file. This is an advanced option and users should be pre-paired to know that state of their database and site files ahead of time.
|
151 |
The options for step 1 can help better prepare your site should your server need additional settings beyond most general configuration.
|
152 |
<table class="help-opt">
|
153 |
<tr>
|
154 |
+
<th class="col-opt">Option</th>
|
155 |
<th>Details</th>
|
156 |
</tr>
|
157 |
<tr>
|
158 |
<td colspan="2" class="section">General Options</td>
|
159 |
</tr>
|
160 |
<tr>
|
161 |
+
<td class="col-opt">Extraction</td>
|
162 |
<td>
|
163 |
<b>Manual Archive Extraction</b><br/>
|
164 |
Set the Extraction value to "Manual Archive Extraction" when the archive file has already been manually extracted on the server. This can be done through your hosts
|
178 |
</td>
|
179 |
</tr>
|
180 |
<tr>
|
181 |
+
<td class="col-opt">Permissions</td>
|
182 |
<td>
|
183 |
<b>All Files:</b> Check the 'All Files' check-box and enter in the desired <a href="http://php.net/manual/en/function.chmod.php" target="_blank">chmod command</a>
|
184 |
to recursively set the octal value on all the files being extracted. Typically this value is 644 on most servers and hosts.
|
194 |
<td colspan="2" class="section">Advanced Options</td>
|
195 |
</tr>
|
196 |
<tr>
|
197 |
+
<td class="col-opt">Safe Mode</td>
|
198 |
<td>
|
199 |
Safe mode is designed to configure the site with specific options at install time to help over come issues that may happen during the install were the site
|
200 |
is having issues. These options should only be used if you run into issues after you have tried to run an install.
|
208 |
</td>
|
209 |
</tr>
|
210 |
<tr>
|
211 |
+
<td class="col-opt">Config Files </td>
|
212 |
<td>
|
213 |
When dealing with configuration files (.htaccess, web.config and .user.ini) the installer can apply different modes:
|
214 |
<br/><br/>
|
237 |
</tr>
|
238 |
|
239 |
<tr>
|
240 |
+
<td class="col-opt">File Times</td>
|
241 |
<td>When the archive is extracted should it show the current date-time or keep the original time it had when it was built. This setting will be applied to
|
242 |
all files and directories.</td>
|
243 |
</tr>
|
244 |
<tr>
|
245 |
+
<td class="col-opt">Logging</td>
|
246 |
<td>
|
247 |
The level of detail that will be sent to the log file (installer-log.txt). The recommend setting for most installs should be 'Light'.
|
248 |
Note if you use Debug the amount of data written can be very large. Debug is only recommended for support.
|
283 |
<i>The cPanel connectivity option is only available for Duplicator Pro.</i>
|
284 |
<table class="help-opt">
|
285 |
<tr>
|
286 |
+
<th class="col-opt">Option</th>
|
287 |
<th>Details</th>
|
288 |
</tr>
|
289 |
<tr>
|
290 |
+
<td class="col-opt">Host</td>
|
291 |
<td>This should be the primary domain account URL that is associated with your host. Most hosts will require you to register a primary domain name.
|
292 |
This should be the URL that you place in the host field. For example if your primary domain name is "mysite.com" then you would enter in
|
293 |
"https://mysite.com:2083". The port 2038 is the common port number that cPanel works on. If you do not know your primary domain name please contact your
|
294 |
hosting provider or server administrator.</td>
|
295 |
</tr>
|
296 |
<tr>
|
297 |
+
<td class="col-opt">Username</td>
|
298 |
<td>The cPanel username used to login to your cPanel account. <i>This is <b>not</b> the same thing as your WordPress administrator account</i>.
|
299 |
If your unsure of this name please contact your hosting provider or server administrator.</td>
|
300 |
</tr>
|
301 |
<tr>
|
302 |
+
<td class="col-opt">Password</td>
|
303 |
<td>The password of the cPanel user</td>
|
304 |
</tr>
|
305 |
<tr>
|
306 |
+
<td class="col-opt">Troubleshoot</td>
|
307 |
<td>
|
308 |
<b>Common cPanel Connection Issues:</b><br/>
|
309 |
- Your host does not use <a href="http://cpanel.com/" target="_blank">cPanel Software</a> <br/>
|
320 |
The database setup options allow you to connect to an existing database or in the case of cPanel connect or create a new database.
|
321 |
<table class="help-opt">
|
322 |
<tr>
|
323 |
+
<th class="col-opt">Option</th>
|
324 |
<th>Details</th>
|
325 |
</tr>
|
326 |
<tr>
|
327 |
+
<td class="col-opt">Action</td>
|
328 |
<td>
|
329 |
<b>Create New Database:</b> Will attempt to create a new database if it does not exist. When using the 'Basic' option this option will not work on many
|
330 |
hosting providers as the ability to create new databases is normally locked down. If the database does not exist then you will need to login to your
|
348 |
</td>
|
349 |
</tr>
|
350 |
<tr>
|
351 |
+
<td class="col-opt">Host</td>
|
352 |
<td>The name of the host server that the database resides on. Many times this will be 'localhost', however each hosting provider will have it's own naming
|
353 |
convention please check with your server administrator or host to valid for sure the name needed. To add a port number just append it to the host i.e.
|
354 |
'localhost:3306'.</td>
|
355 |
</tr>
|
356 |
<tr>
|
357 |
+
<td class="col-opt">Database</td>
|
358 |
<td>The name of the database to which this installation will connect and install the new tables and data into. Some hosts will require a prefix while others
|
359 |
do not. Be sure to know exactly how your host requires the database name to be entered.</td>
|
360 |
</tr>
|
361 |
<tr>
|
362 |
+
<td class="col-opt">User</td>
|
363 |
<td>The name of a MySQL database server user. This is special account that has privileges to access a database and can read from or write to that database.
|
364 |
<i>This is <b>not</b> the same thing as your WordPress administrator account</i>.</td>
|
365 |
</tr>
|
366 |
<tr>
|
367 |
+
<td class="col-opt">Password</td>
|
368 |
<td>The password of the MySQL database server user.</td>
|
369 |
</tr>
|
370 |
|
375 |
<h3>Options</h3>
|
376 |
<table class="help-opt">
|
377 |
<tr>
|
378 |
+
<th class="col-opt">Option</th>
|
379 |
<th>Details</th>
|
380 |
</tr>
|
381 |
<tr>
|
382 |
+
<td class="col-opt">Prefix<sup>pro*</sup></td>
|
383 |
<td>By default, databases are prefixed with the cPanel account's username (for example, myusername_databasename). However you can ignore this option if
|
384 |
your host does not use the default cPanel username prefix schema. Check the 'Ignore cPanel Prefix' and the username prefixes will be ignored.
|
385 |
This will still require you to enter in the cPanels required setup prefix if they require one. The checkbox will be set to read-only if your host has
|
386 |
disabled prefix settings. Please see your host full requirements when using the cPanel options.</td>
|
387 |
</tr>
|
388 |
<tr>
|
389 |
+
<td class="col-opt">Legacy</td>
|
390 |
<td>When creating a database table, the Mysql version being used may not support the collation type of the Mysql version where the table was created.
|
391 |
In this scenario, the installer will fallback to a legacy collation type to try and create the table. This value should only be checked if you receive an error when
|
392 |
testing the database.
|
400 |
</td>
|
401 |
</tr>
|
402 |
<tr>
|
403 |
+
<td class="col-opt">Spacing</td>
|
404 |
<td>The process will remove utf8 characters represented as 'xC2' 'xA0' and replace with a uniform space. Use this option if you find strange question
|
405 |
marks in you posts</td>
|
406 |
</tr>
|
407 |
<tr>
|
408 |
+
<td class="col-opt">Mode</td>
|
409 |
<td>The MySQL mode option will allow you to set the mode for this session. It is very useful when running into conversion issues. For a full overview please
|
410 |
see the <a href="https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html" target="_blank">MySQL mode documentation</a> specific to your version.</td>
|
411 |
</tr>
|
412 |
<tr>
|
413 |
+
<td class="col-opt">Charset</td>
|
414 |
<td>When the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your
|
415 |
databases character set should be.</td>
|
416 |
</tr>
|
417 |
<tr>
|
418 |
+
<td class="col-opt">Collation</td>
|
419 |
<td>When the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your
|
420 |
databases collation set should be.</td>
|
421 |
</tr>
|
428 |
|
429 |
<table class="help-opt">
|
430 |
<tr>
|
431 |
+
<th class="col-opt">Option</th>
|
432 |
<th>Details</th>
|
433 |
</tr>
|
434 |
<tr>
|
435 |
+
<td class="col-opt">Test<br/>Database</td>
|
436 |
<td>
|
437 |
The 'Test Database' button will help validate if the connection parameters are correct for this server and help with details about any issues
|
438 |
that may arise.
|
439 |
</td>
|
440 |
</tr>
|
441 |
<tr>
|
442 |
+
<td class="col-opt">Troubleshoot</td>
|
443 |
<td>
|
444 |
<b>Common Database Connection Issues:</b><br/>
|
445 |
- Double check case sensitive values 'User', 'Password' & the 'Database Name' <br/>
|
484 |
<h3>Options</h3>
|
485 |
<table class="help-opt">
|
486 |
<tr>
|
487 |
+
<th class="col-opt">Option</th>
|
488 |
<th>Details</th>
|
489 |
</tr>
|
490 |
<tr>
|
491 |
<td colspan="2" class="section">New Admin Account</td>
|
492 |
</tr>
|
493 |
<tr>
|
494 |
+
<td class="col-opt">Username</td>
|
495 |
<td>A new WordPress username to create. This will create a new WordPress administrator account. Please note that usernames are not changeable from the within the UI.</td>
|
496 |
</tr>
|
497 |
<tr>
|
498 |
+
<td class="col-opt">Password</td>
|
499 |
<td>The new password for the new user. Must be at least 6 characters long.</td>
|
500 |
</tr>
|
501 |
<tr>
|
502 |
<td colspan="2" class="section">Scan Options</td>
|
503 |
</tr>
|
504 |
<tr>
|
505 |
+
<td class="col-opt">Cleanup <sup>pro</sup></td>
|
506 |
<td>The checkbox labeled Remove schedules & storage endpoints will empty the Duplicator schedule and storage settings. This is recommended to keep enabled so that you do not have unwanted schedules and storage options enabled.</td>
|
507 |
</tr>
|
508 |
<tr>
|
509 |
+
<td class="col-opt">Old URL</td>
|
510 |
<td>The old URL of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons</td>
|
511 |
</tr>
|
512 |
<tr>
|
513 |
+
<td class="col-opt">Old Path</td>
|
514 |
<td>The old path of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons</td>
|
515 |
</tr>
|
516 |
<tr>
|
517 |
+
<td class="col-opt">Site URL</td>
|
518 |
<td> For details see WordPress <a href="http://codex.wordpress.org/Changing_The_Site_URL" target="_blank">Site URL</a> & <a href="http://codex.wordpress.org/Giving_WordPress_Its_Own_Directory" target="_blank">Alternate Directory</a>. If you're not sure about this value then leave it the same as the new settings URL.</td>
|
519 |
</tr>
|
520 |
<tr>
|
521 |
+
<td class="col-opt">Scan Tables</td>
|
522 |
<td>Select the tables to be updated. This process will update all of the 'Old Settings' with the 'New Settings'. Hold down the 'ctrl key' to select/deselect multiple.</td>
|
523 |
</tr>
|
524 |
<tr>
|
525 |
+
<td class="col-opt">Activate Plugins</td>
|
526 |
<td>These plug-ins are the plug-ins that were activated when the package was created and represent the plug-ins that will be activated after the install.</td>
|
527 |
</tr>
|
528 |
<tr>
|
529 |
+
<td class="col-opt">Update email domains</td>
|
530 |
<td>The domain portion of all email addresses will be updated if this option is enabled.</td>
|
531 |
</tr>
|
532 |
<tr>
|
533 |
+
<td class="col-opt">Full Search</td>
|
534 |
<td>Full search forces a scan of every single cell in the database. If it is not checked then only text based columns are searched which makes the update process much faster.
|
535 |
Use this option if you have issues with data not updating correctly.</td>
|
536 |
</tr>
|
537 |
<tr>
|
538 |
+
<td class="col-opt">Post GUID</td>
|
539 |
<td>If your moving a site keep this value checked. For more details see the <a href="http://codex.wordpress.org/Changing_The_Site_URL#Important_GUID_Note" target="_blank">notes on GUIDS</a>. Changing values in the posts table GUID column can change RSS readers to evaluate that the posts are new and may show them in feeds again.</td>
|
540 |
</tr>
|
541 |
<tr>
|
542 |
+
<td class="col-opt">Cross search <sup>pro</sup></td>
|
543 |
<td>
|
544 |
This option enables the searching and replacing of subsite domains and paths that link to each other. <br>
|
545 |
Check this option if hyperlinks of at least one subsite point to another subsite.<br>
|
546 |
Uncheck this option there if there are at least <?php echo MAX_SITES_TO_DEFAULT_ENABLE_CORSS_SEARCH ?> subsites and no subsites hyperlinking to each other (Checking this option in this scenario would unnecessarily load your server).<br><br>
|
547 |
Check this option If you unsure if you need this option.<br></td>
|
548 |
</tr>
|
549 |
+
<tr>
|
550 |
+
<td class="col-opt"> Max size check for serialize objects</td>
|
551 |
+
<td>
|
552 |
+
Large serialized objects can cause a fatal error when Duplicator attempts to transform them. <br>
|
553 |
+
If a fatal error is generated, lower this limit. <br>
|
554 |
+
If a warning of this type appears in the final report <br>
|
555 |
+
<pre style="white-space: pre-line;">
|
556 |
+
DATA-REPLACE ERROR: Serialization
|
557 |
+
ENGINE: serialize data too big to convert; data len: XXX Max size: YYY
|
558 |
+
DATA: .....
|
559 |
+
</pre>
|
560 |
+
And you think that the serialized object is necessary you can increase the limit or <b>set it to 0 to have no limit</b>.
|
561 |
+
</td>
|
562 |
+
</tr>
|
563 |
<tr>
|
564 |
<td colspan="2" class="section">WP-Config File</td>
|
565 |
</tr>
|
566 |
<tr>
|
567 |
+
<td class="col-opt">Config SSL</td>
|
568 |
<td>Turn off SSL support for WordPress. This sets FORCE_SSL_ADMIN in your wp-config file to false if true, otherwise it will create the setting if not set. The "Enforce on Login"
|
569 |
will turn off SSL support for WordPress Logins.</td>
|
570 |
</tr>
|
571 |
<tr>
|
572 |
+
<td class="col-opt">Config Cache</td>
|
573 |
<td>Turn off Cache support for WordPress. This sets WP_CACHE in your wp-config file to false if true, otherwise it will create the setting if not set. The "Keep Home Path"
|
574 |
sets WPCACHEHOME in your wp-config file to nothing if true, otherwise nothing is changed.</td>
|
575 |
</tr>
|
installer/dup-installer/views/view.s1.base.php
CHANGED
@@ -658,9 +658,10 @@ OPTIONS
|
|
658 |
<tr>
|
659 |
<td>Logging:</td>
|
660 |
<td>
|
661 |
-
|
662 |
-
|
663 |
-
|
|
|
664 |
</td>
|
665 |
</tr>
|
666 |
<?php if(!$archive_config->isZipArchive()): ?>
|
658 |
<tr>
|
659 |
<td>Logging:</td>
|
660 |
<td>
|
661 |
+
<input type="radio" name="logging" id="logging-light" value="<?php echo DUPX_Log::LV_DEFAULT; ?>" checked="true"> <label for="logging-light" class="radio">Light</label>
|
662 |
+
<input type="radio" name="logging" id="logging-detailed" value="<?php echo DUPX_Log::LV_DETAILED; ?>"> <label for="logging-detailed" class="radio">Detailed</label>
|
663 |
+
<input type="radio" name="logging" id="logging-debug" value="<?php echo DUPX_Log::LV_DEBUG; ?>"> <label for="logging-debug" class="radio">Debug</label>
|
664 |
+
<input type="radio" name="logging" id="logging-h-debug" value="<?php echo DUPX_Log::LV_HARD_DEBUG; ?>"> <label for="logging-h-debug" class="radio">Hard debug</label>
|
665 |
</td>
|
666 |
</tr>
|
667 |
<?php if(!$archive_config->isZipArchive()): ?>
|
installer/dup-installer/views/view.s3.php
CHANGED
@@ -281,6 +281,14 @@ VIEW: STEP 3- INPUT -->
|
|
281 |
<input type="checkbox" name="search_replace_email_domain" id="search_replace_email_domain" value="1" /> <label for="search_replace_email_domain">Update email domains</label><br/>
|
282 |
<input type="checkbox" name="fullsearch" id="fullsearch" value="1" /> <label for="fullsearch">Use Database Full Search Mode</label><br/>
|
283 |
<input type="checkbox" name="postguid" id="postguid" value="1" /> <label for="postguid">Keep Post GUID Unchanged</label><br/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
284 |
<br/><br/>
|
285 |
</div>
|
286 |
|
@@ -594,6 +602,8 @@ DUPX.hideErrorResult2 = function()
|
|
594 |
//DOCUMENT LOAD
|
595 |
$(document).ready(function()
|
596 |
{
|
|
|
|
|
597 |
$("#tabs").tabs();
|
598 |
DUPX.getNewURL('url_new');
|
599 |
DUPX.getNewURL('siteurl');
|
281 |
<input type="checkbox" name="search_replace_email_domain" id="search_replace_email_domain" value="1" /> <label for="search_replace_email_domain">Update email domains</label><br/>
|
282 |
<input type="checkbox" name="fullsearch" id="fullsearch" value="1" /> <label for="fullsearch">Use Database Full Search Mode</label><br/>
|
283 |
<input type="checkbox" name="postguid" id="postguid" value="1" /> <label for="postguid">Keep Post GUID Unchanged</label><br/>
|
284 |
+
<label>
|
285 |
+
<B>Max size check for serialize objects:</b>
|
286 |
+
<input type="number"
|
287 |
+
name="<?php echo DUPX_CTRL::NAME_MAX_SERIALIZE_STRLEN_IN_M; ?>"
|
288 |
+
value="<?php echo DUPX_Constants::DEFAULT_MAX_STRLEN_SERIALIZED_CHECK_IN_M; ?>"
|
289 |
+
min="0" max="99" step="1" size="2"
|
290 |
+
style="width: 40px;width: 50px; text-align: center;" /> MB
|
291 |
+
</label>
|
292 |
<br/><br/>
|
293 |
</div>
|
294 |
|
602 |
//DOCUMENT LOAD
|
603 |
$(document).ready(function()
|
604 |
{
|
605 |
+
$('#wp_username').val('');
|
606 |
+
$('#wp_password').val('');
|
607 |
$("#tabs").tabs();
|
608 |
DUPX.getNewURL('url_new');
|
609 |
DUPX.getNewURL('siteurl');
|
installer/dup-installer/views/view.s4.php
CHANGED
@@ -285,6 +285,7 @@ LONGMSG;
|
|
285 |
}
|
286 |
|
287 |
$nManager->sortFinalReport();
|
|
|
288 |
?>
|
289 |
|
290 |
<div class="s4-go-back">
|
285 |
}
|
286 |
|
287 |
$nManager->sortFinalReport();
|
288 |
+
$nManager->finalReportLog(array('general','files','database','search_replace'));
|
289 |
?>
|
290 |
|
291 |
<div class="s4-go-back">
|
installer/installer.tpl
CHANGED
@@ -1,9 +1,13 @@
|
|
1 |
<?php
|
|
|
2 |
|
3 |
-
|
4 |
-
|
5 |
-
}
|
6 |
|
|
|
|
|
|
|
|
|
7 |
if (!defined('KB_IN_BYTES')) { define('KB_IN_BYTES', 1024); }
|
8 |
if (!defined('MB_IN_BYTES')) { define('MB_IN_BYTES', 1024 * KB_IN_BYTES); }
|
9 |
if (!defined('GB_IN_BYTES')) { define('GB_IN_BYTES', 1024 * MB_IN_BYTES); }
|
@@ -25,7 +29,6 @@ if (!function_exists('wp_is_ini_value_changeable')) {
|
|
25 |
*/
|
26 |
function wp_is_ini_value_changeable( $setting ) {
|
27 |
static $ini_all;
|
28 |
-
|
29 |
if ( ! isset( $ini_all ) ) {
|
30 |
$ini_all = false;
|
31 |
// Sometimes `ini_get_all()` is disabled via the `disable_functions` option for "security purposes".
|
@@ -57,132 +60,8 @@ if (wp_is_ini_value_changeable('pcre.backtrack_limit'))
|
|
57 |
@ini_set('pcre.backtrack_limit', PHP_INT_MAX);
|
58 |
if (wp_is_ini_value_changeable('default_socket_timeout'))
|
59 |
@ini_set('default_socket_timeout', 3600);
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
/** Session var name
|
64 |
-
* @var string
|
65 |
-
*/
|
66 |
-
public static $prefix = '_DUPX_CSRF';
|
67 |
-
private static $CSRFVars;
|
68 |
-
|
69 |
-
public static function setKeyVal($key, $val) {
|
70 |
-
$CSRFVars = self::getCSRFVars();
|
71 |
-
$CSRFVars[$key] = $val;
|
72 |
-
self::saveCSRFVars($CSRFVars);
|
73 |
-
self::$CSRFVars = false;
|
74 |
-
}
|
75 |
-
|
76 |
-
public static function getVal($key) {
|
77 |
-
$CSRFVars = self::getCSRFVars();
|
78 |
-
if (isset($CSRFVars[$key])) {
|
79 |
-
return $CSRFVars[$key];
|
80 |
-
} else {
|
81 |
-
return false;
|
82 |
-
}
|
83 |
-
|
84 |
-
}
|
85 |
-
|
86 |
-
/** Generate DUPX_CSRF value for form
|
87 |
-
* @param string $form - Form name as session key
|
88 |
-
* @return string - token
|
89 |
-
*/
|
90 |
-
public static function generate($form = NULL) {
|
91 |
-
$keyName = self::getKeyName($form);
|
92 |
-
|
93 |
-
$existingToken = self::getVal($keyName);
|
94 |
-
if (false !== $existingToken) {
|
95 |
-
$token = $existingToken;
|
96 |
-
} else {
|
97 |
-
$token = DUPX_CSRF::token() . DUPX_CSRF::fingerprint();
|
98 |
-
}
|
99 |
-
|
100 |
-
self::setKeyVal($keyName, $token);
|
101 |
-
return $token;
|
102 |
-
}
|
103 |
-
|
104 |
-
/** Check DUPX_CSRF value of form
|
105 |
-
* @param string $token - Token
|
106 |
-
* @param string $form - Form name as session key
|
107 |
-
* @return boolean
|
108 |
-
*/
|
109 |
-
public static function check($token, $form = NULL) {
|
110 |
-
$keyName = self::getKeyName($form);
|
111 |
-
$CSRFVars = self::getCSRFVars();
|
112 |
-
if (isset($CSRFVars[$keyName]) && $CSRFVars[$keyName] == $token) { // token OK
|
113 |
-
return true;
|
114 |
-
}
|
115 |
-
return FALSE;
|
116 |
-
}
|
117 |
-
|
118 |
-
/** Generate token
|
119 |
-
* @param void
|
120 |
-
* @return string
|
121 |
-
*/
|
122 |
-
protected static function token() {
|
123 |
-
mt_srand((double) microtime() * 10000);
|
124 |
-
$charid = strtoupper(md5(uniqid(rand(), TRUE)));
|
125 |
-
return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);
|
126 |
-
}
|
127 |
-
|
128 |
-
/** Returns "digital fingerprint" of user
|
129 |
-
* @param void
|
130 |
-
* @return string - MD5 hashed data
|
131 |
-
*/
|
132 |
-
protected static function fingerprint() {
|
133 |
-
return strtoupper(md5(implode('|', array($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']))));
|
134 |
-
}
|
135 |
-
|
136 |
-
private static function getKeyName($form) {
|
137 |
-
return DUPX_CSRF::$prefix . '_' . $form;
|
138 |
-
}
|
139 |
-
|
140 |
-
private static function getPackageHash() {
|
141 |
-
if (class_exists('DUPX_Bootstrap')) {
|
142 |
-
return DUPX_Bootstrap::PACKAGE_HASH;
|
143 |
-
} else {
|
144 |
-
return $GLOBALS['DUPX_AC']->package_hash;
|
145 |
-
}
|
146 |
-
}
|
147 |
-
|
148 |
-
private static function getFilePath() {
|
149 |
-
if (class_exists('DUPX_Bootstrap')) {
|
150 |
-
$dupInstallerfolderPath = dirname(__FILE__).'/dup-installer/';
|
151 |
-
} else {
|
152 |
-
$dupInstallerfolderPath = $GLOBALS['DUPX_INIT'].'/';
|
153 |
-
}
|
154 |
-
$packageHash = self::getPackageHash();
|
155 |
-
$fileName = 'dup-installer-csrf__'.$packageHash.'.txt';
|
156 |
-
$filePath = $dupInstallerfolderPath.$fileName;
|
157 |
-
return $filePath;
|
158 |
-
}
|
159 |
-
|
160 |
-
private static function getCSRFVars() {
|
161 |
-
if (!isset(self::$CSRFVars) || false === self::$CSRFVars) {
|
162 |
-
$filePath = self::getFilePath();
|
163 |
-
if (file_exists($filePath)) {
|
164 |
-
$contents = file_get_contents($filePath);
|
165 |
-
if (empty($contents)) {
|
166 |
-
self::$CSRFVars = array();
|
167 |
-
} else {
|
168 |
-
$CSRFobjs = json_decode($contents);
|
169 |
-
foreach ($CSRFobjs as $key => $value) {
|
170 |
-
self::$CSRFVars[$key] = $value;
|
171 |
-
}
|
172 |
-
}
|
173 |
-
} else {
|
174 |
-
self::$CSRFVars = array();
|
175 |
-
}
|
176 |
-
}
|
177 |
-
return self::$CSRFVars;
|
178 |
-
}
|
179 |
-
|
180 |
-
private static function saveCSRFVars($CSRFVars) {
|
181 |
-
$contents = json_encode($CSRFVars);
|
182 |
-
$filePath = self::getFilePath();
|
183 |
-
file_put_contents($filePath, $contents);
|
184 |
-
}
|
185 |
-
}
|
186 |
|
187 |
/**
|
188 |
* Bootstrap utility to exatract the core installer
|
@@ -197,6 +76,8 @@ class DUPX_CSRF {
|
|
197 |
* installer.php?unzipmode=ziparchive
|
198 |
* installer.php?unzipmode=shellexec
|
199 |
*/
|
|
|
|
|
200 |
|
201 |
abstract class DUPX_Bootstrap_Zip_Mode
|
202 |
{
|
@@ -205,13 +86,6 @@ abstract class DUPX_Bootstrap_Zip_Mode
|
|
205 |
const ShellExec = 2;
|
206 |
}
|
207 |
|
208 |
-
abstract class DUPX_Connectivity
|
209 |
-
{
|
210 |
-
const OK = 0;
|
211 |
-
const Error = 1;
|
212 |
-
const Unknown = 2;
|
213 |
-
}
|
214 |
-
|
215 |
class DUPX_Bootstrap
|
216 |
{
|
217 |
//@@ Params get dynamically swapped when package is built
|
@@ -237,6 +111,9 @@ class DUPX_Bootstrap
|
|
237 |
*/
|
238 |
public function __construct()
|
239 |
{
|
|
|
|
|
|
|
240 |
//ARCHIVE_SIZE will be blank with a root filter so we can estimate
|
241 |
//the default size of the package around 17.5MB (18088000)
|
242 |
$archiveActualSize = @filesize(self::ARCHIVE_FILENAME);
|
@@ -266,7 +143,7 @@ class DUPX_Bootstrap
|
|
266 |
public function run()
|
267 |
{
|
268 |
date_default_timezone_set('UTC'); // Some machines don't have this set so just do it here
|
269 |
-
|
270 |
self::log('==DUPLICATOR INSTALLER BOOTSTRAP v@@VERSION@@==');
|
271 |
self::log('----------------------------------------------------');
|
272 |
self::log('Installer bootstrap start');
|
@@ -298,7 +175,7 @@ class DUPX_Bootstrap
|
|
298 |
|
299 |
//MISSING ARCHIVE FILE
|
300 |
if (! file_exists($archive_filepath)) {
|
301 |
-
self::log("ERROR
|
302 |
$archive_candidates = ($isZip) ? $this->getFilesWithExtension('zip') : $this->getFilesWithExtension('daf');
|
303 |
$candidate_count = count($archive_candidates);
|
304 |
$candidate_html = "- No {$archive_extension} files found -";
|
@@ -306,12 +183,17 @@ class DUPX_Bootstrap
|
|
306 |
if ($candidate_count >= 1) {
|
307 |
$candidate_html = "<ol>";
|
308 |
foreach($archive_candidates as $archive_candidate) {
|
309 |
-
$
|
|
|
310 |
}
|
311 |
$candidate_html .= "</ol>";
|
312 |
}
|
313 |
|
314 |
-
$error = "<
|
|
|
|
|
|
|
|
|
315 |
. "The archive file name must be the <u>exact</u> name of the archive file placed in the extraction path character for character.<br/><br/> "
|
316 |
. "If the file does not have the correct name then rename it to the <i>'Required File'</i> below. When downloading the package files make "
|
317 |
. "sure both files are from the same package line in the packages view. If the archive is not finished downloading please wait for it to complete.<br/><br/>"
|
@@ -324,33 +206,34 @@ class DUPX_Bootstrap
|
|
324 |
return $error;
|
325 |
}
|
326 |
|
327 |
-
if (!
|
328 |
-
|
329 |
-
$os_first_three_chars = substr(PHP_OS, 0, 3);
|
330 |
-
$os_first_three_chars = strtoupper($os_first_three_chars);
|
331 |
$no_of_bits = PHP_INT_SIZE * 8;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
}
|
339 |
-
} else { // DAF
|
340 |
-
if ('WIN' === $os_first_three_chars) {
|
341 |
-
$error = 'Windows PHP limitations prevents extraction of archives larger than 2GB. Please do the following: <ol><li>Download and use the <a target="_blank" href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-052-q">Windows DupArchive extractor</a> to extract all files from the archive.</li><li>Perform a <a target="_blank" href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-015-q">Manual Extract Install</a> starting at step 4.</li></ol>';
|
342 |
-
} else {
|
343 |
-
$error = 'This archive is too large for 32-bit PHP. Ask your host to upgrade the server to 64-bit PHP or install on another system has 64-bit PHP.';
|
344 |
-
}
|
345 |
-
return $error;
|
346 |
-
}
|
347 |
-
}
|
348 |
}
|
349 |
|
350 |
//SIZE CHECK ERROR
|
351 |
if (($this->archiveRatio < 90) && ($this->archiveActualSize > 0) && ($this->archiveExpectedSize > 0)) {
|
352 |
$this->log("ERROR: The expected archive size should be around [{$archiveExpectedEasy}]. The actual size is currently [{$archiveActualEasy}].");
|
353 |
-
$this->log("The archive file may not have fully been downloaded to the server");
|
354 |
$percent = round($this->archiveRatio);
|
355 |
|
356 |
$autochecked = isset($_POST['auto-fresh']) ? "checked='true'" : '';
|
@@ -373,20 +256,18 @@ class DUPX_Bootstrap
|
|
373 |
if ($manual_extract_found) {
|
374 |
// INSTALL DIRECTORY: Check if its setup correctly AND we are not in overwrite mode
|
375 |
if (isset($_GET['force-extract-installer']) && ('1' == $_GET['force-extract-installer'] || 'enable' == $_GET['force-extract-installer'] || 'false' == $_GET['force-extract-installer'])) {
|
376 |
-
|
377 |
self::log("Manual extract found with force extract installer get parametr");
|
378 |
$extract_installer = true;
|
379 |
-
|
380 |
} else {
|
381 |
$extract_installer = false;
|
382 |
self::log("Manual extract found so not going to extract dup-installer dir");
|
383 |
}
|
384 |
} else {
|
385 |
$extract_installer = true;
|
386 |
-
self::log("Manual extract didn't found so going to extract dup-installer dir");
|
387 |
}
|
388 |
|
389 |
if ($extract_installer && file_exists($installer_directory)) {
|
|
|
390 |
$scanned_directory = array_diff(scandir($installer_directory), array('..', '.'));
|
391 |
foreach ($scanned_directory as $object) {
|
392 |
$object_file_path = $installer_directory.'/'.$object;
|
@@ -394,7 +275,7 @@ class DUPX_Bootstrap
|
|
394 |
if (unlink($object_file_path)) {
|
395 |
self::log('Successfully deleted the file '.$object_file_path);
|
396 |
} else {
|
397 |
-
$error .= 'Error deleting the file '.$object_file_path.' Please manually delete it and try again.';
|
398 |
self::log($error);
|
399 |
}
|
400 |
}
|
@@ -410,20 +291,20 @@ class DUPX_Bootstrap
|
|
410 |
$destination = dirname(__FILE__);
|
411 |
if (!is_writable($destination)) {
|
412 |
self::log("destination folder for extraction is not writable");
|
413 |
-
if (
|
414 |
-
self::log("Permission of destination folder changed to
|
415 |
} else {
|
416 |
-
self::log("Permission of destination folder failed to change to
|
417 |
}
|
418 |
}
|
419 |
|
420 |
if (!is_writable($destination)) {
|
|
|
421 |
$error = "NOTICE: The {$destination} directory is not writable on this server please talk to your host or server admin about making ";
|
422 |
$error .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-055-q'>writable {$destination} directory</a> on this server. <br/>";
|
423 |
return $error;
|
424 |
}
|
425 |
|
426 |
-
|
427 |
if ($isZip) {
|
428 |
$zip_mode = $this->getZipMode();
|
429 |
|
@@ -436,11 +317,11 @@ class DUPX_Bootstrap
|
|
436 |
self::log('Successfully extracted with ZipArchive');
|
437 |
} else {
|
438 |
if (0 == $this->installer_files_found) {
|
439 |
-
$error = "This archive is not properly formatted and does not contain a dup-installer directory. Please make sure you are attempting to install the original archive and not one that has been reconstructed.";
|
440 |
self::log($error);
|
441 |
return $error;
|
442 |
} else {
|
443 |
-
$error = 'Error extracting with ZipArchive. ';
|
444 |
self::log($error);
|
445 |
}
|
446 |
}
|
@@ -460,7 +341,7 @@ class DUPX_Bootstrap
|
|
460 |
self::log('Successfully extracted with Shell Exec');
|
461 |
$error = null;
|
462 |
} else {
|
463 |
-
$error .= 'Error extracting with Shell Exec. Please manually extract archive then choose Advanced > Manual Extract in installer.';
|
464 |
self::log($error);
|
465 |
}
|
466 |
} else {
|
@@ -475,6 +356,7 @@ class DUPX_Bootstrap
|
|
475 |
if (!$extract_success && $zip_mode == DUPX_Bootstrap_Zip_Mode::AutoUnzip) {
|
476 |
$unzip_filepath = $this->getUnzipFilePath();
|
477 |
if (!class_exists('ZipArchive') && empty($unzip_filepath)) {
|
|
|
478 |
$error = "NOTICE: ZipArchive and Shell Exec are not enabled on this server please talk to your host or server admin about enabling ";
|
479 |
$error .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-060-q'>ZipArchive</a> or <a target='_blank' href='http://php.net/manual/en/function.shell-exec.php'>Shell Exec</a> on this server or manually extract archive then choose Advanced > Manual Extract in installer.";
|
480 |
}
|
@@ -484,7 +366,7 @@ class DUPX_Bootstrap
|
|
484 |
try {
|
485 |
DupArchiveMiniExpander::expandDirectory($archive_filepath, self::INSTALLER_DIR_NAME, dirname(__FILE__));
|
486 |
} catch (Exception $ex) {
|
487 |
-
self::log("Error expanding installer subdirectory:".$ex->getMessage());
|
488 |
throw $ex;
|
489 |
}
|
490 |
}
|
@@ -553,10 +435,10 @@ class DUPX_Bootstrap
|
|
553 |
}
|
554 |
} else {
|
555 |
self::log("No need to create dup-installer/.htaccess or dup-installer/.user.ini");
|
556 |
-
self::log("SAPI: Unrecognized");
|
557 |
}
|
558 |
} else {
|
559 |
-
self::log("Didn't need to extract the installer.");
|
560 |
}
|
561 |
|
562 |
if (empty($error)) {
|
@@ -583,9 +465,13 @@ class DUPX_Bootstrap
|
|
583 |
$server_port = $_SERVER['SERVER_PORT'];
|
584 |
}
|
585 |
|
586 |
-
|
587 |
-
|
588 |
-
|
|
|
|
|
|
|
|
|
589 |
if(strpos($current_url,':') === false) {
|
590 |
$current_url = $current_url.':'.$server_port;
|
591 |
}
|
@@ -612,7 +498,7 @@ class DUPX_Bootstrap
|
|
612 |
$this->mainInstallerURL .= '?'.$_SERVER['QUERY_STRING'];
|
613 |
}
|
614 |
|
615 |
-
self::log("No detected errors so redirecting to the main installer. Main Installer URI = {$this->mainInstallerURL}");
|
616 |
}
|
617 |
}
|
618 |
|
@@ -639,7 +525,7 @@ class DUPX_Bootstrap
|
|
639 |
}
|
640 |
}
|
641 |
}
|
642 |
-
|
643 |
/**
|
644 |
* Indicates if site is running https or not
|
645 |
*
|
@@ -665,13 +551,9 @@ class DUPX_Bootstrap
|
|
665 |
*/
|
666 |
private function fixInstallerPerms()
|
667 |
{
|
668 |
-
$file_perms =
|
669 |
-
$
|
670 |
-
//$dir_perms = substr(sprintf('%o', fileperms(dirname(__FILE__))), -4);
|
671 |
|
672 |
-
// No longer using existing directory permissions since that can cause problems. Just set it to 755
|
673 |
-
$dir_perms = '755';
|
674 |
-
$dir_perms = octdec($dir_perms);
|
675 |
$installer_dir_path = $this->installerContentsPath;
|
676 |
|
677 |
$this->setPerms($installer_dir_path, $dir_perms, false);
|
@@ -682,7 +564,7 @@ class DUPX_Bootstrap
|
|
682 |
* Set the permissions of a given directory and optionally all files
|
683 |
*
|
684 |
* @param string $directory The full path to the directory where perms will be set
|
685 |
-
* @param string $perms The given permission sets to use such as '0755'
|
686 |
* @param string $do_files Also set the permissions of all the files in the directory
|
687 |
*
|
688 |
* @return null
|
@@ -708,34 +590,41 @@ class DUPX_Bootstrap
|
|
708 |
* Set the permissions of a single directory or file
|
709 |
*
|
710 |
* @param string $path The full path to the directory or file where perms will be set
|
711 |
-
* @param string $perms The given permission sets to use such as '0755'
|
712 |
*
|
713 |
* @return bool Returns true if the permission was properly set
|
714 |
*/
|
715 |
private function setPermsOnItem($path, $perms)
|
716 |
{
|
717 |
-
$result =
|
718 |
$perms_display = decoct($perms);
|
719 |
if ($result === false) {
|
720 |
-
self::log("Couldn't set permissions of $path to {$perms_display}<br/>");
|
721 |
} else {
|
722 |
self::log("Set permissions of $path to {$perms_display}<br/>");
|
723 |
}
|
724 |
return $result;
|
725 |
}
|
726 |
|
727 |
-
|
728 |
-
|
729 |
* Logs a string to the dup-installer-bootlog__[HASH].txt file
|
730 |
*
|
731 |
* @param string $s The string to log to the log file
|
732 |
*
|
733 |
-
* @return
|
734 |
*/
|
735 |
-
public static function log($s)
|
736 |
{
|
737 |
-
|
738 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
739 |
}
|
740 |
|
741 |
/**
|
@@ -751,7 +640,7 @@ class DUPX_Bootstrap
|
|
751 |
$zipArchive = new ZipArchive();
|
752 |
$subFolderArchiveList = array();
|
753 |
|
754 |
-
if ($zipArchive->open($archive_filepath) === true) {
|
755 |
self::log("Successfully opened $archive_filepath");
|
756 |
$destination = dirname(__FILE__);
|
757 |
$folder_prefix = self::INSTALLER_DIR_NAME.'/';
|
@@ -790,7 +679,7 @@ class DUPX_Bootstrap
|
|
790 |
if ($zipArchive->extractTo($destination, $filename) === true) {
|
791 |
self::log("Success: {$filename} >>> {$destination}");
|
792 |
} else {
|
793 |
-
self::log("Error extracting {$filename} from archive archive file");
|
794 |
$success = false;
|
795 |
break;
|
796 |
}
|
@@ -824,7 +713,7 @@ class DUPX_Bootstrap
|
|
824 |
if ($zipArchive->extractTo($destination, $filename) === true) {
|
825 |
self::log("Success: {$filename} >>> {$destination}");
|
826 |
} else {
|
827 |
-
self::log("Error extracting {$filename} from archive archive file");
|
828 |
$success = false;
|
829 |
break;
|
830 |
}
|
@@ -836,27 +725,227 @@ class DUPX_Bootstrap
|
|
836 |
if ($zipArchive->close() === true) {
|
837 |
self::log("Successfully closed archive file");
|
838 |
} else {
|
839 |
-
self::log("Problem closing archive file");
|
840 |
$success = false;
|
841 |
}
|
842 |
|
843 |
if ($success != false && $this->installer_files_found < 10) {
|
844 |
if ($checkSubFolder) {
|
845 |
-
self::log("Couldn't find the installer directory in the archive!");
|
846 |
$success = false;
|
847 |
} else {
|
848 |
-
self::log("Couldn't find the installer directory in archive root! Check subfolder");
|
849 |
$this->extractInstallerZipArchive($archive_filepath, true);
|
850 |
}
|
851 |
}
|
852 |
} else {
|
853 |
-
self::log("Couldn't open archive archive file with ZipArchive");
|
854 |
$success = false;
|
855 |
}
|
856 |
|
857 |
return $success;
|
858 |
}
|
859 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
860 |
/**
|
861 |
* move all folder content up to parent
|
862 |
*
|
@@ -878,7 +967,7 @@ class DUPX_Bootstrap
|
|
878 |
|
879 |
$success = true;
|
880 |
if (($subList = glob(rtrim($subFolderName, '/').'/*', GLOB_NOSORT)) === false) {
|
881 |
-
self::log("Problem glob folder ".$subFolderName);
|
882 |
return false;
|
883 |
} else {
|
884 |
foreach ($subList as $cName) {
|
@@ -900,7 +989,7 @@ class DUPX_Bootstrap
|
|
900 |
}
|
901 |
|
902 |
if (!$success) {
|
903 |
-
self::log("Problem om moveUpfromSubFolder subFolder:".$subFolderName);
|
904 |
}
|
905 |
|
906 |
return $success;
|
@@ -934,7 +1023,7 @@ class DUPX_Bootstrap
|
|
934 |
$unzip_command = "$unzip_filepath -q $archive_filepath snaplib/* 2>&1";
|
935 |
self::log("Executing $unzip_command");
|
936 |
$stderr .= shell_exec($unzip_command);
|
937 |
-
mkdir($lib_directory);
|
938 |
rename($local_lib_directory, $snaplib_directory);
|
939 |
}
|
940 |
|
@@ -942,7 +1031,7 @@ class DUPX_Bootstrap
|
|
942 |
self::log("Shell exec unzip succeeded");
|
943 |
$success = true;
|
944 |
} else {
|
945 |
-
self::log("Shell exec unzip failed. Output={$stderr}");
|
946 |
}
|
947 |
}
|
948 |
|
@@ -1144,12 +1233,12 @@ class DUPX_Bootstrap
|
|
1144 |
} else {
|
1145 |
$success = @unlink($fullPath);
|
1146 |
if ($success === false) {
|
1147 |
-
self::log( __FUNCTION__.": Problem deleting file:".$fullPath);
|
1148 |
}
|
1149 |
}
|
1150 |
|
1151 |
if ($success === false) {
|
1152 |
-
self::log("Problem deleting dir:".$directory);
|
1153 |
break;
|
1154 |
}
|
1155 |
}
|
@@ -1174,7 +1263,7 @@ class DUPX_Bootstrap
|
|
1174 |
$success = @unlink($path);
|
1175 |
|
1176 |
if ($success === false) {
|
1177 |
-
self::log( __FUNCTION__.": Problem deleting file:".$path);
|
1178 |
}
|
1179 |
}
|
1180 |
|
@@ -1198,6 +1287,696 @@ class DUPX_Bootstrap
|
|
1198 |
}
|
1199 |
}
|
1200 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1201 |
try {
|
1202 |
$boot = new DUPX_Bootstrap();
|
1203 |
$boot_error = $boot->run();
|
1 |
<?php
|
2 |
+
/* ------------------------------ NOTICE ----------------------------------
|
3 |
|
4 |
+
If you're seeing this text when browsing to the installer, it means your
|
5 |
+
web server is not set up properly.
|
|
|
6 |
|
7 |
+
Please contact your host and ask them to enable "PHP" processing on your
|
8 |
+
account.
|
9 |
+
----------------------------- NOTICE ---------------------------------*/
|
10 |
+
|
11 |
if (!defined('KB_IN_BYTES')) { define('KB_IN_BYTES', 1024); }
|
12 |
if (!defined('MB_IN_BYTES')) { define('MB_IN_BYTES', 1024 * KB_IN_BYTES); }
|
13 |
if (!defined('GB_IN_BYTES')) { define('GB_IN_BYTES', 1024 * MB_IN_BYTES); }
|
29 |
*/
|
30 |
function wp_is_ini_value_changeable( $setting ) {
|
31 |
static $ini_all;
|
|
|
32 |
if ( ! isset( $ini_all ) ) {
|
33 |
$ini_all = false;
|
34 |
// Sometimes `ini_get_all()` is disabled via the `disable_functions` option for "security purposes".
|
60 |
@ini_set('pcre.backtrack_limit', PHP_INT_MAX);
|
61 |
if (wp_is_ini_value_changeable('default_socket_timeout'))
|
62 |
@ini_set('default_socket_timeout', 3600);
|
63 |
+
|
64 |
+
DUPX_Handler::init_error_handler();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
/**
|
67 |
* Bootstrap utility to exatract the core installer
|
76 |
* installer.php?unzipmode=ziparchive
|
77 |
* installer.php?unzipmode=shellexec
|
78 |
*/
|
79 |
+
|
80 |
+
/*** CLASS DEFINITION START ***/
|
81 |
|
82 |
abstract class DUPX_Bootstrap_Zip_Mode
|
83 |
{
|
86 |
const ShellExec = 2;
|
87 |
}
|
88 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
class DUPX_Bootstrap
|
90 |
{
|
91 |
//@@ Params get dynamically swapped when package is built
|
111 |
*/
|
112 |
public function __construct()
|
113 |
{
|
114 |
+
// clean log file
|
115 |
+
self::log('', true);
|
116 |
+
|
117 |
//ARCHIVE_SIZE will be blank with a root filter so we can estimate
|
118 |
//the default size of the package around 17.5MB (18088000)
|
119 |
$archiveActualSize = @filesize(self::ARCHIVE_FILENAME);
|
143 |
public function run()
|
144 |
{
|
145 |
date_default_timezone_set('UTC'); // Some machines don't have this set so just do it here
|
146 |
+
|
147 |
self::log('==DUPLICATOR INSTALLER BOOTSTRAP v@@VERSION@@==');
|
148 |
self::log('----------------------------------------------------');
|
149 |
self::log('Installer bootstrap start');
|
175 |
|
176 |
//MISSING ARCHIVE FILE
|
177 |
if (! file_exists($archive_filepath)) {
|
178 |
+
self::log("[ERROR] Archive file not found!");
|
179 |
$archive_candidates = ($isZip) ? $this->getFilesWithExtension('zip') : $this->getFilesWithExtension('daf');
|
180 |
$candidate_count = count($archive_candidates);
|
181 |
$candidate_html = "- No {$archive_extension} files found -";
|
183 |
if ($candidate_count >= 1) {
|
184 |
$candidate_html = "<ol>";
|
185 |
foreach($archive_candidates as $archive_candidate) {
|
186 |
+
$fineDiffObj = new FineDiff($archive_candidate, $archive_filename, FineDiff::$characterGranularity);
|
187 |
+
$candidate_html .= '<li class="diff-list"> '.$fineDiffObj->renderDiffToHTML().'</li>';
|
188 |
}
|
189 |
$candidate_html .= "</ol>";
|
190 |
}
|
191 |
|
192 |
+
$error = "<style>
|
193 |
+
.diff-list del { color: red; background: #fdd; text-decoration: none; }
|
194 |
+
.diff-list ins { color: green; background: #dfd; text-decoration: none; }
|
195 |
+
</style>
|
196 |
+
<b>Archive not found!</b> The <i>'Required File'</i> below should be present in the <i>'Extraction Path'</i>. "
|
197 |
. "The archive file name must be the <u>exact</u> name of the archive file placed in the extraction path character for character.<br/><br/> "
|
198 |
. "If the file does not have the correct name then rename it to the <i>'Required File'</i> below. When downloading the package files make "
|
199 |
. "sure both files are from the same package line in the packages view. If the archive is not finished downloading please wait for it to complete.<br/><br/>"
|
206 |
return $error;
|
207 |
}
|
208 |
|
209 |
+
if (!self::checkInputVaslidInt(self::ARCHIVE_SIZE)) {
|
|
|
|
|
|
|
210 |
$no_of_bits = PHP_INT_SIZE * 8;
|
211 |
+
$error = 'Current is a '.$no_of_bits.'-bit SO. This archive is too large for '.$no_of_bits.'-bit PHP.'.'<br>';
|
212 |
+
$this->log('[ERROR] '.$error);
|
213 |
+
$error .= 'Possibibles solutions:<br>';
|
214 |
+
$error .= '- Use the file filters to get your package lower to support this server or try the package on a Linux server.'.'<br>';
|
215 |
+
$error .= '- Perform a <a target="_blank" href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-installer-015-q">Manual Extract Install</a>'.'<br>';
|
216 |
+
|
217 |
+
switch ($no_of_bits == 32) {
|
218 |
+
case 32:
|
219 |
+
$error .= '- Ask your host to upgrade the server to 64-bit PHP or install on another system has 64-bit PHP'.'<br>';
|
220 |
+
break;
|
221 |
+
case 64:
|
222 |
+
$error .= '- Ask your host to upgrade the server to 128-bit PHP or install on another system has 128-bit PHP'.'<br>';
|
223 |
+
break;
|
224 |
+
}
|
225 |
|
226 |
+
if (self::isWindows()) {
|
227 |
+
$error .= '- <a target="_blank" href="https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-052-q">Windows DupArchive extractor</a> to extract all files from the archive.'.'<br>';
|
228 |
+
}
|
229 |
+
|
230 |
+
return $error;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
231 |
}
|
232 |
|
233 |
//SIZE CHECK ERROR
|
234 |
if (($this->archiveRatio < 90) && ($this->archiveActualSize > 0) && ($this->archiveExpectedSize > 0)) {
|
235 |
$this->log("ERROR: The expected archive size should be around [{$archiveExpectedEasy}]. The actual size is currently [{$archiveActualEasy}].");
|
236 |
+
$this->log("ERROR: The archive file may not have fully been downloaded to the server");
|
237 |
$percent = round($this->archiveRatio);
|
238 |
|
239 |
$autochecked = isset($_POST['auto-fresh']) ? "checked='true'" : '';
|
256 |
if ($manual_extract_found) {
|
257 |
// INSTALL DIRECTORY: Check if its setup correctly AND we are not in overwrite mode
|
258 |
if (isset($_GET['force-extract-installer']) && ('1' == $_GET['force-extract-installer'] || 'enable' == $_GET['force-extract-installer'] || 'false' == $_GET['force-extract-installer'])) {
|
|
|
259 |
self::log("Manual extract found with force extract installer get parametr");
|
260 |
$extract_installer = true;
|
|
|
261 |
} else {
|
262 |
$extract_installer = false;
|
263 |
self::log("Manual extract found so not going to extract dup-installer dir");
|
264 |
}
|
265 |
} else {
|
266 |
$extract_installer = true;
|
|
|
267 |
}
|
268 |
|
269 |
if ($extract_installer && file_exists($installer_directory)) {
|
270 |
+
self::log("EXTRACT dup-installer dir");
|
271 |
$scanned_directory = array_diff(scandir($installer_directory), array('..', '.'));
|
272 |
foreach ($scanned_directory as $object) {
|
273 |
$object_file_path = $installer_directory.'/'.$object;
|
275 |
if (unlink($object_file_path)) {
|
276 |
self::log('Successfully deleted the file '.$object_file_path);
|
277 |
} else {
|
278 |
+
$error .= '[ERROR] Error deleting the file '.$object_file_path.' Please manually delete it and try again.';
|
279 |
self::log($error);
|
280 |
}
|
281 |
}
|
291 |
$destination = dirname(__FILE__);
|
292 |
if (!is_writable($destination)) {
|
293 |
self::log("destination folder for extraction is not writable");
|
294 |
+
if (self::chmod($destination, 'u+rwx')) {
|
295 |
+
self::log("Permission of destination folder changed to u+rwx");
|
296 |
} else {
|
297 |
+
self::log("[ERROR] Permission of destination folder failed to change to u+rwx");
|
298 |
}
|
299 |
}
|
300 |
|
301 |
if (!is_writable($destination)) {
|
302 |
+
self::log("WARNING: The {$destination} directory is not writable.");
|
303 |
$error = "NOTICE: The {$destination} directory is not writable on this server please talk to your host or server admin about making ";
|
304 |
$error .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-055-q'>writable {$destination} directory</a> on this server. <br/>";
|
305 |
return $error;
|
306 |
}
|
307 |
|
|
|
308 |
if ($isZip) {
|
309 |
$zip_mode = $this->getZipMode();
|
310 |
|
317 |
self::log('Successfully extracted with ZipArchive');
|
318 |
} else {
|
319 |
if (0 == $this->installer_files_found) {
|
320 |
+
$error = "[ERROR] This archive is not properly formatted and does not contain a dup-installer directory. Please make sure you are attempting to install the original archive and not one that has been reconstructed.";
|
321 |
self::log($error);
|
322 |
return $error;
|
323 |
} else {
|
324 |
+
$error = '[ERROR] Error extracting with ZipArchive. ';
|
325 |
self::log($error);
|
326 |
}
|
327 |
}
|
341 |
self::log('Successfully extracted with Shell Exec');
|
342 |
$error = null;
|
343 |
} else {
|
344 |
+
$error .= '[ERROR] Error extracting with Shell Exec. Please manually extract archive then choose Advanced > Manual Extract in installer.';
|
345 |
self::log($error);
|
346 |
}
|
347 |
} else {
|
356 |
if (!$extract_success && $zip_mode == DUPX_Bootstrap_Zip_Mode::AutoUnzip) {
|
357 |
$unzip_filepath = $this->getUnzipFilePath();
|
358 |
if (!class_exists('ZipArchive') && empty($unzip_filepath)) {
|
359 |
+
self::log("WARNING: ZipArchive and Shell Exec are not enabled on this server.");
|
360 |
$error = "NOTICE: ZipArchive and Shell Exec are not enabled on this server please talk to your host or server admin about enabling ";
|
361 |
$error .= "<a target='_blank' href='https://snapcreek.com/duplicator/docs/faqs-tech/#faq-trouble-060-q'>ZipArchive</a> or <a target='_blank' href='http://php.net/manual/en/function.shell-exec.php'>Shell Exec</a> on this server or manually extract archive then choose Advanced > Manual Extract in installer.";
|
362 |
}
|
366 |
try {
|
367 |
DupArchiveMiniExpander::expandDirectory($archive_filepath, self::INSTALLER_DIR_NAME, dirname(__FILE__));
|
368 |
} catch (Exception $ex) {
|
369 |
+
self::log("[ERROR] Error expanding installer subdirectory:".$ex->getMessage());
|
370 |
throw $ex;
|
371 |
}
|
372 |
}
|
435 |
}
|
436 |
} else {
|
437 |
self::log("No need to create dup-installer/.htaccess or dup-installer/.user.ini");
|
438 |
+
self::log("ERROR: SAPI: Unrecognized");
|
439 |
}
|
440 |
} else {
|
441 |
+
self::log("ERROR: Didn't need to extract the installer.");
|
442 |
}
|
443 |
|
444 |
if (empty($error)) {
|
465 |
$server_port = $_SERVER['SERVER_PORT'];
|
466 |
}
|
467 |
|
468 |
+
// for ngrok url and Local by Flywheel Live URL
|
469 |
+
if (isset($_SERVER['HTTP_X_ORIGINAL_HOST'])) {
|
470 |
+
$host = $_SERVER['HTTP_X_ORIGINAL_HOST'];
|
471 |
+
} else {
|
472 |
+
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];//WAS SERVER_NAME and caused problems on some boxes
|
473 |
+
}
|
474 |
+
$current_url .= $host;
|
475 |
if(strpos($current_url,':') === false) {
|
476 |
$current_url = $current_url.':'.$server_port;
|
477 |
}
|
498 |
$this->mainInstallerURL .= '?'.$_SERVER['QUERY_STRING'];
|
499 |
}
|
500 |
|
501 |
+
self::log("DONE: No detected errors so redirecting to the main installer. Main Installer URI = {$this->mainInstallerURL}");
|
502 |
}
|
503 |
}
|
504 |
|
525 |
}
|
526 |
}
|
527 |
}
|
528 |
+
|
529 |
/**
|
530 |
* Indicates if site is running https or not
|
531 |
*
|
551 |
*/
|
552 |
private function fixInstallerPerms()
|
553 |
{
|
554 |
+
$file_perms = 'u+rw';
|
555 |
+
$dir_perms = 'u+rwx';
|
|
|
556 |
|
|
|
|
|
|
|
557 |
$installer_dir_path = $this->installerContentsPath;
|
558 |
|
559 |
$this->setPerms($installer_dir_path, $dir_perms, false);
|
564 |
* Set the permissions of a given directory and optionally all files
|
565 |
*
|
566 |
* @param string $directory The full path to the directory where perms will be set
|
567 |
+
* @param string $perms The given permission sets to use such as '0755' or 'u+rw'
|
568 |
* @param string $do_files Also set the permissions of all the files in the directory
|
569 |
*
|
570 |
* @return null
|
590 |
* Set the permissions of a single directory or file
|
591 |
*
|
592 |
* @param string $path The full path to the directory or file where perms will be set
|
593 |
+
* @param string $perms The given permission sets to use such as '0755' or 'u+rw'
|
594 |
*
|
595 |
* @return bool Returns true if the permission was properly set
|
596 |
*/
|
597 |
private function setPermsOnItem($path, $perms)
|
598 |
{
|
599 |
+
$result = self::chmod($path, $perms);
|
600 |
$perms_display = decoct($perms);
|
601 |
if ($result === false) {
|
602 |
+
self::log("ERROR: Couldn't set permissions of $path to {$perms_display}<br/>");
|
603 |
} else {
|
604 |
self::log("Set permissions of $path to {$perms_display}<br/>");
|
605 |
}
|
606 |
return $result;
|
607 |
}
|
608 |
|
609 |
+
|
610 |
+
/**
|
611 |
* Logs a string to the dup-installer-bootlog__[HASH].txt file
|
612 |
*
|
613 |
* @param string $s The string to log to the log file
|
614 |
*
|
615 |
+
* @return boog|int // This function returns the number of bytes that were written to the file, or FALSE on failure.
|
616 |
*/
|
617 |
+
public static function log($s, $deleteOld = false)
|
618 |
{
|
619 |
+
static $logfile = null;
|
620 |
+
if (is_null($logfile)) {
|
621 |
+
$logfile = dirname(__FILE__).'/dup-installer-bootlog__'.self::PACKAGE_HASH.'.txt';
|
622 |
+
}
|
623 |
+
if ($deleteOld && file_exists($logfile)) {
|
624 |
+
@unlink($logfile);
|
625 |
+
}
|
626 |
+
$timestamp = date('M j H:i:s');
|
627 |
+
return @file_put_contents($logfile, '['.$timestamp.'] '.$s."\n", FILE_APPEND);
|
628 |
}
|
629 |
|
630 |
/**
|
640 |
$zipArchive = new ZipArchive();
|
641 |
$subFolderArchiveList = array();
|
642 |
|
643 |
+
if (($zipOpenRes = $zipArchive->open($archive_filepath)) === true) {
|
644 |
self::log("Successfully opened $archive_filepath");
|
645 |
$destination = dirname(__FILE__);
|
646 |
$folder_prefix = self::INSTALLER_DIR_NAME.'/';
|
679 |
if ($zipArchive->extractTo($destination, $filename) === true) {
|
680 |
self::log("Success: {$filename} >>> {$destination}");
|
681 |
} else {
|
682 |
+
self::log("[ERROR] Error extracting {$filename} from archive archive file");
|
683 |
$success = false;
|
684 |
break;
|
685 |
}
|
713 |
if ($zipArchive->extractTo($destination, $filename) === true) {
|
714 |
self::log("Success: {$filename} >>> {$destination}");
|
715 |
} else {
|
716 |
+
self::log("[ERROR] Error extracting {$filename} from archive archive file");
|
717 |
$success = false;
|
718 |
break;
|
719 |
}
|
725 |
if ($zipArchive->close() === true) {
|
726 |
self::log("Successfully closed archive file");
|
727 |
} else {
|
728 |
+
self::log("[ERROR] Problem closing archive file");
|
729 |
$success = false;
|
730 |
}
|
731 |
|
732 |
if ($success != false && $this->installer_files_found < 10) {
|
733 |
if ($checkSubFolder) {
|
734 |
+
self::log("[ERROR] Couldn't find the installer directory in the archive!");
|
735 |
$success = false;
|
736 |
} else {
|
737 |
+
self::log("[ERROR] Couldn't find the installer directory in archive root! Check subfolder");
|
738 |
$this->extractInstallerZipArchive($archive_filepath, true);
|
739 |
}
|
740 |
}
|
741 |
} else {
|
742 |
+
self::log("[ERROR] Couldn't open archive archive file with ZipArchive CODE[".$zipOpenRes."]");
|
743 |
$success = false;
|
744 |
}
|
745 |
|
746 |
return $success;
|
747 |
}
|
748 |
|
749 |
+
/**
|
750 |
+
* return true if current SO is windows
|
751 |
+
*
|
752 |
+
* @staticvar bool $isWindows
|
753 |
+
* @return bool
|
754 |
+
*/
|
755 |
+
public static function isWindows()
|
756 |
+
{
|
757 |
+
static $isWindows = null;
|
758 |
+
if (is_null($isWindows)) {
|
759 |
+
$isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
760 |
+
}
|
761 |
+
return $isWindows;
|
762 |
+
}
|
763 |
+
|
764 |
+
/**
|
765 |
+
* return current SO path path len
|
766 |
+
* @staticvar int $maxPath
|
767 |
+
* @return int
|
768 |
+
*/
|
769 |
+
public static function maxPathLen()
|
770 |
+
{
|
771 |
+
static $maxPath = null;
|
772 |
+
if (is_null($maxPath)) {
|
773 |
+
if (defined('PHP_MAXPATHLEN')) {
|
774 |
+
$maxPath = PHP_MAXPATHLEN;
|
775 |
+
} else {
|
776 |
+
// for PHP < 5.3.0
|
777 |
+
$maxPath = self::isWindows() ? 260 : 4096;
|
778 |
+
}
|
779 |
+
}
|
780 |
+
return $maxPath;
|
781 |
+
}
|
782 |
+
|
783 |
+
/**
|
784 |
+
* this function make a chmod only if the are different from perms input and if chmod function is enabled
|
785 |
+
*
|
786 |
+
* this function handles the variable MODE in a way similar to the chmod of lunux
|
787 |
+
* So the MODE variable can be
|
788 |
+
* 1) an octal number (0755)
|
789 |
+
* 2) a string that defines an octal number ("644")
|
790 |
+
* 3) a string with the following format [ugoa]*([-+=]([rwx]*)+
|
791 |
+
*
|
792 |
+
* examples
|
793 |
+
* u+rw add read and write at the user
|
794 |
+
* u+rw,uo-wx add read and write ad the user and remove wx at groupd and other
|
795 |
+
* a=rw is equal at 666
|
796 |
+
* u=rwx,go-rwx is equal at 700
|
797 |
+
*
|
798 |
+
* @param string $file
|
799 |
+
* @param int|string $mode
|
800 |
+
* @return boolean
|
801 |
+
*/
|
802 |
+
public static function chmod($file, $mode)
|
803 |
+
{
|
804 |
+
if (!file_exists($file)) {
|
805 |
+
return false;
|
806 |
+
}
|
807 |
+
|
808 |
+
$octalMode = 0;
|
809 |
+
|
810 |
+
if (is_int($mode)) {
|
811 |
+
$octalMode = $mode;
|
812 |
+
} else if (is_string($mode)) {
|
813 |
+
$mode = trim($mode);
|
814 |
+
if (preg_match('/([0-7]{1,3})/', $mode)) {
|
815 |
+
$octalMode = intval(('0'.$mode), 8);
|
816 |
+
} else if (preg_match_all('/(a|[ugo]{1,3})([-=+])([rwx]{1,3})/', $mode, $gMatch, PREG_SET_ORDER)) {
|
817 |
+
if (!function_exists('fileperms')) {
|
818 |
+
return false;
|
819 |
+
}
|
820 |
+
|
821 |
+
// start by file permission
|
822 |
+
$octalMode = (fileperms($file) & 0777);
|
823 |
+
|
824 |
+
foreach ($gMatch as $matches) {
|
825 |
+
// [ugo] or a = ugo
|
826 |
+
$group = $matches[1];
|
827 |
+
if ($group === 'a') {
|
828 |
+
$group = 'ugo';
|
829 |
+
}
|
830 |
+
// can be + - =
|
831 |
+
$action = $matches[2];
|
832 |
+
// [rwx]
|
833 |
+
$gPerms = $matches[3];
|
834 |
+
|
835 |
+
// reset octal group perms
|
836 |
+
$octalGroupMode = 0;
|
837 |
+
|
838 |
+
// Init sub perms
|
839 |
+
$subPerm = 0;
|
840 |
+
$subPerm += strpos($gPerms, 'x') !== false ? 1 : 0; // mask 001
|
841 |
+
$subPerm += strpos($gPerms, 'w') !== false ? 2 : 0; // mask 010
|
842 |
+
$subPerm += strpos($gPerms, 'r') !== false ? 4 : 0; // mask 100
|
843 |
+
|
844 |
+
$ugoLen = strlen($group);
|
845 |
+
|
846 |
+
if ($action === '=') {
|
847 |
+
// generate octal group permsissions and ugo mask invert
|
848 |
+
$ugoMaskInvert = 0777;
|
849 |
+
for ($i = 0; $i < $ugoLen; $i++) {
|
850 |
+
switch ($group[$i]) {
|
851 |
+
case 'u':
|
852 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000
|
853 |
+
$ugoMaskInvert = $ugoMaskInvert & 077;
|
854 |
+
break;
|
855 |
+
case 'g':
|
856 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000
|
857 |
+
$ugoMaskInvert = $ugoMaskInvert & 0707;
|
858 |
+
break;
|
859 |
+
case 'o':
|
860 |
+
$octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx
|
861 |
+
$ugoMaskInvert = $ugoMaskInvert & 0770;
|
862 |
+
break;
|
863 |
+
}
|
864 |
+
}
|
865 |
+
// apply = action
|
866 |
+
$octalMode = $octalMode & ($ugoMaskInvert | $octalGroupMode);
|
867 |
+
} else {
|
868 |
+
// generate octal group permsissions
|
869 |
+
for ($i = 0; $i < $ugoLen; $i++) {
|
870 |
+
switch ($group[$i]) {
|
871 |
+
case 'u':
|
872 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000
|
873 |
+
break;
|
874 |
+
case 'g':
|
875 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000
|
876 |
+
break;
|
877 |
+
case 'o':
|
878 |
+
$octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx
|
879 |
+
break;
|
880 |
+
}
|
881 |
+
}
|
882 |
+
// apply + or - action
|
883 |
+
switch ($action) {
|
884 |
+
case '+':
|
885 |
+
$octalMode = $octalMode | $octalGroupMode;
|
886 |
+
break;
|
887 |
+
case '-':
|
888 |
+
$octalMode = $octalMode & ~$octalGroupMode;
|
889 |
+
break;
|
890 |
+
}
|
891 |
+
}
|
892 |
+
}
|
893 |
+
}
|
894 |
+
}
|
895 |
+
|
896 |
+
// if input permissions are equal at file permissions return true without performing chmod
|
897 |
+
if (function_exists('fileperms') && $octalMode === (fileperms($file) & 0777)) {
|
898 |
+
return true;
|
899 |
+
}
|
900 |
+
|
901 |
+
if (!function_exists('chmod')) {
|
902 |
+
return false;
|
903 |
+
}
|
904 |
+
|
905 |
+
return @chmod($file, $octalMode);
|
906 |
+
}
|
907 |
+
|
908 |
+
public static function checkInputVaslidInt($input) {
|
909 |
+
return (filter_var($input, FILTER_VALIDATE_INT) === 0 || filter_var($input, FILTER_VALIDATE_INT));
|
910 |
+
}
|
911 |
+
|
912 |
+
|
913 |
+
/**
|
914 |
+
* this function creates a folder if it does not exist and performs a chmod.
|
915 |
+
* it is different from the normal mkdir function to which an umask is applied to the input permissions.
|
916 |
+
*
|
917 |
+
* this function handles the variable MODE in a way similar to the chmod of lunux
|
918 |
+
* So the MODE variable can be
|
919 |
+
* 1) an octal number (0755)
|
920 |
+
* 2) a string that defines an octal number ("644")
|
921 |
+
* 3) a string with the following format [ugoa]*([-+=]([rwx]*)+
|
922 |
+
*
|
923 |
+
* @param string $path
|
924 |
+
* @param int|string $mode
|
925 |
+
* @param bool $recursive
|
926 |
+
* @param resource $context // not used for windows bug
|
927 |
+
* @return boolean bool TRUE on success or FALSE on failure.
|
928 |
+
*
|
929 |
+
* @todo check recursive true and multiple chmod
|
930 |
+
*/
|
931 |
+
public static function mkdir($path, $mode = 0777, $recursive = false, $context = null)
|
932 |
+
{
|
933 |
+
if (strlen($path) > self::maxPathLen()) {
|
934 |
+
throw new Exception('Skipping a file that exceeds allowed max path length ['.self::maxPathLen().']. File: '.$filepath);
|
935 |
+
}
|
936 |
+
|
937 |
+
if (!file_exists($path)) {
|
938 |
+
if (!function_exists('mkdir')) {
|
939 |
+
return false;
|
940 |
+
}
|
941 |
+
if (!@mkdir($path, 0777, $recursive)) {
|
942 |
+
return false;
|
943 |
+
}
|
944 |
+
}
|
945 |
+
|
946 |
+
return self::chmod($path, $mode);
|
947 |
+
}
|
948 |
+
|
949 |
/**
|
950 |
* move all folder content up to parent
|
951 |
*
|
967 |
|
968 |
$success = true;
|
969 |
if (($subList = glob(rtrim($subFolderName, '/').'/*', GLOB_NOSORT)) === false) {
|
970 |
+
self::log("[ERROR] Problem glob folder ".$subFolderName);
|
971 |
return false;
|
972 |
} else {
|
973 |
foreach ($subList as $cName) {
|
989 |
}
|
990 |
|
991 |
if (!$success) {
|
992 |
+
self::log("[ERROR] Problem om moveUpfromSubFolder subFolder:".$subFolderName);
|
993 |
}
|
994 |
|
995 |
return $success;
|
1023 |
$unzip_command = "$unzip_filepath -q $archive_filepath snaplib/* 2>&1";
|
1024 |
self::log("Executing $unzip_command");
|
1025 |
$stderr .= shell_exec($unzip_command);
|
1026 |
+
self::mkdir($lib_directory,'u+rwx');
|
1027 |
rename($local_lib_directory, $snaplib_directory);
|
1028 |
}
|
1029 |
|
1031 |
self::log("Shell exec unzip succeeded");
|
1032 |
$success = true;
|
1033 |
} else {
|
1034 |
+
self::log("[ERROR] Shell exec unzip failed. Output={$stderr}");
|
1035 |
}
|
1036 |
}
|
1037 |
|
1233 |
} else {
|
1234 |
$success = @unlink($fullPath);
|
1235 |
if ($success === false) {
|
1236 |
+
self::log('[ERROR] '.__FUNCTION__.": Problem deleting file:".$fullPath);
|
1237 |
}
|
1238 |
}
|
1239 |
|
1240 |
if ($success === false) {
|
1241 |
+
self::log("[ERROR] Problem deleting dir:".$directory);
|
1242 |
break;
|
1243 |
}
|
1244 |
}
|
1263 |
$success = @unlink($path);
|
1264 |
|
1265 |
if ($success === false) {
|
1266 |
+
self::log('[ERROR] '. __FUNCTION__.": Problem deleting file:".$path);
|
1267 |
}
|
1268 |
}
|
1269 |
|
1287 |
}
|
1288 |
}
|
1289 |
|
1290 |
+
class DUPX_Handler
|
1291 |
+
{
|
1292 |
+
/**
|
1293 |
+
*
|
1294 |
+
* @var bool
|
1295 |
+
*/
|
1296 |
+
private static $inizialized = false;
|
1297 |
+
|
1298 |
+
/**
|
1299 |
+
* This function only initializes the error handler the first time it is called
|
1300 |
+
*/
|
1301 |
+
public static function init_error_handler()
|
1302 |
+
{
|
1303 |
+
if (!self::$inizialized) {
|
1304 |
+
@set_error_handler(array(__CLASS__, 'error'));
|
1305 |
+
@register_shutdown_function(array(__CLASS__, 'shutdown'));
|
1306 |
+
self::$inizialized = true;
|
1307 |
+
}
|
1308 |
+
}
|
1309 |
+
|
1310 |
+
/**
|
1311 |
+
* Error handler
|
1312 |
+
*
|
1313 |
+
* @param integer $errno Error level
|
1314 |
+
* @param string $errstr Error message
|
1315 |
+
* @param string $errfile Error file
|
1316 |
+
* @param integer $errline Error line
|
1317 |
+
* @return void
|
1318 |
+
*/
|
1319 |
+
public static function error($errno, $errstr, $errfile, $errline)
|
1320 |
+
{
|
1321 |
+
switch ($errno) {
|
1322 |
+
case E_ERROR :
|
1323 |
+
$log_message = self::getMessage($errno, $errstr, $errfile, $errline);
|
1324 |
+
if (DUPX_Bootstrap::log($log_message) === false) {
|
1325 |
+
$log_message = "Can\'t wrinte logfile\n\n".$log_message;
|
1326 |
+
}
|
1327 |
+
die('<pre>'.htmlspecialchars($log_message).'</pre>');
|
1328 |
+
break;
|
1329 |
+
case E_NOTICE :
|
1330 |
+
case E_WARNING :
|
1331 |
+
default :
|
1332 |
+
$log_message = self::getMessage($errno, $errstr, $errfile, $errline);
|
1333 |
+
DUPX_Bootstrap::log($log_message);
|
1334 |
+
break;
|
1335 |
+
}
|
1336 |
+
}
|
1337 |
+
|
1338 |
+
private static function getMessage($errno, $errstr, $errfile, $errline)
|
1339 |
+
{
|
1340 |
+
$result = '[PHP ERR]';
|
1341 |
+
switch ($errno) {
|
1342 |
+
case E_ERROR :
|
1343 |
+
$result .= '[FATAL]';
|
1344 |
+
break;
|
1345 |
+
case E_WARNING :
|
1346 |
+
$result .= '[WARN]';
|
1347 |
+
break;
|
1348 |
+
case E_NOTICE :
|
1349 |
+
$result .= '[NOTICE]';
|
1350 |
+
break;
|
1351 |
+
default :
|
1352 |
+
$result .= '[ISSUE]';
|
1353 |
+
break;
|
1354 |
+
}
|
1355 |
+
$result .= ' MSG:';
|
1356 |
+
$result .= $errstr;
|
1357 |
+
$result .= ' [CODE:'.$errno.'|FILE:'.$errfile.'|LINE:'.$errline.']';
|
1358 |
+
return $result;
|
1359 |
+
}
|
1360 |
+
|
1361 |
+
/**
|
1362 |
+
* Shutdown handler
|
1363 |
+
*
|
1364 |
+
* @return void
|
1365 |
+
*/
|
1366 |
+
public static function shutdown()
|
1367 |
+
{
|
1368 |
+
if (($error = error_get_last())) {
|
1369 |
+
DUPX_Handler::error($error['type'], $error['message'], $error['file'], $error['line']);
|
1370 |
+
}
|
1371 |
+
}
|
1372 |
+
}
|
1373 |
+
|
1374 |
+
class DUPX_CSRF {
|
1375 |
+
|
1376 |
+
/** Session var name
|
1377 |
+
* @var string
|
1378 |
+
*/
|
1379 |
+
public static $prefix = '_DUPX_CSRF';
|
1380 |
+
private static $CSRFVars;
|
1381 |
+
|
1382 |
+
public static function setKeyVal($key, $val) {
|
1383 |
+
$CSRFVars = self::getCSRFVars();
|
1384 |
+
$CSRFVars[$key] = $val;
|
1385 |
+
self::saveCSRFVars($CSRFVars);
|
1386 |
+
self::$CSRFVars = false;
|
1387 |
+
}
|
1388 |
+
|
1389 |
+
public static function getVal($key) {
|
1390 |
+
$CSRFVars = self::getCSRFVars();
|
1391 |
+
if (isset($CSRFVars[$key])) {
|
1392 |
+
return $CSRFVars[$key];
|
1393 |
+
} else {
|
1394 |
+
return false;
|
1395 |
+
}
|
1396 |
+
|
1397 |
+
}
|
1398 |
+
|
1399 |
+
/** Generate DUPX_CSRF value for form
|
1400 |
+
* @param string $form - Form name as session key
|
1401 |
+
* @return string - token
|
1402 |
+
*/
|
1403 |
+
public static function generate($form = NULL) {
|
1404 |
+
$keyName = self::getKeyName($form);
|
1405 |
+
|
1406 |
+
$existingToken = self::getVal($keyName);
|
1407 |
+
if (false !== $existingToken) {
|
1408 |
+
$token = $existingToken;
|
1409 |
+
} else {
|
1410 |
+
$token = self::token() . self::fingerprint();
|
1411 |
+
}
|
1412 |
+
|
1413 |
+
self::setKeyVal($keyName, $token);
|
1414 |
+
return $token;
|
1415 |
+
}
|
1416 |
+
|
1417 |
+
/** Check DUPX_CSRF value of form
|
1418 |
+
* @param string $token - Token
|
1419 |
+
* @param string $form - Form name as session key
|
1420 |
+
* @return boolean
|
1421 |
+
*/
|
1422 |
+
public static function check($token, $form = NULL) {
|
1423 |
+
$keyName = self::getKeyName($form);
|
1424 |
+
$CSRFVars = self::getCSRFVars();
|
1425 |
+
if (isset($CSRFVars[$keyName]) && $CSRFVars[$keyName] == $token) { // token OK
|
1426 |
+
return true;
|
1427 |
+
}
|
1428 |
+
return FALSE;
|
1429 |
+
}
|
1430 |
+
|
1431 |
+
/** Generate token
|
1432 |
+
* @param void
|
1433 |
+
* @return string
|
1434 |
+
*/
|
1435 |
+
protected static function token() {
|
1436 |
+
mt_srand((double) microtime() * 10000);
|
1437 |
+
$charid = strtoupper(md5(uniqid(rand(), TRUE)));
|
1438 |
+
return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);
|
1439 |
+
}
|
1440 |
+
|
1441 |
+
/** Returns "digital fingerprint" of user
|
1442 |
+
* @param void
|
1443 |
+
* @return string - MD5 hashed data
|
1444 |
+
*/
|
1445 |
+
protected static function fingerprint() {
|
1446 |
+
return strtoupper(md5(implode('|', array($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']))));
|
1447 |
+
}
|
1448 |
+
|
1449 |
+
private static function getKeyName($form) {
|
1450 |
+
return self::$prefix . '_' . $form;
|
1451 |
+
}
|
1452 |
+
|
1453 |
+
private static function getPackageHash() {
|
1454 |
+
if (class_exists('DUPX_Bootstrap')) {
|
1455 |
+
return DUPX_Bootstrap::PACKAGE_HASH;
|
1456 |
+
} else {
|
1457 |
+
return $GLOBALS['DUPX_AC']->package_hash;
|
1458 |
+
}
|
1459 |
+
}
|
1460 |
+
|
1461 |
+
private static function getFilePath() {
|
1462 |
+
if (class_exists('DUPX_Bootstrap')) {
|
1463 |
+
$dupInstallerfolderPath = dirname(__FILE__).'/dup-installer/';
|
1464 |
+
} else {
|
1465 |
+
$dupInstallerfolderPath = $GLOBALS['DUPX_INIT'].'/';
|
1466 |
+
}
|
1467 |
+
$packageHash = self::getPackageHash();
|
1468 |
+
$fileName = 'dup-installer-csrf__'.$packageHash.'.txt';
|
1469 |
+
$filePath = $dupInstallerfolderPath.$fileName;
|
1470 |
+
return $filePath;
|
1471 |
+
}
|
1472 |
+
|
1473 |
+
private static function getCSRFVars() {
|
1474 |
+
if (!isset(self::$CSRFVars) || false === self::$CSRFVars) {
|
1475 |
+
$filePath = self::getFilePath();
|
1476 |
+
if (file_exists($filePath)) {
|
1477 |
+
$contents = file_get_contents($filePath);
|
1478 |
+
if (empty($contents)) {
|
1479 |
+
self::$CSRFVars = array();
|
1480 |
+
} else {
|
1481 |
+
$CSRFobjs = json_decode($contents);
|
1482 |
+
foreach ($CSRFobjs as $key => $value) {
|
1483 |
+
self::$CSRFVars[$key] = $value;
|
1484 |
+
}
|
1485 |
+
}
|
1486 |
+
} else {
|
1487 |
+
self::$CSRFVars = array();
|
1488 |
+
}
|
1489 |
+
}
|
1490 |
+
return self::$CSRFVars;
|
1491 |
+
}
|
1492 |
+
|
1493 |
+
private static function saveCSRFVars($CSRFVars) {
|
1494 |
+
$contents = json_encode($CSRFVars);
|
1495 |
+
$filePath = self::getFilePath();
|
1496 |
+
file_put_contents($filePath, $contents);
|
1497 |
+
}
|
1498 |
+
}
|
1499 |
+
|
1500 |
+
/**
|
1501 |
+
* Copyright (c) 2011 Raymond Hill (http://raymondhill.net/blog/?p=441)
|
1502 |
+
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
|
1503 |
+
* @link http://www.raymondhill.net/finediff/
|
1504 |
+
* @version 0.6
|
1505 |
+
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
1506 |
+
*/
|
1507 |
+
abstract class FineDiffOp
|
1508 |
+
{
|
1509 |
+
|
1510 |
+
abstract public function getFromLen();
|
1511 |
+
|
1512 |
+
abstract public function getToLen();
|
1513 |
+
|
1514 |
+
abstract public function getOpcode();
|
1515 |
+
}
|
1516 |
+
|
1517 |
+
class FineDiffDeleteOp extends FineDiffOp
|
1518 |
+
{
|
1519 |
+
|
1520 |
+
public function __construct($len)
|
1521 |
+
{
|
1522 |
+
$this->fromLen = $len;
|
1523 |
+
}
|
1524 |
+
|
1525 |
+
public function getFromLen()
|
1526 |
+
{
|
1527 |
+
return $this->fromLen;
|
1528 |
+
}
|
1529 |
+
|
1530 |
+
public function getToLen()
|
1531 |
+
{
|
1532 |
+
return 0;
|
1533 |
+
}
|
1534 |
+
|
1535 |
+
public function getOpcode()
|
1536 |
+
{
|
1537 |
+
if ($this->fromLen === 1) {
|
1538 |
+
return 'd';
|
1539 |
+
}
|
1540 |
+
return "d{$this->fromLen}";
|
1541 |
+
}
|
1542 |
+
}
|
1543 |
+
|
1544 |
+
class FineDiffInsertOp extends FineDiffOp
|
1545 |
+
{
|
1546 |
+
|
1547 |
+
public function __construct($text)
|
1548 |
+
{
|
1549 |
+
$this->text = $text;
|
1550 |
+
}
|
1551 |
+
|
1552 |
+
public function getFromLen()
|
1553 |
+
{
|
1554 |
+
return 0;
|
1555 |
+
}
|
1556 |
+
|
1557 |
+
public function getToLen()
|
1558 |
+
{
|
1559 |
+
return strlen($this->text);
|
1560 |
+
}
|
1561 |
+
|
1562 |
+
public function getText()
|
1563 |
+
{
|
1564 |
+
return $this->text;
|
1565 |
+
}
|
1566 |
+
|
1567 |
+
public function getOpcode()
|
1568 |
+
{
|
1569 |
+
$to_len = strlen($this->text);
|
1570 |
+
if ($to_len === 1) {
|
1571 |
+
return "i:{$this->text}";
|
1572 |
+
}
|
1573 |
+
return "i{$to_len}:{$this->text}";
|
1574 |
+
}
|
1575 |
+
}
|
1576 |
+
|
1577 |
+
class FineDiffReplaceOp extends FineDiffOp
|
1578 |
+
{
|
1579 |
+
|
1580 |
+
public function __construct($fromLen, $text)
|
1581 |
+
{
|
1582 |
+
$this->fromLen = $fromLen;
|
1583 |
+
$this->text = $text;
|
1584 |
+
}
|
1585 |
+
|
1586 |
+
public function getFromLen()
|
1587 |
+
{
|
1588 |
+
return $this->fromLen;
|
1589 |
+
}
|
1590 |
+
|
1591 |
+
public function getToLen()
|
1592 |
+
{
|
1593 |
+
return strlen($this->text);
|
1594 |
+
}
|
1595 |
+
|
1596 |
+
public function getText()
|
1597 |
+
{
|
1598 |
+
return $this->text;
|
1599 |
+
}
|
1600 |
+
|
1601 |
+
public function getOpcode()
|
1602 |
+
{
|
1603 |
+
if ($this->fromLen === 1) {
|
1604 |
+
$del_opcode = 'd';
|
1605 |
+
} else {
|
1606 |
+
$del_opcode = "d{$this->fromLen}";
|
1607 |
+
}
|
1608 |
+
$to_len = strlen($this->text);
|
1609 |
+
if ($to_len === 1) {
|
1610 |
+
return "{$del_opcode}i:{$this->text}";
|
1611 |
+
}
|
1612 |
+
return "{$del_opcode}i{$to_len}:{$this->text}";
|
1613 |
+
}
|
1614 |
+
}
|
1615 |
+
|
1616 |
+
class FineDiffCopyOp extends FineDiffOp
|
1617 |
+
{
|
1618 |
+
|
1619 |
+
public function __construct($len)
|
1620 |
+
{
|
1621 |
+
$this->len = $len;
|
1622 |
+
}
|
1623 |
+
|
1624 |
+
public function getFromLen()
|
1625 |
+
{
|
1626 |
+
return $this->len;
|
1627 |
+
}
|
1628 |
+
|
1629 |
+
public function getToLen()
|
1630 |
+
{
|
1631 |
+
return $this->len;
|
1632 |
+
}
|
1633 |
+
|
1634 |
+
public function getOpcode()
|
1635 |
+
{
|
1636 |
+
if ($this->len === 1) {
|
1637 |
+
return 'c';
|
1638 |
+
}
|
1639 |
+
return "c{$this->len}";
|
1640 |
+
}
|
1641 |
+
|
1642 |
+
public function increase($size)
|
1643 |
+
{
|
1644 |
+
return $this->len += $size;
|
1645 |
+
}
|
1646 |
+
}
|
1647 |
+
|
1648 |
+
class FineDiffOps
|
1649 |
+
{
|
1650 |
+
|
1651 |
+
public function appendOpcode($opcode, $from, $from_offset, $from_len)
|
1652 |
+
{
|
1653 |
+
if ($opcode === 'c') {
|
1654 |
+
$edits[] = new FineDiffCopyOp($from_len);
|
1655 |
+
} else if ($opcode === 'd') {
|
1656 |
+
$edits[] = new FineDiffDeleteOp($from_len);
|
1657 |
+
} else /* if ( $opcode === 'i' ) */ {
|
1658 |
+
$edits[] = new FineDiffInsertOp(substr($from, $from_offset, $from_len));
|
1659 |
+
}
|
1660 |
+
}
|
1661 |
+
|
1662 |
+
public $edits = array();
|
1663 |
+
|
1664 |
+
}
|
1665 |
+
|
1666 |
+
class FineDiff
|
1667 |
+
{
|
1668 |
+
|
1669 |
+
public function __construct($from_text = '', $to_text = '', $granularityStack = null)
|
1670 |
+
{
|
1671 |
+
// setup stack for generic text documents by default
|
1672 |
+
$this->granularityStack = $granularityStack ? $granularityStack : FineDiff::$characterGranularity;
|
1673 |
+
$this->edits = array();
|
1674 |
+
$this->from_text = $from_text;
|
1675 |
+
$this->doDiff($from_text, $to_text);
|
1676 |
+
}
|
1677 |
+
|
1678 |
+
public function getOps()
|
1679 |
+
{
|
1680 |
+
return $this->edits;
|
1681 |
+
}
|
1682 |
+
|
1683 |
+
public function renderDiffToHTML()
|
1684 |
+
{
|
1685 |
+
$in_offset = 0;
|
1686 |
+
ob_start();
|
1687 |
+
foreach ($this->edits as $edit) {
|
1688 |
+
$n = $edit->getFromLen();
|
1689 |
+
if ($edit instanceof FineDiffCopyOp) {
|
1690 |
+
FineDiff::renderDiffToHTMLFromOpcode('c', $this->from_text, $in_offset, $n);
|
1691 |
+
} else if ($edit instanceof FineDiffDeleteOp) {
|
1692 |
+
FineDiff::renderDiffToHTMLFromOpcode('d', $this->from_text, $in_offset, $n);
|
1693 |
+
} else if ($edit instanceof FineDiffInsertOp) {
|
1694 |
+
FineDiff::renderDiffToHTMLFromOpcode('i', $edit->getText(), 0, $edit->getToLen());
|
1695 |
+
} else /* if ( $edit instanceof FineDiffReplaceOp ) */ {
|
1696 |
+
FineDiff::renderDiffToHTMLFromOpcode('d', $this->from_text, $in_offset, $n);
|
1697 |
+
FineDiff::renderDiffToHTMLFromOpcode('i', $edit->getText(), 0, $edit->getToLen());
|
1698 |
+
}
|
1699 |
+
$in_offset += $n;
|
1700 |
+
}
|
1701 |
+
return ob_get_clean();
|
1702 |
+
}
|
1703 |
+
|
1704 |
+
const characterDelimiters = "";
|
1705 |
+
|
1706 |
+
public static $characterGranularity = array(
|
1707 |
+
FineDiff::characterDelimiters
|
1708 |
+
);
|
1709 |
+
|
1710 |
+
private function doDiff($from_text, $to_text)
|
1711 |
+
{
|
1712 |
+
$this->last_edit = false;
|
1713 |
+
$this->stackpointer = 0;
|
1714 |
+
$this->from_text = $from_text;
|
1715 |
+
$this->from_offset = 0;
|
1716 |
+
// can't diff without at least one granularity specifier
|
1717 |
+
if (empty($this->granularityStack)) {
|
1718 |
+
return;
|
1719 |
+
}
|
1720 |
+
$this->_processGranularity($from_text, $to_text);
|
1721 |
+
}
|
1722 |
+
|
1723 |
+
private function _processGranularity($from_segment, $to_segment)
|
1724 |
+
{
|
1725 |
+
$delimiters = $this->granularityStack[$this->stackpointer++];
|
1726 |
+
$has_next_stage = $this->stackpointer < count($this->granularityStack);
|
1727 |
+
foreach (FineDiff::doFragmentDiff($from_segment, $to_segment, $delimiters) as $fragment_edit) {
|
1728 |
+
// increase granularity
|
1729 |
+
if ($fragment_edit instanceof FineDiffReplaceOp && $has_next_stage) {
|
1730 |
+
$this->_processGranularity(
|
1731 |
+
substr($this->from_text, $this->from_offset, $fragment_edit->getFromLen()), $fragment_edit->getText()
|
1732 |
+
);
|
1733 |
+
}
|
1734 |
+
// fuse copy ops whenever possible
|
1735 |
+
else if ($fragment_edit instanceof FineDiffCopyOp && $this->last_edit instanceof FineDiffCopyOp) {
|
1736 |
+
$this->edits[count($this->edits) - 1]->increase($fragment_edit->getFromLen());
|
1737 |
+
$this->from_offset += $fragment_edit->getFromLen();
|
1738 |
+
} else {
|
1739 |
+
/* $fragment_edit instanceof FineDiffCopyOp */
|
1740 |
+
/* $fragment_edit instanceof FineDiffDeleteOp */
|
1741 |
+
/* $fragment_edit instanceof FineDiffInsertOp */
|
1742 |
+
$this->edits[] = $this->last_edit = $fragment_edit;
|
1743 |
+
$this->from_offset += $fragment_edit->getFromLen();
|
1744 |
+
}
|
1745 |
+
}
|
1746 |
+
$this->stackpointer--;
|
1747 |
+
}
|
1748 |
+
|
1749 |
+
private static function doFragmentDiff($from_text, $to_text, $delimiters)
|
1750 |
+
{
|
1751 |
+
// Empty delimiter means character-level diffing.
|
1752 |
+
// In such case, use code path optimized for character-level
|
1753 |
+
// diffing.
|
1754 |
+
if (empty($delimiters)) {
|
1755 |
+
return FineDiff::doCharDiff($from_text, $to_text);
|
1756 |
+
}
|
1757 |
+
|
1758 |
+
$result = array();
|
1759 |
+
|
1760 |
+
// fragment-level diffing
|
1761 |
+
$from_text_len = strlen($from_text);
|
1762 |
+
$to_text_len = strlen($to_text);
|
1763 |
+
$from_fragments = FineDiff::extractFragments($from_text, $delimiters);
|
1764 |
+
$to_fragments = FineDiff::extractFragments($to_text, $delimiters);
|
1765 |
+
|
1766 |
+
$jobs = array(array(0, $from_text_len, 0, $to_text_len));
|
1767 |
+
|
1768 |
+
$cached_array_keys = array();
|
1769 |
+
|
1770 |
+
while ($job = array_pop($jobs)) {
|
1771 |
+
|
1772 |
+
// get the segments which must be diff'ed
|
1773 |
+
list($from_segment_start, $from_segment_end, $to_segment_start, $to_segment_end) = $job;
|
1774 |
+
|
1775 |
+
// catch easy cases first
|
1776 |
+
$from_segment_length = $from_segment_end - $from_segment_start;
|
1777 |
+
$to_segment_length = $to_segment_end - $to_segment_start;
|
1778 |
+
if (!$from_segment_length || !$to_segment_length) {
|
1779 |
+
if ($from_segment_length) {
|
1780 |
+
$result[$from_segment_start * 4] = new FineDiffDeleteOp($from_segment_length);
|
1781 |
+
} else if ($to_segment_length) {
|
1782 |
+
$result[$from_segment_start * 4 + 1] = new FineDiffInsertOp(substr($to_text, $to_segment_start, $to_segment_length));
|
1783 |
+
}
|
1784 |
+
continue;
|
1785 |
+
}
|
1786 |
+
|
1787 |
+
// find longest copy operation for the current segments
|
1788 |
+
$best_copy_length = 0;
|
1789 |
+
|
1790 |
+
$from_base_fragment_index = $from_segment_start;
|
1791 |
+
|
1792 |
+
$cached_array_keys_for_current_segment = array();
|
1793 |
+
|
1794 |
+
while ($from_base_fragment_index < $from_segment_end) {
|
1795 |
+
$from_base_fragment = $from_fragments[$from_base_fragment_index];
|
1796 |
+
$from_base_fragment_length = strlen($from_base_fragment);
|
1797 |
+
// performance boost: cache array keys
|
1798 |
+
if (!isset($cached_array_keys_for_current_segment[$from_base_fragment])) {
|
1799 |
+
if (!isset($cached_array_keys[$from_base_fragment])) {
|
1800 |
+
$to_all_fragment_indices = $cached_array_keys[$from_base_fragment] = array_keys($to_fragments, $from_base_fragment, true);
|
1801 |
+
} else {
|
1802 |
+
$to_all_fragment_indices = $cached_array_keys[$from_base_fragment];
|
1803 |
+
}
|
1804 |
+
// get only indices which falls within current segment
|
1805 |
+
if ($to_segment_start > 0 || $to_segment_end < $to_text_len) {
|
1806 |
+
$to_fragment_indices = array();
|
1807 |
+
foreach ($to_all_fragment_indices as $to_fragment_index) {
|
1808 |
+
if ($to_fragment_index < $to_segment_start) {
|
1809 |
+
continue;
|
1810 |
+
}
|
1811 |
+
if ($to_fragment_index >= $to_segment_end) {
|
1812 |
+
break;
|
1813 |
+
}
|
1814 |
+
$to_fragment_indices[] = $to_fragment_index;
|
1815 |
+
}
|
1816 |
+
$cached_array_keys_for_current_segment[$from_base_fragment] = $to_fragment_indices;
|
1817 |
+
} else {
|
1818 |
+
$to_fragment_indices = $to_all_fragment_indices;
|
1819 |
+
}
|
1820 |
+
} else {
|
1821 |
+
$to_fragment_indices = $cached_array_keys_for_current_segment[$from_base_fragment];
|
1822 |
+
}
|
1823 |
+
// iterate through collected indices
|
1824 |
+
foreach ($to_fragment_indices as $to_base_fragment_index) {
|
1825 |
+
$fragment_index_offset = $from_base_fragment_length;
|
1826 |
+
// iterate until no more match
|
1827 |
+
for (;;) {
|
1828 |
+
$fragment_from_index = $from_base_fragment_index + $fragment_index_offset;
|
1829 |
+
if ($fragment_from_index >= $from_segment_end) {
|
1830 |
+
break;
|
1831 |
+
}
|
1832 |
+
$fragment_to_index = $to_base_fragment_index + $fragment_index_offset;
|
1833 |
+
if ($fragment_to_index >= $to_segment_end) {
|
1834 |
+
break;
|
1835 |
+
}
|
1836 |
+
if ($from_fragments[$fragment_from_index] !== $to_fragments[$fragment_to_index]) {
|
1837 |
+
break;
|
1838 |
+
}
|
1839 |
+
$fragment_length = strlen($from_fragments[$fragment_from_index]);
|
1840 |
+
$fragment_index_offset += $fragment_length;
|
1841 |
+
}
|
1842 |
+
if ($fragment_index_offset > $best_copy_length) {
|
1843 |
+
$best_copy_length = $fragment_index_offset;
|
1844 |
+
$best_from_start = $from_base_fragment_index;
|
1845 |
+
$best_to_start = $to_base_fragment_index;
|
1846 |
+
}
|
1847 |
+
}
|
1848 |
+
$from_base_fragment_index += strlen($from_base_fragment);
|
1849 |
+
// If match is larger than half segment size, no point trying to find better
|
1850 |
+
// TODO: Really?
|
1851 |
+
if ($best_copy_length >= $from_segment_length / 2) {
|
1852 |
+
break;
|
1853 |
+
}
|
1854 |
+
// no point to keep looking if what is left is less than
|
1855 |
+
// current best match
|
1856 |
+
if ($from_base_fragment_index + $best_copy_length >= $from_segment_end) {
|
1857 |
+
break;
|
1858 |
+
}
|
1859 |
+
}
|
1860 |
+
|
1861 |
+
if ($best_copy_length) {
|
1862 |
+
$jobs[] = array($from_segment_start, $best_from_start, $to_segment_start, $best_to_start);
|
1863 |
+
$result[$best_from_start * 4 + 2] = new FineDiffCopyOp($best_copy_length);
|
1864 |
+
$jobs[] = array($best_from_start + $best_copy_length, $from_segment_end, $best_to_start + $best_copy_length, $to_segment_end);
|
1865 |
+
} else {
|
1866 |
+
$result[$from_segment_start * 4] = new FineDiffReplaceOp($from_segment_length, substr($to_text, $to_segment_start, $to_segment_length));
|
1867 |
+
}
|
1868 |
+
}
|
1869 |
+
|
1870 |
+
ksort($result, SORT_NUMERIC);
|
1871 |
+
return array_values($result);
|
1872 |
+
}
|
1873 |
+
|
1874 |
+
private static function doCharDiff($from_text, $to_text)
|
1875 |
+
{
|
1876 |
+
$result = array();
|
1877 |
+
$jobs = array(array(0, strlen($from_text), 0, strlen($to_text)));
|
1878 |
+
while ($job = array_pop($jobs)) {
|
1879 |
+
// get the segments which must be diff'ed
|
1880 |
+
list($from_segment_start, $from_segment_end, $to_segment_start, $to_segment_end) = $job;
|
1881 |
+
$from_segment_len = $from_segment_end - $from_segment_start;
|
1882 |
+
$to_segment_len = $to_segment_end - $to_segment_start;
|
1883 |
+
|
1884 |
+
// catch easy cases first
|
1885 |
+
if (!$from_segment_len || !$to_segment_len) {
|
1886 |
+
if ($from_segment_len) {
|
1887 |
+
$result[$from_segment_start * 4 + 0] = new FineDiffDeleteOp($from_segment_len);
|
1888 |
+
} else if ($to_segment_len) {
|
1889 |
+
$result[$from_segment_start * 4 + 1] = new FineDiffInsertOp(substr($to_text, $to_segment_start, $to_segment_len));
|
1890 |
+
}
|
1891 |
+
continue;
|
1892 |
+
}
|
1893 |
+
if ($from_segment_len >= $to_segment_len) {
|
1894 |
+
$copy_len = $to_segment_len;
|
1895 |
+
while ($copy_len) {
|
1896 |
+
$to_copy_start = $to_segment_start;
|
1897 |
+
$to_copy_start_max = $to_segment_end - $copy_len;
|
1898 |
+
while ($to_copy_start <= $to_copy_start_max) {
|
1899 |
+
$from_copy_start = strpos(substr($from_text, $from_segment_start, $from_segment_len), substr($to_text, $to_copy_start, $copy_len));
|
1900 |
+
if ($from_copy_start !== false) {
|
1901 |
+
$from_copy_start += $from_segment_start;
|
1902 |
+
break 2;
|
1903 |
+
}
|
1904 |
+
$to_copy_start++;
|
1905 |
+
}
|
1906 |
+
$copy_len--;
|
1907 |
+
}
|
1908 |
+
} else {
|
1909 |
+
$copy_len = $from_segment_len;
|
1910 |
+
while ($copy_len) {
|
1911 |
+
$from_copy_start = $from_segment_start;
|
1912 |
+
$from_copy_start_max = $from_segment_end - $copy_len;
|
1913 |
+
while ($from_copy_start <= $from_copy_start_max) {
|
1914 |
+
$to_copy_start = strpos(substr($to_text, $to_segment_start, $to_segment_len), substr($from_text, $from_copy_start, $copy_len));
|
1915 |
+
if ($to_copy_start !== false) {
|
1916 |
+
$to_copy_start += $to_segment_start;
|
1917 |
+
break 2;
|
1918 |
+
}
|
1919 |
+
$from_copy_start++;
|
1920 |
+
}
|
1921 |
+
$copy_len--;
|
1922 |
+
}
|
1923 |
+
}
|
1924 |
+
// match found
|
1925 |
+
if ($copy_len) {
|
1926 |
+
$jobs[] = array($from_segment_start, $from_copy_start, $to_segment_start, $to_copy_start);
|
1927 |
+
$result[$from_copy_start * 4 + 2] = new FineDiffCopyOp($copy_len);
|
1928 |
+
$jobs[] = array($from_copy_start + $copy_len, $from_segment_end, $to_copy_start + $copy_len, $to_segment_end);
|
1929 |
+
}
|
1930 |
+
// no match, so delete all, insert all
|
1931 |
+
else {
|
1932 |
+
$result[$from_segment_start * 4] = new FineDiffReplaceOp($from_segment_len, substr($to_text, $to_segment_start, $to_segment_len));
|
1933 |
+
}
|
1934 |
+
}
|
1935 |
+
ksort($result, SORT_NUMERIC);
|
1936 |
+
return array_values($result);
|
1937 |
+
}
|
1938 |
+
|
1939 |
+
private static function extractFragments($text, $delimiters)
|
1940 |
+
{
|
1941 |
+
// special case: split into characters
|
1942 |
+
if (empty($delimiters)) {
|
1943 |
+
$chars = str_split($text, 1);
|
1944 |
+
$chars[strlen($text)] = '';
|
1945 |
+
return $chars;
|
1946 |
+
}
|
1947 |
+
$fragments = array();
|
1948 |
+
$start = $end = 0;
|
1949 |
+
for (;;) {
|
1950 |
+
$end += strcspn($text, $delimiters, $end);
|
1951 |
+
$end += strspn($text, $delimiters, $end);
|
1952 |
+
if ($end === $start) {
|
1953 |
+
break;
|
1954 |
+
}
|
1955 |
+
$fragments[$start] = substr($text, $start, $end - $start);
|
1956 |
+
$start = $end;
|
1957 |
+
}
|
1958 |
+
$fragments[$start] = '';
|
1959 |
+
return $fragments;
|
1960 |
+
}
|
1961 |
+
|
1962 |
+
private static function renderDiffToHTMLFromOpcode($opcode, $from, $from_offset, $from_len)
|
1963 |
+
{
|
1964 |
+
if ($opcode === 'c') {
|
1965 |
+
echo htmlspecialchars(substr($from, $from_offset, $from_len));
|
1966 |
+
} else if ($opcode === 'd') {
|
1967 |
+
$deletion = substr($from, $from_offset, $from_len);
|
1968 |
+
if (strcspn($deletion, " \n\r") === 0) {
|
1969 |
+
$deletion = str_replace(array("\n", "\r"), array('\n', '\r'), $deletion);
|
1970 |
+
}
|
1971 |
+
echo '<del>', htmlspecialchars($deletion), '</del>';
|
1972 |
+
} else /* if ( $opcode === 'i' ) */ {
|
1973 |
+
echo '<ins>', htmlspecialchars(substr($from, $from_offset, $from_len)), '</ins>';
|
1974 |
+
}
|
1975 |
+
}
|
1976 |
+
}
|
1977 |
+
|
1978 |
+
/*** CLASS DEFINITION END ***/
|
1979 |
+
|
1980 |
try {
|
1981 |
$boot = new DUPX_Bootstrap();
|
1982 |
$boot_error = $boot->run();
|
lib/config/class.wp.config.tranformer.php
CHANGED
@@ -7,6 +7,8 @@ if (!class_exists('WPConfigTransformer')):
|
|
7 |
*/
|
8 |
class WPConfigTransformer {
|
9 |
|
|
|
|
|
10 |
/**
|
11 |
* Path to the wp-config.php file.
|
12 |
*
|
@@ -93,7 +95,7 @@ class WPConfigTransformer {
|
|
93 |
*
|
94 |
* @return array
|
95 |
*/
|
96 |
-
public function get_value( $type, $name ) {
|
97 |
$wp_config_src = file_get_contents( $this->wp_config_path );
|
98 |
if ( ! trim( $wp_config_src ) ) {
|
99 |
throw new Exception( 'wp-config.php file is empty.' );
|
@@ -113,15 +115,40 @@ class WPConfigTransformer {
|
|
113 |
|
114 |
// Duplicator Extra
|
115 |
$val = $this->wp_configs[ $type ][ $name ]['value'];
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
|
|
120 |
|
121 |
return $val;
|
122 |
}
|
123 |
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
* Adds a config to the wp-config.php file.
|
126 |
*
|
127 |
* @throws Exception If the config value provided is not a string.
|
@@ -275,16 +302,12 @@ class WPConfigTransformer {
|
|
275 |
$new_src = implode( '', $new_parts );
|
276 |
}
|
277 |
|
278 |
-
|
279 |
-
// subst: $1\\$
|
280 |
-
$safe_new_src = preg_replace('/(^\$|^(?:\\\\\\\\)+|[^\\\\](?:\\\\\\\\)+|[^\\\\])\$/m', '$1\\\\$' , trim($new_src));
|
281 |
-
|
282 |
-
$contents = preg_replace(
|
283 |
sprintf( '/(?<=^|;|<\?php\s|<\?\s)(\s*?)%s/m', preg_quote( trim( $old_src ), '/' ) ),
|
284 |
-
'$1' .
|
285 |
$this->wp_config_src
|
286 |
);
|
287 |
-
|
288 |
return $this->save( $contents );
|
289 |
}
|
290 |
|
@@ -433,4 +456,4 @@ class WPConfigTransformer {
|
|
433 |
|
434 |
}
|
435 |
|
436 |
-
endif;
|
7 |
*/
|
8 |
class WPConfigTransformer {
|
9 |
|
10 |
+
const REPLACE_TEMP_STIRNG = '_1_2_RePlAcE_3_4_TeMp_5_6_StRiNg_7_8_';
|
11 |
+
|
12 |
/**
|
13 |
* Path to the wp-config.php file.
|
14 |
*
|
95 |
*
|
96 |
* @return array
|
97 |
*/
|
98 |
+
public function get_value( $type, $name, $get_real_value = true) {
|
99 |
$wp_config_src = file_get_contents( $this->wp_config_path );
|
100 |
if ( ! trim( $wp_config_src ) ) {
|
101 |
throw new Exception( 'wp-config.php file is empty.' );
|
115 |
|
116 |
// Duplicator Extra
|
117 |
$val = $this->wp_configs[ $type ][ $name ]['value'];
|
118 |
+
if ($get_real_value) {
|
119 |
+
return self::getRealValFromVal($val);
|
120 |
+
} else {
|
121 |
+
return $val;
|
122 |
+
}
|
123 |
|
124 |
return $val;
|
125 |
}
|
126 |
|
127 |
+
public static function getRealValFromVal($val)
|
128 |
+
{
|
129 |
+
if ($val[0] == '\'') {
|
130 |
+
// string with '
|
131 |
+
$result = substr($val, 1, strlen($val) - 2);
|
132 |
+
return str_replace(array('\\\'' , '\\\\'), array('\'', '\\'), $result);
|
133 |
+
} else if ($val[0] == '"') {
|
134 |
+
// string with "
|
135 |
+
return json_decode(str_replace('\\$', '$', $val));
|
136 |
+
} else if (strcasecmp($val, 'true')) {
|
137 |
+
return true;
|
138 |
+
} else if (strcasecmp($val, 'false')) {
|
139 |
+
return false;
|
140 |
+
} else if (strcasecmp($val, 'null')) {
|
141 |
+
return null;
|
142 |
+
} else if (preg_match('/^[-+]?[0-9]+$/', $val)) {
|
143 |
+
return (int) $val;
|
144 |
+
} else if (preg_match('/^[-+]?[0-9]+\.[0-9]+$/', $val)) {
|
145 |
+
return (float) $val;
|
146 |
+
} else {
|
147 |
+
return $val;
|
148 |
+
}
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
* Adds a config to the wp-config.php file.
|
153 |
*
|
154 |
* @throws Exception If the config value provided is not a string.
|
302 |
$new_src = implode( '', $new_parts );
|
303 |
}
|
304 |
|
305 |
+
$contents = preg_replace(
|
|
|
|
|
|
|
|
|
306 |
sprintf( '/(?<=^|;|<\?php\s|<\?\s)(\s*?)%s/m', preg_quote( trim( $old_src ), '/' ) ),
|
307 |
+
'$1' . self::REPLACE_TEMP_STIRNG ,
|
308 |
$this->wp_config_src
|
309 |
);
|
310 |
+
$contents = str_replace(self::REPLACE_TEMP_STIRNG, trim($new_src), $contents);
|
311 |
return $this->save( $contents );
|
312 |
}
|
313 |
|
456 |
|
457 |
}
|
458 |
|
459 |
+
endif;
|
lib/config/class.wp.config.tranformer.src.php
CHANGED
@@ -59,7 +59,7 @@ if (!class_exists('WPConfigTransformerSrc')):
|
|
59 |
*
|
60 |
* @return array
|
61 |
*/
|
62 |
-
public function get_value($type, $name)
|
63 |
{
|
64 |
$this->wp_configs = $this->parse_wp_config($this->wp_config_src);
|
65 |
|
@@ -69,17 +69,16 @@ if (!class_exists('WPConfigTransformerSrc')):
|
|
69 |
|
70 |
// Duplicator Extra
|
71 |
$val = $this->wp_configs[$type][$name]['value'];
|
72 |
-
if (
|
73 |
-
|
74 |
-
|
|
|
75 |
}
|
76 |
-
|
77 |
-
return $val;
|
78 |
}
|
79 |
|
80 |
/**
|
81 |
* update wp_config_src
|
82 |
-
*
|
83 |
* @param string $contents
|
84 |
* @return boolean
|
85 |
*/
|
@@ -89,5 +88,5 @@ if (!class_exists('WPConfigTransformerSrc')):
|
|
89 |
return true;
|
90 |
}
|
91 |
}
|
92 |
-
|
93 |
endif;
|
59 |
*
|
60 |
* @return array
|
61 |
*/
|
62 |
+
public function get_value($type, $name, $get_real_value = true)
|
63 |
{
|
64 |
$this->wp_configs = $this->parse_wp_config($this->wp_config_src);
|
65 |
|
69 |
|
70 |
// Duplicator Extra
|
71 |
$val = $this->wp_configs[$type][$name]['value'];
|
72 |
+
if ($get_real_value) {
|
73 |
+
return self::getRealValFromVal($val);
|
74 |
+
} else {
|
75 |
+
return $val;
|
76 |
}
|
|
|
|
|
77 |
}
|
78 |
|
79 |
/**
|
80 |
* update wp_config_src
|
81 |
+
*
|
82 |
* @param string $contents
|
83 |
* @return boolean
|
84 |
*/
|
88 |
return true;
|
89 |
}
|
90 |
}
|
91 |
+
|
92 |
endif;
|
lib/dup_archive/classes/class.duparchive.engine.php
CHANGED
@@ -575,18 +575,11 @@ class DupArchiveEngine
|
|
575 |
|
576 |
if (!$expandState->validateOnly) {
|
577 |
$directory = $expandState->basePath . '/' . $directoryHeader->relativePath;
|
578 |
-
|
579 |
-
$mode = $directoryHeader->permissions;
|
580 |
-
|
581 |
if ($expandState->directoryModeOverride != -1) {
|
582 |
$mode = $expandState->directoryModeOverride;
|
583 |
}
|
584 |
-
|
585 |
-
if (!file_exists($directory)) {
|
586 |
-
$createdDirectory = @mkdir($directory, $mode, true);
|
587 |
-
} else {
|
588 |
-
$createdDirectory = true;
|
589 |
-
}
|
590 |
}
|
591 |
|
592 |
if ($createdDirectory) {
|
575 |
|
576 |
if (!$expandState->validateOnly) {
|
577 |
$directory = $expandState->basePath . '/' . $directoryHeader->relativePath;
|
578 |
+
$mode = 'u+rwx';
|
|
|
|
|
579 |
if ($expandState->directoryModeOverride != -1) {
|
580 |
$mode = $expandState->directoryModeOverride;
|
581 |
}
|
582 |
+
$createdDirectory = DupLiteSnapLibIOU::dirWriteCheckOrMkdir($directory, $mode, true);
|
|
|
|
|
|
|
|
|
|
|
583 |
}
|
584 |
|
585 |
if ($createdDirectory) {
|
lib/dup_archive/classes/class.duparchive.mini.expander.php
CHANGED
@@ -148,6 +148,9 @@ class DupArchiveMiniHeader
|
|
148 |
private function __construct()
|
149 |
{
|
150 |
// Prevent instantiation
|
|
|
|
|
|
|
151 |
}
|
152 |
|
153 |
public static function readFromArchive($archiveHandle)
|
@@ -293,7 +296,7 @@ class DupArchiveMiniExpander
|
|
293 |
// $mode = $directoryHeader->permissions;
|
294 |
|
295 |
// rodo handle this more elegantly @mkdir($directory, $directoryHeader->permissions, true);
|
296 |
-
|
297 |
|
298 |
|
299 |
$writeInfo->directoryWriteCount++;
|
@@ -349,19 +352,13 @@ class DupArchiveMiniExpander
|
|
349 |
{
|
350 |
/* @var $writeInfo DupArchiveMiniWriteInfo */
|
351 |
$parentDir = dirname($destFilePath);
|
352 |
-
|
353 |
if (!file_exists($parentDir)) {
|
|
|
|
|
|
|
|
|
354 |
|
355 |
-
|
356 |
-
|
357 |
-
if(!$r)
|
358 |
-
{
|
359 |
-
throw new Exception("Couldn't create {$parentDir}");
|
360 |
-
}
|
361 |
-
}
|
362 |
-
|
363 |
-
$destFileHandle = fopen($destFilePath, 'wb+');
|
364 |
-
|
365 |
if ($destFileHandle === false) {
|
366 |
throw new Exception("Couldn't open {$destFilePath} for writing.");
|
367 |
}
|
@@ -377,14 +374,14 @@ class DupArchiveMiniExpander
|
|
377 |
|
378 |
fclose($destFileHandle);
|
379 |
|
380 |
-
|
381 |
|
382 |
self::validateExpandedFile($writeInfo);
|
383 |
} else {
|
384 |
if(touch($destFilePath) === false) {
|
385 |
throw new Exception("Couldn't create $destFilePath");
|
386 |
}
|
387 |
-
|
388 |
}
|
389 |
}
|
390 |
|
148 |
private function __construct()
|
149 |
{
|
150 |
// Prevent instantiation
|
151 |
+
if (!class_exists('DUPX_Bootstrap')) {
|
152 |
+
throw new Exception('Class DUPX_Bootstrap not found');
|
153 |
+
}
|
154 |
}
|
155 |
|
156 |
public static function readFromArchive($archiveHandle)
|
296 |
// $mode = $directoryHeader->permissions;
|
297 |
|
298 |
// rodo handle this more elegantly @mkdir($directory, $directoryHeader->permissions, true);
|
299 |
+
DUPX_Bootstrap::mkdir($directory, 'u+rwx', true);
|
300 |
|
301 |
|
302 |
$writeInfo->directoryWriteCount++;
|
352 |
{
|
353 |
/* @var $writeInfo DupArchiveMiniWriteInfo */
|
354 |
$parentDir = dirname($destFilePath);
|
|
|
355 |
if (!file_exists($parentDir)) {
|
356 |
+
if (!DUPX_Bootstrap::mkdir($parentDir, 'u+rwx', true)) {
|
357 |
+
throw new Exception("Couldn't create {$parentDir}");
|
358 |
+
}
|
359 |
+
}
|
360 |
|
361 |
+
$destFileHandle = fopen($destFilePath, 'wb+');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
if ($destFileHandle === false) {
|
363 |
throw new Exception("Couldn't open {$destFilePath} for writing.");
|
364 |
}
|
374 |
|
375 |
fclose($destFileHandle);
|
376 |
|
377 |
+
DUPX_Bootstrap::chmod($destFilePath, 'u+rw');
|
378 |
|
379 |
self::validateExpandedFile($writeInfo);
|
380 |
} else {
|
381 |
if(touch($destFilePath) === false) {
|
382 |
throw new Exception("Couldn't create $destFilePath");
|
383 |
}
|
384 |
+
DUPX_Bootstrap::chmod($destFilePath, 'u+rw');
|
385 |
}
|
386 |
}
|
387 |
|
lib/dup_archive/classes/processors/class.duparchive.processor.file.php
CHANGED
@@ -113,10 +113,7 @@ class DupArchiveFileProcessor
|
|
113 |
|
114 |
$moreGlobstoProcess = true;
|
115 |
|
116 |
-
|
117 |
-
|
118 |
-
DupLiteSnapLibIOU::mkdir($parentDir, 0755, true);
|
119 |
-
}
|
120 |
|
121 |
if ($expandState->currentFileHeader->fileSize > 0) {
|
122 |
|
@@ -192,9 +189,9 @@ class DupArchiveFileProcessor
|
|
192 |
}
|
193 |
|
194 |
if (!$moreGlobstoProcess && $expandState->validateOnly && ($expandState->validationType == DupArchiveValidationTypes::Full)) {
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
if (@unlink($destFilepath) === false) {
|
199 |
// $expandState->addFailure(DupArchiveFailureTypes::File, $destFilepath, "Couldn't delete {$destFilepath} during validation", false);
|
200 |
// TODO: Have to know how to handle this - want to report it but don’t want to mess up validation - some non critical errors could be important to validation
|
@@ -256,14 +253,11 @@ class DupArchiveFileProcessor
|
|
256 |
|
257 |
public static function setFileMode($expandState, $filePath)
|
258 |
{
|
259 |
-
$mode =
|
260 |
-
|
261 |
-
if($expandState->fileModeOverride != -1) {
|
262 |
-
|
263 |
$mode = $expandState->fileModeOverride;
|
264 |
}
|
265 |
-
|
266 |
-
@chmod($filePath, $mode);
|
267 |
}
|
268 |
|
269 |
public static function standardValidateFileEntry(&$expandState, $archiveHandle)
|
113 |
|
114 |
$moreGlobstoProcess = true;
|
115 |
|
116 |
+
DupLiteSnapLibIOU::dirWriteCheckOrMkdir($parentDir, 'u+rwx');
|
|
|
|
|
|
|
117 |
|
118 |
if ($expandState->currentFileHeader->fileSize > 0) {
|
119 |
|
189 |
}
|
190 |
|
191 |
if (!$moreGlobstoProcess && $expandState->validateOnly && ($expandState->validationType == DupArchiveValidationTypes::Full)) {
|
192 |
+
if (!is_writable($destFilepath)) {
|
193 |
+
DupLiteSnapLibIOU::chmod($destFilepath, 'u+rw');
|
194 |
+
}
|
195 |
if (@unlink($destFilepath) === false) {
|
196 |
// $expandState->addFailure(DupArchiveFailureTypes::File, $destFilepath, "Couldn't delete {$destFilepath} during validation", false);
|
197 |
// TODO: Have to know how to handle this - want to report it but don’t want to mess up validation - some non critical errors could be important to validation
|
253 |
|
254 |
public static function setFileMode($expandState, $filePath)
|
255 |
{
|
256 |
+
$mode = 'u+rw';
|
257 |
+
if($expandState->fileModeOverride !== -1) {
|
|
|
|
|
258 |
$mode = $expandState->fileModeOverride;
|
259 |
}
|
260 |
+
DupLiteSnapLibIOU::chmod($filePath, $mode);
|
|
|
261 |
}
|
262 |
|
263 |
public static function standardValidateFileEntry(&$expandState, $archiveHandle)
|
lib/dup_archive/daws/daws.php
CHANGED
@@ -131,7 +131,7 @@ class DAWS
|
|
131 |
$expandState->filteredFiles = $filteredFiles;
|
132 |
$expandState->fileRenames = $fileRenames;
|
133 |
$expandState->fileModeOverride = 0644;
|
134 |
-
$expandState->directoryModeOverride =
|
135 |
|
136 |
$expandState->save();
|
137 |
}
|
131 |
$expandState->filteredFiles = $filteredFiles;
|
132 |
$expandState->fileRenames = $fileRenames;
|
133 |
$expandState->fileModeOverride = 0644;
|
134 |
+
$expandState->directoryModeOverride = 'u+rwx';
|
135 |
|
136 |
$expandState->save();
|
137 |
}
|
lib/snaplib/class.snaplib.u.io.php
CHANGED
@@ -37,8 +37,7 @@ if (!class_exists('DupLiteSnapLibIOU', false)) {
|
|
37 |
foreach ($filePaths as $filePath) {
|
38 |
$modes[] = $mode;
|
39 |
}
|
40 |
-
|
41 |
-
@array_map('chmod', $filePaths, $modes);
|
42 |
}
|
43 |
|
44 |
public static function copy($source, $dest, $overwriteIfExists = true)
|
@@ -71,8 +70,8 @@ if (!class_exists('DupLiteSnapLibIOU', false)) {
|
|
71 |
|
72 |
$destination = rtrim($destination, '/\\');
|
73 |
|
74 |
-
if (!file_exists($destination)) {
|
75 |
-
self::mkdir($destination);
|
76 |
}
|
77 |
|
78 |
foreach ($fileSystemObjects as $fileSystemObject) {
|
@@ -126,11 +125,8 @@ if (!class_exists('DupLiteSnapLibIOU', false)) {
|
|
126 |
|
127 |
public static function fopen($filepath, $mode, $throwOnError = true)
|
128 |
{
|
129 |
-
if (DupLiteSnapLibOSU
|
130 |
-
|
131 |
-
if (strlen($filepath) > DupLiteSnapLibOSU::WindowsMaxPathLength) {
|
132 |
-
throw new Exception("Skipping a file that exceeds allowed Windows path length. File: {$filepath}");
|
133 |
-
}
|
134 |
}
|
135 |
|
136 |
if (DupLiteSnapLibStringU::startsWith($mode, 'w') || DupLiteSnapLibStringU::startsWith($mode, 'c') || file_exists($filepath)) {
|
@@ -168,7 +164,7 @@ if (!class_exists('DupLiteSnapLibIOU', false)) {
|
|
168 |
public static function rmdir($dirname, $mustExist = false)
|
169 |
{
|
170 |
if (file_exists($dirname)) {
|
171 |
-
|
172 |
if (@rmdir($dirname) === false) {
|
173 |
throw new Exception("Couldn't remove {$dirname}");
|
174 |
}
|
@@ -180,7 +176,7 @@ if (!class_exists('DupLiteSnapLibIOU', false)) {
|
|
180 |
public static function rm($filepath, $mustExist = false)
|
181 |
{
|
182 |
if (file_exists($filepath)) {
|
183 |
-
|
184 |
if (@unlink($filepath) === false) {
|
185 |
throw new Exception("Couldn't remove {$filepath}");
|
186 |
}
|
@@ -296,31 +292,33 @@ if (!class_exists('DupLiteSnapLibIOU', false)) {
|
|
296 |
return $mtime;
|
297 |
}
|
298 |
|
299 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
300 |
{
|
301 |
-
if (
|
302 |
-
|
303 |
-
if (strlen($pathname) > DupLiteSnapLibOSU::WindowsMaxPathLength) {
|
304 |
-
throw new Exception("Skipping creating directory that exceeds allowed Windows path length. File: {$pathname}");
|
305 |
-
}
|
306 |
}
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
}
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
}
|
317 |
-
}
|
318 |
-
|
319 |
-
public static function filePutContents($filename, $data)
|
320 |
-
{
|
321 |
if (file_put_contents($filename, $data) === false) {
|
322 |
-
throw new Exception(
|
323 |
}
|
|
|
324 |
}
|
325 |
|
326 |
public static function getFileName($file_path)
|
@@ -334,5 +332,187 @@ if (!class_exists('DupLiteSnapLibIOU', false)) {
|
|
334 |
$info = new SplFileInfo($file_path);
|
335 |
return $info->getPath();
|
336 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
337 |
}
|
338 |
}
|
37 |
foreach ($filePaths as $filePath) {
|
38 |
$modes[] = $mode;
|
39 |
}
|
40 |
+
array_map(array(__CLASS__, 'chmod'), $filePaths, $modes);
|
|
|
41 |
}
|
42 |
|
43 |
public static function copy($source, $dest, $overwriteIfExists = true)
|
70 |
|
71 |
$destination = rtrim($destination, '/\\');
|
72 |
|
73 |
+
if (!file_exists($destination) || !is_writeable($destination)) {
|
74 |
+
self::mkdir($destination, 'u+rwx');
|
75 |
}
|
76 |
|
77 |
foreach ($fileSystemObjects as $fileSystemObject) {
|
125 |
|
126 |
public static function fopen($filepath, $mode, $throwOnError = true)
|
127 |
{
|
128 |
+
if (strlen($filepath) > DupLiteSnapLibOSU::maxPathLen()) {
|
129 |
+
throw new Exception('Skipping a file that exceeds allowed max path length ['.DupLiteSnapLibOSU::maxPathLen().']. File: '.$filepath);
|
|
|
|
|
|
|
130 |
}
|
131 |
|
132 |
if (DupLiteSnapLibStringU::startsWith($mode, 'w') || DupLiteSnapLibStringU::startsWith($mode, 'c') || file_exists($filepath)) {
|
164 |
public static function rmdir($dirname, $mustExist = false)
|
165 |
{
|
166 |
if (file_exists($dirname)) {
|
167 |
+
self::chmod($dirname, 'u+rwx');
|
168 |
if (@rmdir($dirname) === false) {
|
169 |
throw new Exception("Couldn't remove {$dirname}");
|
170 |
}
|
176 |
public static function rm($filepath, $mustExist = false)
|
177 |
{
|
178 |
if (file_exists($filepath)) {
|
179 |
+
self::chmod($filepath, 'u+rw');
|
180 |
if (@unlink($filepath) === false) {
|
181 |
throw new Exception("Couldn't remove {$filepath}");
|
182 |
}
|
292 |
return $mtime;
|
293 |
}
|
294 |
|
295 |
+
/**
|
296 |
+
* exetute a file put contents after some checks. throw exception if fail.
|
297 |
+
*
|
298 |
+
* @param string $filename
|
299 |
+
* @param mixed $data
|
300 |
+
* @return boolean
|
301 |
+
* @throws Exception if putcontents fails
|
302 |
+
*/
|
303 |
+
public static function filePutContents($filename, $data)
|
304 |
{
|
305 |
+
if (($dirFile = realpath(dirname($filename))) === false) {
|
306 |
+
throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [realpath fail]');
|
|
|
|
|
|
|
307 |
}
|
308 |
+
if (!is_dir($dirFile)) {
|
309 |
+
throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [dir '.$dirFile.' don\'t exists]');
|
310 |
+
}
|
311 |
+
if (!is_writable($dirFile)) {
|
312 |
+
throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [dir '.$dirFile.' exists but isn\'t writable]');
|
313 |
+
}
|
314 |
+
$realFileName = $dirFile.basename($filename);
|
315 |
+
if (file_exists($realFileName) && !is_writable($realFileName)) {
|
316 |
+
throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [file exist '.$realFileName.' but isn\'t writable');
|
317 |
}
|
|
|
|
|
|
|
|
|
318 |
if (file_put_contents($filename, $data) === false) {
|
319 |
+
throw new Exception('FILE ERROR: put_content for file '.$filename.' failed [Couldn\'t write data to '.$realFileName.']');
|
320 |
}
|
321 |
+
return true;
|
322 |
}
|
323 |
|
324 |
public static function getFileName($file_path)
|
332 |
$info = new SplFileInfo($file_path);
|
333 |
return $info->getPath();
|
334 |
}
|
335 |
+
|
336 |
+
/**
|
337 |
+
* this function make a chmod only if the are different from perms input and if chmod function is enabled
|
338 |
+
*
|
339 |
+
* this function handles the variable MODE in a way similar to the chmod of lunux
|
340 |
+
* So the MODE variable can be
|
341 |
+
* 1) an octal number (0755)
|
342 |
+
* 2) a string that defines an octal number ("644")
|
343 |
+
* 3) a string with the following format [ugoa]*([-+=]([rwx]*)+
|
344 |
+
*
|
345 |
+
* examples
|
346 |
+
* u+rw add read and write at the user
|
347 |
+
* u+rw,uo-wx add read and write ad the user and remove wx at groupd and other
|
348 |
+
* a=rw is equal at 666
|
349 |
+
* u=rwx,go-rwx is equal at 700
|
350 |
+
*
|
351 |
+
* @param string $file
|
352 |
+
* @param int|string $mode
|
353 |
+
* @return boolean
|
354 |
+
*/
|
355 |
+
public static function chmod($file, $mode)
|
356 |
+
{
|
357 |
+
if (!file_exists($file)) {
|
358 |
+
return false;
|
359 |
+
}
|
360 |
+
|
361 |
+
$octalMode = 0;
|
362 |
+
|
363 |
+
if (is_int($mode)) {
|
364 |
+
$octalMode = $mode;
|
365 |
+
} else if (is_string($mode)) {
|
366 |
+
$mode = trim($mode);
|
367 |
+
if (preg_match('/([0-7]{1,3})/', $mode)) {
|
368 |
+
$octalMode = intval(('0'.$mode), 8);
|
369 |
+
} else if (preg_match_all('/(a|[ugo]{1,3})([-=+])([rwx]{1,3})/', $mode, $gMatch, PREG_SET_ORDER)) {
|
370 |
+
if (!function_exists('fileperms')) {
|
371 |
+
return false;
|
372 |
+
}
|
373 |
+
|
374 |
+
// start by file permission
|
375 |
+
$octalMode = (fileperms($file) & 0777);
|
376 |
+
|
377 |
+
foreach ($gMatch as $matches) {
|
378 |
+
// [ugo] or a = ugo
|
379 |
+
$group = $matches[1];
|
380 |
+
if ($group === 'a') {
|
381 |
+
$group = 'ugo';
|
382 |
+
}
|
383 |
+
// can be + - =
|
384 |
+
$action = $matches[2];
|
385 |
+
// [rwx]
|
386 |
+
$gPerms = $matches[3];
|
387 |
+
|
388 |
+
// reset octal group perms
|
389 |
+
$octalGroupMode = 0;
|
390 |
+
|
391 |
+
// Init sub perms
|
392 |
+
$subPerm = 0;
|
393 |
+
$subPerm += strpos($gPerms, 'x') !== false ? 1 : 0; // mask 001
|
394 |
+
$subPerm += strpos($gPerms, 'w') !== false ? 2 : 0; // mask 010
|
395 |
+
$subPerm += strpos($gPerms, 'r') !== false ? 4 : 0; // mask 100
|
396 |
+
|
397 |
+
$ugoLen = strlen($group);
|
398 |
+
|
399 |
+
if ($action === '=') {
|
400 |
+
// generate octal group permsissions and ugo mask invert
|
401 |
+
$ugoMaskInvert = 0777;
|
402 |
+
for ($i = 0; $i < $ugoLen; $i++) {
|
403 |
+
switch ($group[$i]) {
|
404 |
+
case 'u':
|
405 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000
|
406 |
+
$ugoMaskInvert = $ugoMaskInvert & 077;
|
407 |
+
break;
|
408 |
+
case 'g':
|
409 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000
|
410 |
+
$ugoMaskInvert = $ugoMaskInvert & 0707;
|
411 |
+
break;
|
412 |
+
case 'o':
|
413 |
+
$octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx
|
414 |
+
$ugoMaskInvert = $ugoMaskInvert & 0770;
|
415 |
+
break;
|
416 |
+
}
|
417 |
+
}
|
418 |
+
// apply = action
|
419 |
+
$octalMode = $octalMode & ($ugoMaskInvert | $octalGroupMode);
|
420 |
+
} else {
|
421 |
+
// generate octal group permsissions
|
422 |
+
for ($i = 0; $i < $ugoLen; $i++) {
|
423 |
+
switch ($group[$i]) {
|
424 |
+
case 'u':
|
425 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 6; // mask xxx000000
|
426 |
+
break;
|
427 |
+
case 'g':
|
428 |
+
$octalGroupMode = $octalGroupMode | $subPerm << 3; // mask 000xxx000
|
429 |
+
break;
|
430 |
+
case 'o':
|
431 |
+
$octalGroupMode = $octalGroupMode | $subPerm; // mask 000000xxx
|
432 |
+
break;
|
433 |
+
}
|
434 |
+
}
|
435 |
+
// apply + or - action
|
436 |
+
switch ($action) {
|
437 |
+
case '+':
|
438 |
+
$octalMode = $octalMode | $octalGroupMode;
|
439 |
+
break;
|
440 |
+
case '-':
|
441 |
+
$octalMode = $octalMode & ~$octalGroupMode;
|
442 |
+
break;
|
443 |
+
}
|
444 |
+
}
|
445 |
+
}
|
446 |
+
}
|
447 |
+
}
|
448 |
+
|
449 |
+
// if input permissions are equal at file permissions return true without performing chmod
|
450 |
+
if (function_exists('fileperms') && $octalMode === (fileperms($file) & 0777)) {
|
451 |
+
return true;
|
452 |
+
}
|
453 |
+
|
454 |
+
if (!function_exists('chmod')) {
|
455 |
+
return false;
|
456 |
+
}
|
457 |
+
|
458 |
+
return @chmod($file, $octalMode);
|
459 |
+
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* this function creates a folder if it does not exist and performs a chmod.
|
463 |
+
* it is different from the normal mkdir function to which an umask is applied to the input permissions.
|
464 |
+
*
|
465 |
+
* this function handles the variable MODE in a way similar to the chmod of lunux
|
466 |
+
* So the MODE variable can be
|
467 |
+
* 1) an octal number (0755)
|
468 |
+
* 2) a string that defines an octal number ("644")
|
469 |
+
* 3) a string with the following format [ugoa]*([-+=]([rwx]*)+
|
470 |
+
*
|
471 |
+
* @param string $path
|
472 |
+
* @param int|string $mode
|
473 |
+
* @param bool $recursive
|
474 |
+
* @param resource $context // not used fo windows bug
|
475 |
+
* @return boolean bool TRUE on success or FALSE on failure.
|
476 |
+
*
|
477 |
+
* @todo check recursive true and multiple chmod
|
478 |
+
*/
|
479 |
+
public static function mkdir($path, $mode = 0777, $recursive = false, $context = null)
|
480 |
+
{
|
481 |
+
if (strlen($path) > DupLiteSnapLibOSU::maxPathLen()) {
|
482 |
+
throw new Exception('Skipping a file that exceeds allowed max path length ['.DupLiteSnapLibOSU::maxPathLen().']. File: '.$filepath);
|
483 |
+
}
|
484 |
+
|
485 |
+
if (!file_exists($path)) {
|
486 |
+
if (!function_exists('mkdir')) {
|
487 |
+
return false;
|
488 |
+
}
|
489 |
+
if (!@mkdir($path, 0777, $recursive)) {
|
490 |
+
return false;
|
491 |
+
}
|
492 |
+
}
|
493 |
+
|
494 |
+
return self::chmod($path, $mode);
|
495 |
+
}
|
496 |
+
|
497 |
+
/**
|
498 |
+
* this function call snap mkdir if te folder don't exists od don't have write or exec permissions
|
499 |
+
*
|
500 |
+
* this function handles the variable MODE in a way similar to the chmod of lunux
|
501 |
+
* The mode variable can be set to have more flexibility but not giving the user write and read and exec permissions doesn't make much sense
|
502 |
+
*
|
503 |
+
* @param string $path
|
504 |
+
* @param int|string $mode
|
505 |
+
* @param bool $recursive
|
506 |
+
* @param resource $context
|
507 |
+
* @return boolean
|
508 |
+
*/
|
509 |
+
public static function dirWriteCheckOrMkdir($path, $mode = 'u+rwx', $recursive = false, $context = null)
|
510 |
+
{
|
511 |
+
if (!is_writable($path) || !is_executable($path)) {
|
512 |
+
return self::mkdir($path, $mode, $recursive, $context);
|
513 |
+
} else {
|
514 |
+
return true;
|
515 |
+
}
|
516 |
+
}
|
517 |
}
|
518 |
}
|
lib/snaplib/class.snaplib.u.os.php
CHANGED
@@ -16,15 +16,41 @@ if (!class_exists('DupLiteSnapLibOSU', false)) {
|
|
16 |
|
17 |
class DupLiteSnapLibOSU
|
18 |
{
|
19 |
-
const
|
|
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
|
|
|
|
|
|
|
|
24 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
}
|
28 |
}
|
29 |
-
DupLiteSnapLibOSU::init();
|
30 |
}
|
16 |
|
17 |
class DupLiteSnapLibOSU
|
18 |
{
|
19 |
+
const DEFAULT_WINDOWS_MAXPATH = 260;
|
20 |
+
const DEFAULT_LINUX_MAXPATH = 4096;
|
21 |
|
22 |
+
/**
|
23 |
+
* return true if current SO is windows
|
24 |
+
*
|
25 |
+
* @staticvar bool $isWindows
|
26 |
+
* @return bool
|
27 |
+
*/
|
28 |
+
public static function isWindows()
|
29 |
{
|
30 |
+
static $isWindows = null;
|
31 |
+
if (is_null($isWindows)) {
|
32 |
+
$isWindows = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
|
33 |
+
}
|
34 |
+
return $isWindows;
|
35 |
+
}
|
36 |
|
37 |
+
/**
|
38 |
+
* return current SO path path len
|
39 |
+
* @staticvar int $maxPath
|
40 |
+
* @return int
|
41 |
+
*/
|
42 |
+
public static function maxPathLen()
|
43 |
+
{
|
44 |
+
static $maxPath = null;
|
45 |
+
if (is_null($maxPath)) {
|
46 |
+
if (defined('PHP_MAXPATHLEN')) {
|
47 |
+
$maxPath = PHP_MAXPATHLEN;
|
48 |
+
} else {
|
49 |
+
// for PHP < 5.3.0
|
50 |
+
$maxPath = self::isWindows() ? self::DEFAULT_WINDOWS_MAXPATH : self::DEFAULT_LINUX_MAXPATH;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
return $maxPath;
|
54 |
}
|
55 |
}
|
|
|
56 |
}
|
lib/snaplib/class.snaplib.u.util.php
CHANGED
@@ -62,7 +62,7 @@ if (!class_exists('DupLiteSnapLibUtil', false)) {
|
|
62 |
public static function getWorkPercent($startingPercent, $endingPercent, $totalTaskCount, $currentTaskCount)
|
63 |
{
|
64 |
if ($totalTaskCount > 0) {
|
65 |
-
$percent =
|
66 |
} else {
|
67 |
$percent = 0;
|
68 |
}
|
62 |
public static function getWorkPercent($startingPercent, $endingPercent, $totalTaskCount, $currentTaskCount)
|
63 |
{
|
64 |
if ($totalTaskCount > 0) {
|
65 |
+
$percent = ($startingPercent + (($endingPercent - $startingPercent) * ($currentTaskCount / (float) $totalTaskCount)));
|
66 |
} else {
|
67 |
$percent = 0;
|
68 |
}
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Tags: migration, backup, restore, move, migrate, duplicate, transfer, clone, aut
|
|
4 |
Requires at least: 4.0
|
5 |
Tested up to: 5.2
|
6 |
Requires PHP: 5.2.17
|
7 |
-
Stable tag: 1.3.
|
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.2
|
6 |
Requires PHP: 5.2.17
|
7 |
+
Stable tag: 1.3.16
|
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/controller.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
|
|
|
3 |
DUP_Util::hasCapability('export');
|
4 |
|
5 |
global $wpdb;
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
+
|
4 |
+
DUP_Handler::init_error_handler();
|
5 |
DUP_Util::hasCapability('export');
|
6 |
|
7 |
global $wpdb;
|
views/packages/main/controller.php
CHANGED
@@ -1,6 +1,8 @@
|
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
|
3 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/ui/class.ui.dialog.php');
|
|
|
4 |
$current_tab = isset($_REQUEST['tab']) ? sanitize_text_field($_REQUEST['tab']) : 'list';
|
5 |
$_GET['_wpnonce'] = isset($_GET['_wpnonce']) ? $_GET['_wpnonce'] : null;
|
6 |
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
+
|
4 |
require_once(DUPLICATOR_PLUGIN_PATH . '/classes/ui/class.ui.dialog.php');
|
5 |
+
|
6 |
$current_tab = isset($_REQUEST['tab']) ? sanitize_text_field($_REQUEST['tab']) : 'list';
|
7 |
$_GET['_wpnonce'] = isset($_GET['_wpnonce']) ? $_GET['_wpnonce'] : null;
|
8 |
|
views/packages/main/packages.php
CHANGED
@@ -278,7 +278,7 @@ $alert2->initAlert();
|
|
278 |
|
279 |
$confirm1 = new DUP_UI_Dialog();
|
280 |
$confirm1->title = __('Delete Packages?', 'duplicator');
|
281 |
-
$confirm1->message = __('Are you sure
|
282 |
$confirm1->progressText = __('Removing Packages, Please Wait...', 'duplicator');
|
283 |
$confirm1->jscallback = 'Duplicator.Pack.Delete()';
|
284 |
$confirm1->initConfirm();
|
278 |
|
279 |
$confirm1 = new DUP_UI_Dialog();
|
280 |
$confirm1->title = __('Delete Packages?', 'duplicator');
|
281 |
+
$confirm1->message = __('Are you sure you want to delete the selected package(s)?', 'duplicator');
|
282 |
$confirm1->progressText = __('Removing Packages, Please Wait...', 'duplicator');
|
283 |
$confirm1->jscallback = 'Duplicator.Pack.Delete()';
|
284 |
$confirm1->initConfirm();
|
views/packages/main/s1.setup2.php
CHANGED
@@ -663,5 +663,7 @@ jQuery(document).ready(function ($)
|
|
663 |
Duplicator.Pack.ToggleDBFilters();
|
664 |
Duplicator.Pack.ExportOnlyDB();
|
665 |
Duplicator.Pack.EnableInstallerPassword();
|
|
|
|
|
666 |
});
|
667 |
</script>
|
663 |
Duplicator.Pack.ToggleDBFilters();
|
664 |
Duplicator.Pack.ExportOnlyDB();
|
665 |
Duplicator.Pack.EnableInstallerPassword();
|
666 |
+
$('input#package-name').focus().select();
|
667 |
+
|
668 |
});
|
669 |
</script>
|
views/packages/main/s3.build.php
CHANGED
@@ -502,7 +502,7 @@ jQuery(document).ready(function ($)
|
|
502 |
|
503 |
for (var j = 0; j < len; j++) {
|
504 |
failure = data.failures[j];
|
505 |
-
errorMessage += failure
|
506 |
}
|
507 |
alert(errorMessage);
|
508 |
}
|
502 |
|
503 |
for (var j = 0; j < len; j++) {
|
504 |
failure = data.failures[j];
|
505 |
+
errorMessage += failure + "\n";
|
506 |
}
|
507 |
alert(errorMessage);
|
508 |
}
|
views/settings/controller.php
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
|
|
|
4 |
DUP_Util::hasCapability('manage_options');
|
5 |
|
6 |
global $wpdb;
|
1 |
<?php
|
2 |
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
3 |
|
4 |
+
DUP_Handler::init_error_handler();
|
5 |
DUP_Util::hasCapability('manage_options');
|
6 |
|
7 |
global $wpdb;
|
views/settings/gopro.php
CHANGED
@@ -216,7 +216,7 @@ require_once(DUPLICATOR_PLUGIN_PATH . '/views/inc.header.php');
|
|
216 |
<?php esc_html_e('Active Customer Support', 'duplicator') ?>
|
217 |
<sup><i class="fa fa-question-circle dup-gopro-help"
|
218 |
data-tooltip-title="<?php esc_attr_e("Support", 'duplicator'); ?>"
|
219 |
-
data-tooltip="<?php esc_attr_e('Pro users get top priority for any
|
220 |
</td>
|
221 |
<td class="check-column"></td>
|
222 |
<td class="check-column"><i class="fa fa-check"></i></td>
|
@@ -236,4 +236,4 @@ require_once(DUPLICATOR_PLUGIN_PATH . '/views/inc.header.php');
|
|
236 |
</p>
|
237 |
<br/><br/>
|
238 |
</div>
|
239 |
-
<br/><br/>
|
216 |
<?php esc_html_e('Active Customer Support', 'duplicator') ?>
|
217 |
<sup><i class="fa fa-question-circle dup-gopro-help"
|
218 |
data-tooltip-title="<?php esc_attr_e("Support", 'duplicator'); ?>"
|
219 |
+
data-tooltip="<?php esc_attr_e('Pro users get top priority for any requests to our support desk. In most cases responses will be answered in under 24 hours.', 'duplicator'); ?>"/></i></sup>
|
220 |
</td>
|
221 |
<td class="check-column"></td>
|
222 |
<td class="check-column"><i class="fa fa-check"></i></td>
|
236 |
</p>
|
237 |
<br/><br/>
|
238 |
</div>
|
239 |
+
<br/><br/>
|
views/tools/controller.php
CHANGED
@@ -6,6 +6,8 @@ require_once(DUPLICATOR_PLUGIN_PATH . '/views/inc.header.php');
|
|
6 |
|
7 |
global $wpdb;
|
8 |
global $wp_version;
|
|
|
|
|
9 |
DUP_Util::hasCapability('manage_options');
|
10 |
$current_tab = isset($_REQUEST['tab']) ? esc_html($_REQUEST['tab']) : 'diagnostics';
|
11 |
if ('d' == $current_tab) {
|
6 |
|
7 |
global $wpdb;
|
8 |
global $wp_version;
|
9 |
+
|
10 |
+
DUP_Handler::init_error_handler();
|
11 |
DUP_Util::hasCapability('manage_options');
|
12 |
$current_tab = isset($_REQUEST['tab']) ? esc_html($_REQUEST['tab']) : 'diagnostics';
|
13 |
if ('d' == $current_tab) {
|