'https://oldurl/', 'replace' => 'https://newurl/')); array_push($GLOBALS['REPLACE_LIST'], array('search' => 'ftps://oldurl/', 'replace' => 'ftps://newurl/')); ================================================================================================= */ // Some machines don’t have this set so just do it here. date_default_timezone_set('UTC'); //PATCH FOR IIS: Does not support REQUEST_URI if (!isset($_SERVER['REQUEST_URI'])) { $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'],0); if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] != "") { $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING']; } } //COMPARE VALUES $GLOBALS['DUPX_DEBUG'] = false; $GLOBALS['DUPX_DBPASS_CHECK'] = true; $GLOBALS['FW_CREATED'] = '2018-12-12 12:47:59'; $GLOBALS['FW_VERSION_DUP'] = '1.2.52'; $GLOBALS['FW_VERSION_WP'] = '5.0'; $GLOBALS['FW_VERSION_DB'] = '5.5.60'; $GLOBALS['FW_VERSION_PHP'] = '7.2.12'; $GLOBALS['FW_VERSION_OS'] = 'Linux'; //GENERAL $GLOBALS['FW_TABLEPREFIX'] = 'KykQPwyJ'; $GLOBALS['FW_URL_OLD'] = 'http://donvalpetres.com'; $GLOBALS['FW_PACKAGE_NAME'] = '20181212_donvalpetresphotography_ac20cebabf6b77227559_20181212124759_archive.zip'; $GLOBALS['FW_PACKAGE_NOTES'] = ''; $GLOBALS['FW_PACKAGE_EST_SIZE'] = 222694432; $GLOBALS['FW_SECURE_NAME'] = '20181212_donvalpetresphotography_ac20cebabf6b77227559_20181212124759'; $GLOBALS['FW_DBHOST'] = ''; $GLOBALS['FW_DBHOST'] = empty($GLOBALS['FW_DBHOST']) ? 'localhost' : $GLOBALS['FW_DBHOST']; $GLOBALS['FW_DBPORT'] = ''; $GLOBALS['FW_DBPORT'] = empty($GLOBALS['FW_DBPORT']) ? 3306 : $GLOBALS['FW_DBPORT']; $GLOBALS['FW_DBNAME'] = ''; $GLOBALS['FW_DBUSER'] = ''; $GLOBALS['FW_DBPASS'] = ''; $GLOBALS['FW_SECUREON'] = 0; $GLOBALS['FW_SECUREPASS'] = '$2a$08$hUecCpJLLO0/GPPKTGvUZ.wjS7Ycojs8a5DH9obzZD1o0vwAzyx.6'; $GLOBALS['FW_BLOGNAME'] = 'Donval-Petres Photographie'; $GLOBALS['FW_WPROOT'] = '/homepages/45/d743460709/htdocs/clickandbuilds/SiteDonvalPetresPhotography/'; $GLOBALS['FW_WPLOGIN_URL'] = 'http://donvalpetres.com/wp-login.php'; $GLOBALS['FW_OPTS_DELETE'] = json_decode('["duplicator_ui_view_state","duplicator_package_active","duplicator_settings"]', true); $GLOBALS['FW_DUPLICATOR_VERSION'] = '1.2.52'; $GLOBALS['FW_ARCHIVE_ONLYDB'] = 0; $GLOBALS['PACKAGE_HASH'] = 'ac20ceb-12124759'; //DATABASE SETUP: all time in seconds $GLOBALS['DB_MAX_TIME'] = 5000; $GLOBALS['DB_MAX_PACKETS'] = 268435456; $GLOBALS['DB_FCGI_FLUSH'] = false; ini_set('mysql.connect_timeout', '5000'); //PHP SETUP: all time in seconds ini_set('memory_limit', '2048M'); ini_set("max_execution_time", '5000'); ini_set("max_input_time", '5000'); ini_set('default_socket_timeout', '5000'); @set_time_limit(0); $GLOBALS['DBCHARSET_DEFAULT'] = 'utf8'; $GLOBALS['DBCOLLATE_DEFAULT'] = 'utf8_general_ci'; $GLOBALS['FAQ_URL'] = 'https://snapcreek.com/duplicator/docs/faqs-tech'; $GLOBALS['NOW_DATE'] = @date("Y-m-d-H:i:s"); $GLOBALS['DB_RENAME_PREFIX'] = 'x-bak__'; //UPDATE TABLE SETTINGS $GLOBALS['REPLACE_LIST'] = array(); /** ================================================================================================ END ADVANCED FEATURES: Do not edit below here. =================================================================================================== */ //CONSTANTS define("DUPLICATOR_INIT", 1); define("DUPLICATOR_SSDIR_NAME", 'wp-snapshots'); //This should match DUPLICATOR_SSDIR_NAME in duplicator.php //SHARED POST PARMS $_POST['action_step'] = isset($_POST['action_step']) ? DUPX_U::sanitize_text_field($_POST['action_step']) : "0"; $_POST['secure-pass'] = isset($_POST['secure-pass']) ? DUPX_U::sanitize_text_field($_POST['secure-pass']) : ''; if ($GLOBALS['FW_SECUREON']) { $pass_hasher = new DUPX_PasswordHash(8, FALSE); $post_secure_pass = DUPX_U::sanitize_text_field($_POST['secure-pass']); $pass_check = $pass_hasher->CheckPassword(base64_encode($post_secure_pass), $GLOBALS['FW_SECUREPASS']); if (! $pass_check) { $_POST['action_step'] = 0; } } /** Host has several combinations : localhost | localhost:55 | localhost: | http://localhost | http://localhost:55 */ if (isset($_POST['dbhost'])) { $post_db_host = DUPX_U::sanitize_text_field($_POST['dbhost']); $_POST['dbhost'] = DUPX_U::sanitize_text_field($post_db_host); } else { $_POST['dbhost'] = null; } if (isset($_POST['dbport'])) { $post_db_port = DUPX_U::sanitize_text_field($_POST['dbport']); $_POST['dbport'] = trim($post_db_port); } else { $_POST['dbport'] = 3306; } $_POST['dbuser'] = isset($_POST['dbuser']) ? DUPX_U::sanitize_text_field($_POST['dbuser']) : null; if (isset($_POST['dbpass'])) { $post_db_pass = DUPX_U::sanitize_text_field($_POST['dbpass']); $_POST['dbpass'] = trim($post_db_pass); } else { $_POST['dbpass'] = null; } if (isset($_POST['dbname'])) { $post_db_name = DUPX_U::sanitize_text_field($_POST['dbname']); $_POST['dbname'] = trim($post_db_name); } else { $_POST['dbname'] = null; } if (isset($_POST['dbcharset'])) { $post_db_charset = DUPX_U::sanitize_text_field($_POST['dbcharset']); $_POST['dbcharset'] = trim($post_db_charset); } else { $_POST['dbcharset'] = $GLOBALS['DBCHARSET_DEFAULT']; } if (isset($_POST['dbcollate'])) { $post_db_collate = DUPX_U::sanitize_text_field($_POST['dbcollate']); $_POST['dbcollate'] = trim($post_db_collate); } else { $_POST['dbcollate'] = $GLOBALS['DBCOLLATE_DEFAULT']; } //GLOBALS // Constants which are dependent on the $GLOBALS['DUPX_AC'] $GLOBALS['SQL_FILE_NAME'] = "dup-installer-data__{$GLOBALS['PACKAGE_HASH']}.sql"; $GLOBALS['LOG_FILE_NAME'] = "dup-installer-log__{$GLOBALS['PACKAGE_HASH']}.txt"; $GLOBALS['LOGGING'] = isset($_POST['logging']) ? DUPX_U::sanitize_text_field($_POST['logging']) : 1; $GLOBALS['CURRENT_ROOT_PATH'] = dirname(__FILE__); $GLOBALS['CHOWN_ROOT_PATH'] = @chmod("{$GLOBALS['CURRENT_ROOT_PATH']}", 0755); $GLOBALS['CHOWN_LOG_PATH'] = @chmod("{$GLOBALS['CURRENT_ROOT_PATH']}/{$GLOBALS['LOG_FILE_NAME']}", 0644); $GLOBALS['URL_SSL'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? true : false; $GLOBALS['URL_PATH'] = ($GLOBALS['URL_SSL']) ? "https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}" : "http://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}"; $GLOBALS['PHP_MEMORY_LIMIT'] = ini_get('memory_limit') === false ? 'n/a' : ini_get('memory_limit'); $GLOBALS['PHP_SUHOSIN_ON'] = extension_loaded('suhosin') ? 'enabled' : 'disabled'; $GLOBALS['ARCHIVE_PATH'] = $GLOBALS['CURRENT_ROOT_PATH'] . '/' . $GLOBALS['FW_PACKAGE_NAME']; $GLOBALS['ARCHIVE_PATH'] = str_replace("\\", "/", $GLOBALS['ARCHIVE_PATH']); if (isset($_GET["view"])) { $GLOBALS["VIEW"] = $_GET["view"]; } elseif (!empty($_POST["view"])) { $GLOBALS["VIEW"] = $_POST["view"]; } else { $GLOBALS["VIEW"] = 'step1'; } //Restart log if user starts from step 1 if ($_POST['action_step'] == 1 && ! isset($_GET['help'])) { $GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_NAME'], "w+"); } else { $GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_NAME'], "a+"); } ?> = 1024 && $i < 4; $i++) $size /= 1024; return round($size, 2).$units[$i]; } catch (Exception $e) { return "n/a"; } } /** * Converts shorthand memory notation value to bytes * * @param $val Memory size shorthand notation string such as 10M, 1G * * @returns int The byte representation of the shorthand $val */ public static function getBytes($val) { $val = trim($val); $last = strtolower($val[strlen($val) - 1]); switch ($last) { // The 'G' modifier is available since PHP 5.1.0 case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; break; default : $val = null; } return $val; } /** * Makes path safe for any OS for PHP * * Paths should ALWAYS READ be "/" * uni: /home/path/file.txt * win: D:/home/path/file.txt * * @param string $path The path to make safe * * @return string The original $path with a with all slashes facing '/'. */ public static function setSafePath($path) { return str_replace("\\", "/", $path); } /** * Looks for a list of strings in a string and returns each list item that is found * * @param array $list An array of strings to search for * @param string $haystack The string blob to search through * * @return array An array of strings from the $list array found in the $haystack */ public static function getListValues($list, $haystack) { $found = array(); foreach ($list as $var) { if (strstr($haystack, $var) !== false) { array_push($found, $var); } } return $found; } /** * Makes path unsafe for any OS for PHP used primarily to show default * Windows OS path standard * * @param string $path The path to make unsafe * * @return string The original $path with a with all slashes facing '\'. */ public static function unsetSafePath($path) { return str_replace("/", "\\", $path); } /** * Filter the string to escape the quote * * @param string $val The value to escape quote * * @return string Returns the input value escaped */ public static function safeQuote($val) { $val = addslashes($val); return $val; } /** * Check PHP version * * @param string $version PHP version we looking for * * @return boolean Returns true if version is same or above. */ public static function isVersion($version) { return (version_compare(PHP_VERSION, $version) >= 0); } // START ESCAPING AND SANITIZATION /** * Escaping for HTML blocks. * * @since 2.8.0 * * @param string $text * @return string */ public static function esc_html( $text ) { $safe_text = self::wp_check_invalid_utf8( $text ); $safe_text = self::_wp_specialchars( $safe_text, ENT_QUOTES ); /** * Filters a string cleaned and escaped for output in HTML. * * Text passed to esc_html() is stripped of invalid or special characters * before output. * * @since 2.8.0 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return $safe_text; } /** * Escape single quotes, htmlspecialchar " < > &, and fix line endings. * * Escapes text strings for echoing in JS. It is intended to be used for inline JS * (in a tag attribute, for example onclick="..."). Note that the strings have to * be in single quotes. The {@see 'js_escape'} filter is also applied here. * * @since 2.8.0 * * @param string $text The text to be escaped. * @return string Escaped text. */ public static function esc_js( $text ) { $safe_text = self::wp_check_invalid_utf8( $text ); $safe_text = self::_wp_specialchars( $safe_text, ENT_COMPAT ); $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) ); $safe_text = str_replace( "\r", '', $safe_text ); $safe_text = str_replace( "\n", '\\n', addslashes( $safe_text ) ); /** * Filters a string cleaned and escaped for output in JavaScript. * * Text passed to esc_js() is stripped of invalid or special characters, * and properly slashed for output. * * @since 2.0.6 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return $safe_text; } /** * Escaping for HTML attributes. * * @since 2.8.0 * * @param string $text * @return string */ public static function esc_attr( $text ) { $safe_text = self::wp_check_invalid_utf8( $text ); $safe_text = self::_wp_specialchars( $safe_text, ENT_QUOTES ); /** * Filters a string cleaned and escaped for output in an HTML attribute. * * Text passed to esc_attr() is stripped of invalid or special characters * before output. * * @since 2.0.6 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return $safe_text; } /** * Escaping for textarea values. * * @since 3.1.0 * * @param string $text * @return string */ public static function esc_textarea( $text ) { // $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) ); $safe_text = htmlspecialchars( $text, ENT_QUOTES, 'UTF-8' ); /** * Filters a string cleaned and escaped for output in a textarea element. * * @since 3.1.0 * * @param string $safe_text The text after it has been escaped. * @param string $text The text prior to being escaped. */ return $safe_text; } /** * Escape an HTML tag name. * * @since 2.5.0 * * @param string $tag_name * @return string */ function tag_escape( $tag_name ) { $safe_tag = strtolower( preg_replace('/[^a-zA-Z0-9_:]/', '', $tag_name) ); /** * Filters a string cleaned and escaped for output as an HTML tag. * * @since 2.8.0 * * @param string $safe_tag The tag name after it has been escaped. * @param string $tag_name The text before it was escaped. */ return $safe_tag; } /** * Converts a number of special characters into their HTML entities. * * Specifically deals with: &, <, >, ", and '. * * $quote_style can be set to ENT_COMPAT to encode " to * ", or ENT_QUOTES to do both. Default is ENT_NOQUOTES where no quotes are encoded. * * @since 1.2.2 * @access private * * @staticvar string $_charset * * @param string $string The text which is to be encoded. * @param int|string $quote_style Optional. Converts double quotes if set to ENT_COMPAT, * both single and double if set to ENT_QUOTES or none if set to ENT_NOQUOTES. * Also compatible with old values; converting single quotes if set to 'single', * double if set to 'double' or both if otherwise set. * Default is ENT_NOQUOTES. * @param string $charset Optional. The character encoding of the string. Default is false. * @param bool $double_encode Optional. Whether to encode existing html entities. Default is false. * @return string The encoded text with HTML entities. */ public static function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) { $string = (string) $string; if ( 0 === strlen( $string ) ) return ''; // Don't bother if there are no specialchars - saves some processing if ( ! preg_match( '/[&<>"\']/', $string ) ) return $string; // Account for the previous behaviour of the function when the $quote_style is not an accepted value if ( empty( $quote_style ) ) $quote_style = ENT_NOQUOTES; elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) $quote_style = ENT_QUOTES; // Store the site charset as a static to avoid multiple calls to wp_load_alloptions() if ( ! $charset ) { static $_charset = null; if ( ! isset( $_charset ) ) { $_charset = ''; } $charset = $_charset; } if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) $charset = 'UTF-8'; $_quote_style = $quote_style; if ( $quote_style === 'double' ) { $quote_style = ENT_COMPAT; $_quote_style = ENT_COMPAT; } elseif ( $quote_style === 'single' ) { $quote_style = ENT_NOQUOTES; } if ( ! $double_encode ) { // Guarantee every &entity; is valid, convert &garbage; into &garbage; // This is required for PHP < 5.4.0 because ENT_HTML401 flag is unavailable. $string = self::wp_kses_normalize_entities( $string ); } $string = @htmlspecialchars( $string, $quote_style, $charset, $double_encode ); // Back-compat. if ( 'single' === $_quote_style ) $string = str_replace( "'", ''', $string ); return $string; } /** * Converts a number of HTML entities into their special characters. * * Specifically deals with: &, <, >, ", and '. * * $quote_style can be set to ENT_COMPAT to decode " entities, * or ENT_QUOTES to do both " and '. Default is ENT_NOQUOTES where no quotes are decoded. * * @since 2.8.0 * * @param string $string The text which is to be decoded. * @param string|int $quote_style Optional. Converts double quotes if set to ENT_COMPAT, * both single and double if set to ENT_QUOTES or * none if set to ENT_NOQUOTES. * Also compatible with old _wp_specialchars() values; * converting single quotes if set to 'single', * double if set to 'double' or both if otherwise set. * Default is ENT_NOQUOTES. * @return string The decoded text without HTML entities. */ public static function wp_specialchars_decode( $string, $quote_style = ENT_NOQUOTES ) { $string = (string) $string; if ( 0 === strlen( $string ) ) { return ''; } // Don't bother if there are no entities - saves a lot of processing if ( strpos( $string, '&' ) === false ) { return $string; } // Match the previous behaviour of _wp_specialchars() when the $quote_style is not an accepted value if ( empty( $quote_style ) ) { $quote_style = ENT_NOQUOTES; } elseif ( !in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) { $quote_style = ENT_QUOTES; } // More complete than get_html_translation_table( HTML_SPECIALCHARS ) $single = array( ''' => '\'', ''' => '\'' ); $single_preg = array( '/�*39;/' => ''', '/�*27;/i' => ''' ); $double = array( '"' => '"', '"' => '"', '"' => '"' ); $double_preg = array( '/�*34;/' => '"', '/�*22;/i' => '"' ); $others = array( '<' => '<', '<' => '<', '>' => '>', '>' => '>', '&' => '&', '&' => '&', '&' => '&' ); $others_preg = array( '/�*60;/' => '<', '/�*62;/' => '>', '/�*38;/' => '&', '/�*26;/i' => '&' ); if ( $quote_style === ENT_QUOTES ) { $translation = array_merge( $single, $double, $others ); $translation_preg = array_merge( $single_preg, $double_preg, $others_preg ); } elseif ( $quote_style === ENT_COMPAT || $quote_style === 'double' ) { $translation = array_merge( $double, $others ); $translation_preg = array_merge( $double_preg, $others_preg ); } elseif ( $quote_style === 'single' ) { $translation = array_merge( $single, $others ); $translation_preg = array_merge( $single_preg, $others_preg ); } elseif ( $quote_style === ENT_NOQUOTES ) { $translation = $others; $translation_preg = $others_preg; } // Remove zero padding on numeric entities $string = preg_replace( array_keys( $translation_preg ), array_values( $translation_preg ), $string ); // Replace characters according to translation table return strtr( $string, $translation ); } /** * Checks for invalid UTF8 in a string. * * @since 2.8.0 * * @staticvar bool $is_utf8 * @staticvar bool $utf8_pcre * * @param string $string The text which is to be checked. * @param bool $strip Optional. Whether to attempt to strip out invalid UTF8. Default is false. * @return string The checked text. */ public static function wp_check_invalid_utf8( $string, $strip = false ) { $string = (string) $string; if ( 0 === strlen( $string ) ) { return ''; } // Store the site charset as a static to avoid multiple calls to get_option() static $is_utf8 = null; if ( ! isset( $is_utf8 ) ) { // $is_utf8 = in_array( get_option( 'blog_charset' ), array( 'utf8', 'utf-8', 'UTF8', 'UTF-8' ) ); $is_utf8 = true; } if ( ! $is_utf8 ) { return $string; } // Check for support for utf8 in the installed PCRE library once and store the result in a static static $utf8_pcre = null; if ( ! isset( $utf8_pcre ) ) { $utf8_pcre = @preg_match( '/^./u', 'a' ); } // We can't demand utf8 in the PCRE installation, so just return the string in those cases if ( !$utf8_pcre ) { return $string; } // preg_match fails when it encounters invalid UTF8 in $string if ( 1 === @preg_match( '/^./us', $string ) ) { return $string; } // Attempt to strip the bad chars if requested (not recommended) if ( $strip && function_exists( 'iconv' ) ) { return iconv( 'utf-8', 'utf-8', $string ); } return ''; } /** * Perform a deep string replace operation to ensure the values in $search are no longer present * * Repeats the replacement operation until it no longer replaces anything so as to remove "nested" values * e.g. $subject = '%0%0%0DDD', $search ='%0D', $result ='' rather than the '%0%0DD' that * str_replace would return * * @since 2.8.1 * @access private * * @param string|array $search The value being searched for, otherwise known as the needle. * An array may be used to designate multiple needles. * @param string $subject The string being searched and replaced on, otherwise known as the haystack. * @return string The string with the replaced svalues. */ private static function _deep_replace( $search, $subject ) { $subject = (string) $subject; $count = 1; while ( $count ) { $subject = str_replace( $search, '', $subject, $count ); } return $subject; } /** * Converts and fixes HTML entities. * * This function normalizes HTML entities. It will convert `AT&T` to the correct * `AT&T`, `:` to `:`, `&#XYZZY;` to `&#XYZZY;` and so on. * * @since 1.0.0 * * @param string $string Content to normalize entities * @return string Content with normalized entities */ public static function wp_kses_normalize_entities($string) { // Disarm all entities by converting & to & $string = str_replace('&', '&', $string); // Change back the allowed entities in our entity whitelist $string = preg_replace_callback('/&([A-Za-z]{2,8}[0-9]{0,2});/', 'self::wp_kses_named_entities', $string); $string = preg_replace_callback('/&#(0*[0-9]{1,7});/', 'self::wp_kses_normalize_entities2', $string); $string = preg_replace_callback('/&#[Xx](0*[0-9A-Fa-f]{1,6});/', 'self::wp_kses_normalize_entities3', $string); return $string; } /** * Callback for wp_kses_normalize_entities() regular expression. * * This function only accepts valid named entity references, which are finite, * case-sensitive, and highly scrutinized by HTML and XML validators. * * @since 3.0.0 * * @global array $allowedentitynames * * @param array $matches preg_replace_callback() matches array * @return string Correctly encoded entity */ public static function wp_kses_named_entities($matches) { global $allowedentitynames; if ( empty($matches[1]) ) return ''; $i = $matches[1]; return ( ! in_array( $i, $allowedentitynames ) ) ? "&$i;" : "&$i;"; } /** * Helper function to determine if a Unicode value is valid. * * @since 2.7.0 * * @param int $i Unicode value * @return bool True if the value was a valid Unicode number */ public static function wp_valid_unicode($i) { return ( $i == 0x9 || $i == 0xa || $i == 0xd || ($i >= 0x20 && $i <= 0xd7ff) || ($i >= 0xe000 && $i <= 0xfffd) || ($i >= 0x10000 && $i <= 0x10ffff) ); } /** * Callback for wp_kses_normalize_entities() regular expression. * * This function helps wp_kses_normalize_entities() to only accept 16-bit * values and nothing more for `&#number;` entities. * * @access private * @since 1.0.0 * * @param array $matches preg_replace_callback() matches array * @return string Correctly encoded entity */ public static function wp_kses_normalize_entities2($matches) { if ( empty($matches[1]) ) return ''; $i = $matches[1]; if (self::wp_valid_unicode($i)) { $i = str_pad(ltrim($i,'0'), 3, '0', STR_PAD_LEFT); $i = "&#$i;"; } else { $i = "&#$i;"; } return $i; } /** * Callback for wp_kses_normalize_entities() for regular expression. * * This function helps wp_kses_normalize_entities() to only accept valid Unicode * numeric entities in hex form. * * @since 2.7.0 * @access private * * @param array $matches preg_replace_callback() matches array * @return string Correctly encoded entity */ public static function wp_kses_normalize_entities3($matches) { if ( empty($matches[1]) ) return ''; $hexchars = $matches[1]; return ( ! self::wp_valid_unicode( hexdec( $hexchars ) ) ) ? "&#x$hexchars;" : '&#x'.ltrim($hexchars,'0').';'; } /** * Retrieve a list of protocols to allow in HTML attributes. * * @since 3.3.0 * @since 4.3.0 Added 'webcal' to the protocols array. * @since 4.7.0 Added 'urn' to the protocols array. * * @see wp_kses() * @see esc_url() * * @staticvar array $protocols * * @return array Array of allowed protocols. Defaults to an array containing 'http', 'https', * 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', * 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp', 'webcal', and 'urn'. */ public static function wp_allowed_protocols() { static $protocols = array(); if ( empty( $protocols ) ) { $protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp', 'webcal', 'urn' ); } return $protocols; } /** * Checks and cleans a URL. * * A number of characters are removed from the URL. If the URL is for displaying * (the default behaviour) ampersands are also replaced. The {@see 'clean_url'} filter * is applied to the returned cleaned URL. * * @since 2.8.0 * * @param string $url The URL to be cleaned. * @param array $protocols Optional. An array of acceptable protocols. * Defaults to return value of wp_allowed_protocols() * @param string $_context Private. Use esc_url_raw() for database usage. * @return string The cleaned $url after the {@see 'clean_url'} filter is applied. */ public static function esc_url( $url, $protocols = null, $_context = 'display' ) { $original_url = $url; if ( '' == $url ) return $url; $url = str_replace( ' ', '%20', $url ); $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url); if ( '' === $url ) { return $url; } if ( 0 !== stripos( $url, 'mailto:' ) ) { $strip = array('%0d', '%0a', '%0D', '%0A'); $url = self::_deep_replace($strip, $url); } $url = str_replace(';//', '://', $url); /* If the URL doesn't appear to contain a scheme, we * presume it needs http:// prepended (unless a relative * link starting with /, # or ? or a php file). */ if ( strpos($url, ':') === false && ! in_array( $url[0], array( '/', '#', '?' ) ) && ! preg_match('/^[a-z0-9-]+?\.php/i', $url) ) $url = 'http://' . $url; // Replace ampersands and single quotes only when displaying. if ( 'display' == $_context ) { $url = self::wp_kses_normalize_entities( $url ); $url = str_replace( '&', '&', $url ); $url = str_replace( "'", ''', $url ); } if ( ( false !== strpos( $url, '[' ) ) || ( false !== strpos( $url, ']' ) ) ) { $parsed = wp_parse_url( $url ); $front = ''; if ( isset( $parsed['scheme'] ) ) { $front .= $parsed['scheme'] . '://'; } elseif ( '/' === $url[0] ) { $front .= '//'; } if ( isset( $parsed['user'] ) ) { $front .= $parsed['user']; } if ( isset( $parsed['pass'] ) ) { $front .= ':' . $parsed['pass']; } if ( isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) { $front .= '@'; } if ( isset( $parsed['host'] ) ) { $front .= $parsed['host']; } if ( isset( $parsed['port'] ) ) { $front .= ':' . $parsed['port']; } $end_dirty = str_replace( $front, '', $url ); $end_clean = str_replace( array( '[', ']' ), array( '%5B', '%5D' ), $end_dirty ); $url = str_replace( $end_dirty, $end_clean, $url ); } if ( '/' === $url[0] ) { $good_protocol_url = $url; } else { if ( ! is_array( $protocols ) ) $protocols = self::wp_allowed_protocols(); $good_protocol_url = self::wp_kses_bad_protocol( $url, $protocols ); if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) return ''; } /** * Filters a string cleaned and escaped for output as a URL. * * @since 2.3.0 * * @param string $good_protocol_url The cleaned URL to be returned. * @param string $original_url The URL prior to cleaning. * @param string $_context If 'display', replace ampersands and single quotes only. */ return $good_protocol_url; } /** * Removes any invalid control characters in $string. * * Also removes any instance of the '\0' string. * * @since 1.0.0 * * @param string $string * @param array $options Set 'slash_zero' => 'keep' when '\0' is allowed. Default is 'remove'. * @return string */ public static function wp_kses_no_null( $string, $options = null ) { if ( ! isset( $options['slash_zero'] ) ) { $options = array( 'slash_zero' => 'remove' ); } $string = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F]/', '', $string ); if ( 'remove' == $options['slash_zero'] ) { $string = preg_replace( '/\\\\+0+/', '', $string ); } return $string; } /** * Sanitize string from bad protocols. * * This function removes all non-allowed protocols from the beginning of * $string. It ignores whitespace and the case of the letters, and it does * understand HTML entities. It does its work in a while loop, so it won't be * fooled by a string like "javascript:javascript:alert(57)". * * @since 1.0.0 * * @param string $string Content to filter bad protocols from * @param array $allowed_protocols Allowed protocols to keep * @return string Filtered content */ public static function wp_kses_bad_protocol($string, $allowed_protocols) { $string = self::wp_kses_no_null($string); $iterations = 0; do { $original_string = $string; $string = self::wp_kses_bad_protocol_once($string, $allowed_protocols); } while ( $original_string != $string && ++$iterations < 6 ); if ( $original_string != $string ) return ''; return $string; } /** * Sanitizes content from bad protocols and other characters. * * This function searches for URL protocols at the beginning of $string, while * handling whitespace and HTML entities. * * @since 1.0.0 * * @param string $string Content to check for bad protocols * @param string $allowed_protocols Allowed protocols * @return string Sanitized content */ public static function wp_kses_bad_protocol_once($string, $allowed_protocols, $count = 1 ) { $string2 = preg_split( '/:|�*58;|�*3a;/i', $string, 2 ); if ( isset($string2[1]) && ! preg_match('%/\?%', $string2[0]) ) { $string = trim( $string2[1] ); $protocol = self::wp_kses_bad_protocol_once2( $string2[0], $allowed_protocols ); if ( 'feed:' == $protocol ) { if ( $count > 2 ) return ''; $string = wp_kses_bad_protocol_once( $string, $allowed_protocols, ++$count ); if ( empty( $string ) ) return $string; } $string = $protocol . $string; } return $string; } /** * Convert all entities to their character counterparts. * * This function decodes numeric HTML entities (`A` and `A`). * It doesn't do anything with other entities like ä, but we don't * need them in the URL protocol whitelisting system anyway. * * @since 1.0.0 * * @param string $string Content to change entities * @return string Content after decoded entities */ public static function wp_kses_decode_entities($string) { $string = preg_replace_callback('/&#([0-9]+);/', 'self::_wp_kses_decode_entities_chr', $string); $string = preg_replace_callback('/&#[Xx]([0-9A-Fa-f]+);/', 'self::_wp_kses_decode_entities_chr_hexdec', $string); return $string; } /** * Regex callback for wp_kses_decode_entities() * * @since 2.9.0 * * @param array $match preg match * @return string */ public static function _wp_kses_decode_entities_chr( $match ) { return chr( $match[1] ); } /** * Regex callback for wp_kses_decode_entities() * * @since 2.9.0 * * @param array $match preg match * @return string */ public static function _wp_kses_decode_entities_chr_hexdec( $match ) { return chr( hexdec( $match[1] ) ); } /** * Callback for wp_kses_bad_protocol_once() regular expression. * * This function processes URL protocols, checks to see if they're in the * whitelist or not, and returns different data depending on the answer. * * @access private * @since 1.0.0 * * @param string $string URI scheme to check against the whitelist * @param string $allowed_protocols Allowed protocols * @return string Sanitized content */ public static function wp_kses_bad_protocol_once2( $string, $allowed_protocols ) { $string2 = self::wp_kses_decode_entities($string); $string2 = preg_replace('/\s/', '', $string2); $string2 = self::wp_kses_no_null($string2); $string2 = strtolower($string2); $allowed = false; foreach ( (array) $allowed_protocols as $one_protocol ) if ( strtolower($one_protocol) == $string2 ) { $allowed = true; break; } if ($allowed) return "$string2:"; else return ''; } /** * Performs esc_url() for database usage. * * @since 2.8.0 * * @param string $url The URL to be cleaned. * @param array $protocols An array of acceptable protocols. * @return string The cleaned URL. */ public static function esc_url_raw( $url, $protocols = null ) { return self::esc_url( $url, $protocols, 'db' ); } // SANITIZE Functions /** * Normalize EOL characters and strip duplicate whitespace. * * @since 2.7.0 * * @param string $str The string to normalize. * @return string The normalized string. */ public static function normalize_whitespace( $str ) { $str = trim( $str ); $str = str_replace( "\r", "\n", $str ); $str = preg_replace( array( '/\n+/', '/[ \t]+/' ), array( "\n", ' ' ), $str ); return $str; } /** * Properly strip all HTML tags including script and style * * This differs from strip_tags() because it removes the contents of * the `' )` * will return 'something'. wp_strip_all_tags will return '' * * @since 2.9.0 * * @param string $string String containing HTML tags * @param bool $remove_breaks Optional. Whether to remove left over line breaks and white space chars * @return string The processed string. */ public static function wp_strip_all_tags($string, $remove_breaks = false) { $string = preg_replace( '@<(script|style)[^>]*?>.*?@si', '', $string ); $string = strip_tags($string); if ( $remove_breaks ) $string = preg_replace('/[\r\n\t ]+/', ' ', $string); return trim( $string ); } /** * Sanitizes a string from user input or from the database. * * - Checks for invalid UTF-8, * - Converts single `<` characters to entities * - Strips all tags * - Removes line breaks, tabs, and extra whitespace * - Strips octets * * @since 2.9.0 * * @see sanitize_textarea_field() * @see wp_check_invalid_utf8() * @see wp_strip_all_tags() * * @param string $str String to sanitize. * @return string Sanitized string. */ public static function sanitize_text_field( $str ) { $filtered = self::_sanitize_text_fields( $str, false ); /** * Filters a sanitized text field string. * * @since 2.9.0 * * @param string $filtered The sanitized string. * @param string $str The string prior to being sanitized. */ return $filtered; } /** * Sanitizes a multiline string from user input or from the database. * * The function is like sanitize_text_field(), but preserves * new lines (\n) and other whitespace, which are legitimate * input in textarea elements. * * @see sanitize_text_field() * * @since 4.7.0 * * @param string $str String to sanitize. * @return string Sanitized string. */ public static function sanitize_textarea_field( $str ) { $filtered = self::_sanitize_text_fields( $str, true ); /** * Filters a sanitized textarea field string. * * @since 4.7.0 * * @param string $filtered The sanitized string. * @param string $str The string prior to being sanitized. */ return $filtered; } /** * Internal helper function to sanitize a string from user input or from the db * * @since 4.7.0 * @access private * * @param string $str String to sanitize. * @param bool $keep_newlines optional Whether to keep newlines. Default: false. * @return string Sanitized string. */ public static function _sanitize_text_fields( $str, $keep_newlines = false ) { $filtered = self::wp_check_invalid_utf8( $str ); if ( strpos($filtered, '<') !== false ) { $filtered = self::wp_pre_kses_less_than( $filtered ); // This will strip extra whitespace for us. $filtered = self::wp_strip_all_tags( $filtered, false ); // Use html entities in a special case to make sure no later // newline stripping stage could lead to a functional tag $filtered = str_replace("<\n", "<\n", $filtered); } if ( ! $keep_newlines ) { $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered ); } $filtered = trim( $filtered ); $found = false; while ( preg_match('/%[a-f0-9]{2}/i', $filtered, $match) ) { $filtered = str_replace($match[0], '', $filtered); $found = true; } if ( $found ) { // Strip out the whitespace that may now exist after removing the octets. $filtered = trim( preg_replace('/ +/', ' ', $filtered) ); } return $filtered; } /** * Convert lone less than signs. * * KSES already converts lone greater than signs. * * @since 2.3.0 * * @param string $text Text to be converted. * @return string Converted text. */ public static function wp_pre_kses_less_than( $text ) { return preg_replace_callback('%<[^>]*?((?=<)|>|$)%', array('self', 'wp_pre_kses_less_than_callback'), $text); } /** * Callback function used by preg_replace. * * @since 2.3.0 * * @param array $matches Populated by matches to preg_replace. * @return string The text returned after esc_html if needed. */ public static function wp_pre_kses_less_than_callback( $matches ) { if ( false === strpos($matches[0], '>') ) return esc_html($matches[0]); return $matches[0]; } } ?> * Last modified: 19 06 2014 * Copyright (C): 2014 IT-radionica.com, All Rights Reserved * * GNU General Public License (Version 2, June 1991) * * This program is free software; you can redistribute * it and/or modify it under the terms of the GNU * General Public License as published by the Free * Software Foundation; either version 2 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License * for more details. * ******************************************************************/ class DUPX_CSRF { /** Session var name * @var string */ public static $session = '_DUPX_CSRF'; /** Generate DUPX_CSRF value for form * @param string $form - Form name as session key * @return string - token */ static function generate($form = NULL) { $token = DUPX_CSRF::token() . DUPX_CSRF::fingerprint(); $_SESSION[DUPX_CSRF::$session . '_' . $form] = $token; return $token; } /** Check DUPX_CSRF value of form * @param string $token - Token * @param string $form - Form name as session key * @return boolean */ public static function check($token, $form = NULL) { if (isset($_SESSION[DUPX_CSRF::$session . '_' . $form]) && $_SESSION[DUPX_CSRF::$session . '_' . $form] == $token) { // token OK return (substr($token, -32) == DUPX_CSRF::fingerprint()); // fingerprint OK? } return FALSE; } /** Generate token * @param void * @return string */ protected static function token() { mt_srand((double) microtime() * 10000); $charid = strtoupper(md5(uniqid(rand(), TRUE))); return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12); } /** Returns "digital fingerprint" of user * @param void * @return string - MD5 hashed data */ protected static function fingerprint() { return strtoupper(md5(implode('|', array($_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT'])))); } } ?> &1') == NULL) { $filepath = 'unzip'; } else { $try_paths = array( '/usr/bin/unzip', '/opt/local/bin/unzip'); foreach ($try_paths as $path) { if (file_exists($path)) { $filepath = $path; break; } } } } return $filepath; } /** * A safe method used to copy larger files * * @param string $source The path to the file being copied * @param string $destination The path to the file being made * * @return bool True if the file was copied */ public static function copyFile($source, $destination) { try { $sp = fopen($source, 'r'); $op = fopen($destination, 'w'); while (!feof($sp)) { $buffer = fread($sp, 512); // use a buffer of 512 bytes fwrite($op, $buffer); } // close handles fclose($op); fclose($sp); return true; } catch (Exception $ex) { return false; } } /** * Returns an array of zip files found in the current executing directory * * @return array of zip files */ public static function getZipFiles() { $files = array(); foreach (glob("*.zip") as $name) { if (file_exists($name)) { $files[] = $name; } } if (count($files) > 0) { return $files; } //FALL BACK: Windows XP has bug with glob, //add secondary check for PHP lameness if ($dh = opendir('.')) { while (false !== ($name = readdir($dh))) { $ext = substr($name, strrpos($name, '.') + 1); if (in_array($ext, array("zip"))) { $files[] = $name; } } closedir($dh); } return $files; } } //INIT Class Properties DUPX_Server::init(); ?> query($query)) { while ($row = $result->fetch_assoc()) { $collations[] = $row["Collation"]; } } $result->free(); return $collations; } /** * Determine if a MySQL database supports a particular feature * * @param conn $dbh Database connection handle * @param string $feature the feature to check for * * @return bool */ public static function hasAbility($dbh, $feature) { $version = self::getVersion($dbh); switch (strtolower($feature)) { case 'collation' : case 'group_concat' : case 'subqueries' : return version_compare($version, '4.1', '>='); case 'set_charset' : return version_compare($version, '5.0.7', '>='); }; return false; } /** * Sets the MySQL connection's character set. * * @param resource $dbh The resource given by mysqli_connect * @param string $charset The character set (optional) * @param string $collate The collation (optional) * * @return bool True on success */ public static function setCharset($dbh, $charset = null, $collate = null) { $charset = (!isset($charset) ) ? $GLOBALS['DBCHARSET_DEFAULT'] : $charset; $collate = (!isset($collate) ) ? $GLOBALS['DBCOLLATE_DEFAULT'] : $collate; if (self::hasAbility($dbh, 'collation') && !empty($charset)) { if (function_exists('mysqli_set_charset') && self::hasAbility($dbh, 'set_charset')) { return mysqli_set_charset($dbh, $charset); } else { $sql = " SET NAMES ".mysqli_real_escape_string($dbh, $charset); if (!empty($collate)) $sql .= " COLLATE ".mysqli_real_escape_string($dbh, $collate); return mysqli_query($dbh, $sql); } } } } ?>
  • Empty this root directory except for the package and installer and try again.
  • Delete just the wp-config.php file and try again. This will over-write all other files in the directory.
  • Check the "Manual package extraction" checkbox under advanced options to skip extraction
  • '); define('ERR_ZIPNOTFOUND', 'The packaged zip file was not found. Be sure the zip package is in the same directory as the installer file and as the correct permissions. If you are trying to reinstall a package you can copy the package from the "' . DUPLICATOR_SSDIR_NAME . '" directory back up to your root which is the same location as your installer.php file.'); define('ERR_ZIPOPEN', 'Failed to open zip archive file. Please be sure the archive is completely downloaded before running the installer. Try to extract the archive manually to make sure the file is not corrupted.'); define('ERR_ZIPEXTRACTION', 'Errors extracting zip file. Portions or part of the zip archive did not extract correctly. Try to extract the archive manually with a client side program like unzip/win-zip/winrar or your hosts cPanel to make sure the file is not corrupted. If the file extracts correctly then there is an invalid file or directory that PHP is unable to extract. This can happen if your moving from one operating system to another where certain naming conventions work on one environment and not another.

    Workarounds:
    1. Create a new package and be sure to exclude any directories that have invalid names or files in them. This warning will be displayed on the scan results under "Name Checks".
    2. Manually extract the zip file with a client side program or your hosts cPanel. Then under options in step 1 of this installer check the "Manual Archive Extraction" option and perform the install.'); define('ERR_ZIPMANUAL', "When choosing manual package extraction, the contents of the package must already be extracted and the wp-config.php and dup-database__{$GLOBALS['PACKAGE_HASH']}.sql files must be present in the same directory as the installer.php for the process to continue. Please manually extract the package into the current directory before continuing in manual extraction mode. Also validate that the wp-config.php and dup-database__[HASH].sql files are present."); define('ERR_MAKELOG', 'PHP is having issues writing to the log file ' . DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']) . '\".$GLOBALS["LOG_FILE_NAME"]." . In order for the Duplicator to proceed validate your owner/group and permission settings for PHP on this path. Try temporarily setting you permissions to 777 to see if the issue gets resolved. If you are on a shared hosting environment please contact your hosting company and tell them you are getting errors writing files to the path above when using PHP.'); define('ERR_ZIPARCHIVE', 'In order to extract the archive.zip file the PHP ZipArchive module must be installed. Please read the FAQ for more details. You can still install this package but you will need to check the Manual package extraction checkbox found in the Advanced Options. Please read the online user guide for details in performing a manual package extraction.'); define('ERR_MYSQLI_SUPPORT', 'In order to complete an install the mysqli extension for PHP is required. If you are on a hosted server please contact your host and request that mysqli be enabled. For more information visit: http://php.net/manual/en/mysqli.installation.php'); define('ERR_DBCONNECT', 'DATABASE CONNECTION FAILED!
    '); define('ERR_DBCONNECT_INFO', 'DATABASE CONNECTION FAILED!
    If the problem persists see the online FAQ for recommended fixes.'); define('ERR_DBCONNECT_CREATE', 'DATABASE CREATION FAILURE!
    Unable to create database "%s". Check to make sure the user has "Create" privileges. Some hosts will restrict creation of a database only through the cpanel. Try creating the database manually to proceed with installation. If the database already exists then check the radio button labeled "Connect and Remove All Data" which will remove all existing tables.'); define('ERR_DBTRYCLEAN', 'DATABASE CREATION FAILURE!
    Unable to remove all tables from database "%s".
    Please remove all tables from this database and try the installation again.'); define('ERR_DBCREATE', 'The database "%s" does not exists.
    Change mode to create in order to create a new database.'); define('ERR_DBEMPTY', 'The database "%s" has "%s" tables. The Duplicator only works with an EMPTY database. Enable the action "Connect and Remove All Data" radio button to remove all tables and or create a new database. Some hosting providers do not allow table removal from scripts. In this case you will need to login to your hosting providers control panel and remove the tables manually. Please contact your hosting provider for further details. Always backup all your data before proceeding!'); define('ERR_TESTDB_UTF8', 'UTF8 Characters were detected as part of the database connection string. If your connection fails be sure to update the MySQL my.ini configuration file setting to support UTF8 characters by enabling this option [character_set_server=utf8] and restarting the database server.'); define('ERR_TESTDB_VERSION_INFO', 'If the current version detected is below 5.5.3 (release on April 8th 2010) then support for utf8mb4 tables will not work. The utf8mb4 format is only supported in MySQL server 5.5.3+. It is highly recommended to upgrade your version of MySQL server on this server to be more compatible with recent releases of WordPress and avoid issues with install errors.'); define('ERR_TESTDB_VERSION_COMPAT', 'In order to avoid database incompatibility issues make sure the database versions between the build and installer servers are as close as possible. If the package was created on a newer database version than where it is being installed then you might run into issues.

    It is best to make sure the server where the installer is running has the same or higher version number than where it was built. If the major and minor version are the same or close for example [5.7 to 5.6], then the migration should work without issues. A version pair of [5.7 to 5.1] is more likely to cause issues unless you have a very simple setup. If the versions are too far apart work with your hosting provider to upgrade the MySQL engine on this server.

    MariaDB: If a version of 10.N.N shows then the database distribution is a MariaDB flavor of MySQL. While the distributions are very close there are some subtle differences. Some operating systems will report the version such as "5.5.5-10.1.21-MariaDB" showing the correlation of both. Please visit the online MariaDB versus MySQL - Compatibility page for more details.

    Please note these messages are simply notices. It is highly recommended that you continue with the install process and closely monitor the file along with the install report found on step 3 of the installer. Be sure to look for any notices/warnings/errors in these locations to validate the install process did not detect any errors. If any issues are found please visit the FAQ pages and see the question What if I get database errors or general warnings on the install report?.'); /** * Class used to log information to the installer-log.txt file * * Standard: PSR-2 * @link http://www.php-fig.org/psr/psr-2 Full Documentation * * @package SC\DUPX\Log * */ class DUPX_Log { /** * Used to write debug info to the text log file * * @param string $msg Any text data * @param int $loglevel Log level * * @return string Write info to both the log and browser */ public static function info($msg, $logging = 1) { if ($logging <= $GLOBALS["LOGGING"]) { @fwrite($GLOBALS["LOG_FILE_HANDLE"], "{$msg}\n"); } } /** * Used to write errors to the text log file * * @param string $msg Any text data * @param int $loglevel Log level * * @return string Write errors to both the log and browser */ public static function error($msg) { $breaks = array("
    ","
    ","
    "); $log_msg = str_ireplace($breaks, "\r\n", $msg); $log_msg = strip_tags($log_msg); @fwrite($GLOBALS["LOG_FILE_HANDLE"], "\nINSTALLER ERROR:\n{$log_msg}\n"); @fclose($GLOBALS["LOG_FILE_HANDLE"]); die("

    INSTALL ERROR!
    {$msg}
    "); } } ?> 0) { while ($row = mysqli_fetch_assoc($result)) { $fields[] = $row['Field']; } } //Return Primary which is needed for index lookup //$result = mysqli_query($dbh, "SHOW INDEX FROM `{$table}` WHERE KEY_NAME LIKE '%PRIMARY%'"); 1.1.15 updated $result = mysqli_query($dbh, "SHOW INDEX FROM `".mysqli_real_escape_string($dbh, $table)."`"); if (mysqli_num_rows($result) > 0) { while ($row = mysqli_fetch_assoc($result)) { $fields[] = $row['Column_name']; } } return (count($fields) > 0) ? $fields : null; } /** * Begins the processing for replace logic * * @param mysql $dbh The db connection object * @param array $list Key value pair of 'search' and 'replace' arrays * @param array $tables The tables we want to look at * @param array $fullsearch Search every column regardless of its data type * * @return array Collection of information gathered during the run. */ public static function load($dbh, $list = array(), $tables = array(), $fullsearch = false) { $report = array( 'scan_tables' => 0, 'scan_rows' => 0, 'scan_cells' => 0, 'updt_tables' => 0, 'updt_rows' => 0, 'updt_cells' => 0, 'errsql' => array(), 'errser' => array(), 'errkey' => array(), 'errsql_sum' => 0, 'errser_sum' => 0, 'errkey_sum' => 0, 'time' => '', 'err_all' => 0 ); function set_sql_column_safe(&$str) { $str = "`$str`"; } $profile_start = DUPX_U::getMicrotime(); if (is_array($tables) && !empty($tables)) { foreach ($tables as $table) { $report['scan_tables'] ++; $columns = array(); // Get a list of columns in this table $fields = mysqli_query($dbh, 'DESCRIBE '.mysqli_real_escape_string($dbh, $table)); while ($column = mysqli_fetch_array($fields)) { $columns[$column['Field']] = $column['Key'] == 'PRI' ? true : false; } // Count the number of rows we have in the table if large we'll split into blocks $row_count = mysqli_query($dbh, "SELECT COUNT(*) FROM `".mysqli_real_escape_string($dbh, $table)."`"); $rows_result = mysqli_fetch_array($row_count); @mysqli_free_result($row_count); $row_count = $rows_result[0]; if ($row_count == 0) { DUPX_Log::info("{$table}^ ({$row_count})"); continue; } $page_size = 25000; $offset = ($page_size + 1); $pages = ceil($row_count / $page_size); // Grab the columns of the table. Only grab text based columns because // they are the only data types that should allow any type of search/replace logic $colList = '*'; $colMsg = '*'; if (!$fullsearch) { $colList = self::getTextColumns($dbh, $table); if ($colList != null && is_array($colList)) { array_walk($colList, set_sql_column_safe); $colList = implode(',', $colList); } $colMsg = (empty($colList)) ? '*' : '~'; } if (empty($colList)) { DUPX_Log::info("{$table}^ ({$row_count})"); continue; } else { DUPX_Log::info("{$table}{$colMsg} ({$row_count})"); } //Paged Records for ($page = 0; $page < $pages; $page++) { $current_row = 0; $start = $page * $page_size; $end = $start + $page_size; $sql = sprintf("SELECT {$colList} FROM `%s` LIMIT %d, %d", mysqli_real_escape_string($dbh, $table), $start, $offset); $data = mysqli_query($dbh, $sql); if (!$data) $report['errsql'][] = mysqli_error($dbh); $scan_count = ($row_count < $end) ? $row_count : $end; DUPX_Log::info("\tScan => {$start} of {$scan_count}", 2); //Loops every row while ($row = mysqli_fetch_array($data)) { $report['scan_rows'] ++; $current_row++; $upd_col = array(); $upd_sql = array(); $where_sql = array(); $upd = false; $serial_err = 0; $is_unkeyed = !in_array(true,$columns); //Loops every cell foreach ($columns as $column => $primary_key) { $report['scan_cells'] ++; $edited_data = $data_to_fix = $row[$column]; $base64converted = false; $txt_found = false; //Unkeyed table code //Added this here to add all columns to $where_sql //The if statement with $txt_found would skip additional columns if($is_unkeyed && ! empty($data_to_fix)) { $where_sql[] = $column.' = "'.mysqli_real_escape_string($dbh, $data_to_fix).'"'; } //Only replacing string values if (!empty($row[$column]) && !is_numeric($row[$column]) && $primary_key != 1) { //Base 64 detection if (base64_decode($row[$column], true)) { $decoded = base64_decode($row[$column], true); if (self::isSerialized($decoded)) { $edited_data = $decoded; $base64converted = true; } } //Skip table cell if match not found foreach ($list as $item) { if (strpos($edited_data, $item['search']) !== false) { $txt_found = true; break; } } if (!$txt_found) { continue; } //Replace logic - level 1: simple check on any string or serialized strings foreach ($list as $item) { $edited_data = self::recursiveUnserializeReplace($item['search'], $item['replace'], $edited_data); } //Replace logic - level 2: repair serialized strings that have become broken $serial_check = self::fixSerialString($edited_data); if ($serial_check['fixed']) { $edited_data = $serial_check['data']; } elseif ($serial_check['tried'] && !$serial_check['fixed']) { $serial_err++; } } //Change was made if ($edited_data != $data_to_fix || $serial_err > 0) { $report['updt_cells'] ++; //Base 64 encode if ($base64converted) { $edited_data = base64_encode($edited_data); } $upd_col[] = $column; $upd_sql[] = $column.' = "'.mysqli_real_escape_string($dbh, $edited_data).'"'; $upd = true; } if ($primary_key) { $where_sql[] = $column.' = "'.mysqli_real_escape_string($dbh, $data_to_fix).'"'; } } //PERFORM ROW UPDATE if ($upd && !empty($where_sql)) { $sql = "UPDATE `".mysqli_real_escape_string($dbh, $table)."` SET ".implode(', ', $upd_sql).' WHERE '.implode(' AND ', array_filter($where_sql)); $result = mysqli_query($dbh, $sql); if ($result) { if ($serial_err > 0) { $report['errser'][] = "SELECT " . implode(', ', $upd_col) . " FROM `{$table}` WHERE " . implode(' AND ', array_filter($where_sql)) . ';'; } $report['updt_rows']++; } else { $report['errsql'][] = ($GLOBALS["LOGGING"] == 1) ? 'DB ERROR: ' . mysqli_error($dbh) : 'DB ERROR: ' . mysqli_error($dbh) . "\nSQL: [{$sql}]\n"; } //DEBUG ONLY: DUPX_Log::info("\t{$sql}\n", 3); } elseif ($upd) { $report['errkey'][] = sprintf("Row [%s] on Table [%s] requires a manual update.", $current_row, $table); } } //DUPX_U::fcgiFlush(); @mysqli_free_result($data); } if ($upd) { $report['updt_tables'] ++; } } } $profile_end = DUPX_U::getMicrotime(); $report['time'] = DUPX_U::elapsedTime($profile_end, $profile_start); $report['errsql_sum'] = empty($report['errsql']) ? 0 : count($report['errsql']); $report['errser_sum'] = empty($report['errser']) ? 0 : count($report['errser']); $report['errkey_sum'] = empty($report['errkey']) ? 0 : count($report['errkey']); $report['err_all'] = $report['errsql_sum'] + $report['errser_sum'] + $report['errkey_sum']; return $report; } /** * Take a serialized array and unserialized it replacing elements and * unserializing any subordinate arrays and performing the replace. * * @param string $from String we're looking to replace. * @param string $to What we want it to be replaced with * @param array $data Used to pass any subordinate arrays back to in. * @param bool $serialised Does the array passed via $data need serializing. * * @return array The original array with all elements replaced as needed. */ public static function recursiveUnserializeReplace($from = '', $to = '', $data = '', $serialised = false) { // some unseriliased data cannot be re-serialised eg. SimpleXMLElements try { if (is_string($data) && ($unserialized = @unserialize($data)) !== false) { $data = self::recursiveUnserializeReplace($from, $to, $unserialized, true); } elseif (is_array($data)) { $_tmp = array(); foreach ($data as $key => $value) { $_tmp[$key] = self::recursiveUnserializeReplace($from, $to, $value, false); } $data = $_tmp; unset($_tmp); /* CJL Check for an update to the key of an array e.g. [http://localhost/projects/wpplugins/] => 1.41 This could have unintended consequences would need to enable with full-search needs more testing if (array_key_exists($from, $data)) { $data[$to] = $data[$from]; unset($data[$from]); } */ } elseif (is_object($data)) { /* RSR Old logic that didn't work with Beaver Builder - they didn't want to create a brand new object instead reused the existing one... $dataClass = get_class($data); $_tmp = new $dataClass(); foreach ($data as $key => $value) { $_tmp->$key = self::recursiveUnserializeReplace($from, $to, $value, false); } $data = $_tmp; unset($_tmp); */ // RSR NEW LOGIC $_tmp = $data; $props = get_object_vars($data); foreach ($props as $key => $value) { $_tmp->$key = self::recursiveUnserializeReplace($from, $to, $value, false); } $data = $_tmp; unset($_tmp); } else { if (is_string($data)) { $data = str_replace($from, $to, $data); } } if ($serialised) return serialize($data); } catch (Exception $error) { DUPX_Log::info("\nRECURSIVE UNSERIALIZE ERROR: With string\n".$error, 2); } return $data; } /** * Test if a string in properly serialized * * @param string $data Any string type * * @return bool Is the string a serialized string */ public static function isSerialized($data) { $test = @unserialize(($data)); return ($test !== false || $test === 'b:0;') ? true : false; } /** * Fixes the string length of a string object that has been serialized but the length is broken * * @param string $data The string ojbect to recalculate the size on. * * @return string A serialized string that fixes and string length types */ public static function fixSerialString($data) { $result = array('data' => $data, 'fixed' => false, 'tried' => false); if (preg_match("/s:[0-9]+:/", $data)) { if (!self::isSerialized($data)) { $regex = '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|d:|i:|o:|N;))!s'; $serial_string = preg_match('/^s:[0-9]+:"(.*$)/s', trim($data), $matches); //Nested serial string if ($serial_string) { $inner = preg_replace_callback($regex, 'DUPX_UpdateEngine::fixStringCallback', rtrim($matches[1], '";')); $serialized_fixed = 's:'.strlen($inner).':"'.$inner.'";'; } else { $serialized_fixed = preg_replace_callback($regex, 'DUPX_UpdateEngine::fixStringCallback', $data); } if (self::isSerialized($serialized_fixed)) { $result['data'] = $serialized_fixed; $result['fixed'] = true; } $result['tried'] = true; } } return $result; } /** * The call back method call from via fixSerialString */ private static function fixStringCallback($matches) { return 's:'.strlen(($matches[2])); } } ?> $val) { $replace[$key] = self::customEscape($val); } $wpconfig = preg_replace($patterns, $replace, $wpconfig); file_put_contents('wp-config.php', $wpconfig); $wpconfig = null; } /** * Updates the web server config files in Step 3 * * @return null */ public static function updateExtended() { $config_file = ''; if (!file_exists('wp-config.php')) { return $config_file; } $root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']); $wpconfig_path = "{$root_path}/wp-config.php"; $config_file = @file_get_contents($wpconfig_path, true); $patterns = array( "/('|\")WP_HOME.*?\)\s*;/", "/('|\")WP_SITEURL.*?\)\s*;/"); $post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']); $replace = array( "'WP_HOME', '".$post_url_new."');", "'WP_SITEURL', '".$post_url_new."');"); //Not sure how well tokenParser works on all servers so only using for not critical constants at this point. //$count checks for dynamic variable types such as: define('WP_TEMP_DIR', 'D:/' . $var . 'somepath/'); //which should not be updated. $defines = self::tokenParser($wpconfig_path); //WP_CONTENT_DIR if (isset($defines['WP_CONTENT_DIR'])) { $post_path_old = DUPX_U::sanitize_text_field($_POST['path_old']); $post_path_new = DUPX_U::sanitize_text_field($_POST['path_new']); $val = str_replace($post_path_old, $post_path_new, DUPX_U::setSafePath($defines['WP_CONTENT_DIR']), $count); if ($count > 0) { array_push($patterns, "/('|\")WP_CONTENT_DIR.*?\)\s*;/"); array_push($replace, "'WP_CONTENT_DIR', '{$val}');"); } } //WP_CONTENT_URL if (isset($defines['WP_CONTENT_URL'])) { $post_url_old = DUPX_U::sanitize_text_field($_POST['url_old']); $post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']); $val = str_replace($post_url_old . '/', $post_url_new . '/', $defines['WP_CONTENT_URL'], $count); if ($count > 0) { array_push($patterns, "/('|\")WP_CONTENT_URL.*?\)\s*;/"); array_push($replace, "'WP_CONTENT_URL', '{$val}');"); } } //WP_TEMP_DIR if (isset($defines['WP_TEMP_DIR'])) { $post_path_old = DUPX_U::sanitize_text_field($_POST['path_old']); $post_path_new = DUPX_U::sanitize_text_field($_POST['path_new']); $val = str_replace($post_path_old, $post_path_new, DUPX_U::setSafePath($defines['WP_TEMP_DIR']) , $count); if ($count > 0) { array_push($patterns, "/('|\")WP_TEMP_DIR.*?\)\s*;/"); array_push($replace, "'WP_TEMP_DIR', '{$val}');"); } } //DOMAIN_CURRENT_SITE if (isset($defines['DOMAIN_CURRENT_SITE'])) { $post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']); $mu_newDomainHost = parse_url($post_url_new, PHP_URL_HOST); array_push($patterns, "/('|\")DOMAIN_CURRENT_SITE.*?\)\s*;/"); array_push($replace, "'DOMAIN_CURRENT_SITE', '{$mu_newDomainHost}');"); } //PATH_CURRENT_SITE if (isset($defines['PATH_CURRENT_SITE'])) { $post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']); $mu_newUrlPath = parse_url($post_url_new, PHP_URL_PATH); array_push($patterns, "/('|\")PATH_CURRENT_SITE.*?\)\s*;/"); array_push($replace, "'PATH_CURRENT_SITE', '{$mu_newUrlPath}');"); } $config_file = preg_replace($patterns, $replace, $config_file); file_put_contents($wpconfig_path, $config_file); $config_file = file_get_contents($wpconfig_path, true); return $config_file; } /** * Used to parse the wp-config.php file * * @return null */ public static function tokenParser($wpconfig_path) { $defines = array(); $wpconfig_file = @file_get_contents($wpconfig_path); if (!function_exists('token_get_all')) { DUPX_Log::info("\nNOTICE: PHP function 'token_get_all' does not exist so skipping WP_CONTENT_DIR and WP_CONTENT_URL processing."); return $defines; } if ($wpconfig_file === false) { return $defines; } $defines = array(); $tokens = token_get_all($wpconfig_file); $token = reset($tokens); while ($token) { if (is_array($token)) { if ($token[0] == T_WHITESPACE || $token[0] == T_COMMENT || $token[0] == T_DOC_COMMENT) { // do nothing } else if ($token[0] == T_STRING && strtolower($token[1]) == 'define') { $state = 1; } else if ($state == 2 && self::isConstant($token[0])) { $key = $token[1]; $state = 3; } else if ($state == 4 && self::isConstant($token[0])) { $value = $token[1]; $state = 5; } } else { $symbol = trim($token); if ($symbol == '(' && $state == 1) { $state = 2; } else if ($symbol == ',' && $state == 3) { $state = 4; } else if ($symbol == ')' && $state == 5) { $defines[self::tokenStrip($key)] = self::tokenStrip($value); $state = 0; } } $token = next($tokens); } return $defines; } private static function tokenStrip($value) { return preg_replace('!^([\'"])(.*)\1$!', '$2', $value); } private static function customEscape($str) { return str_replace('\\', '\\\\', $str); } private static function isConstant($token) { return $token == T_CONSTANT_ENCAPSED_STRING || $token == T_STRING || $token == T_LNUMBER || $token == T_DNUMBER; } } ?> ' . "\n"; $xml_contents .= "\n"; $xml_contents .= "\n"; @file_put_contents('web.config', $xml_contents); //.user.ini - For WordFence @copy('.user.ini', ".user.ini.{$timeStamp}.orig"); @unlink('.user.ini'); DUPX_Log::info("- Backup of .htaccess/web.config made to *.{$timeStamp}.orig"); DUPX_Log::info("- Reset of .htaccess/web.config files"); @chmod('.htaccess', 0644); } /** * Resets the .htaccess file to a very slimed down version with new paths * * @return null */ public static function setup($dbh) { if (!isset($_POST['url_new'])) { return; } DUPX_Log::info("\nWEB SERVER CONFIGURATION FILE BASIC SETUP:"); $post_url_old = DUPX_U::sanitize_text_field($_POST['url_old']); $currdata = parse_url($_POST['url_old']); $post_url_new = DUPX_U::sanitize_text_field($_POST['url_new']); $newdata = parse_url($post_url_new); $currpath = DUPX_U::addSlash(isset($currdata['path']) ? $currdata['path'] : ""); $newpath = DUPX_U::addSlash(isset($newdata['path']) ? $newdata['path'] : ""); $timestamp = date("Y-m-d H:i:s"); $update_msg = "# This file was updated by Duplicator on {$timestamp}. See .htaccess.orig for the original .htaccess file.\n"; $update_msg .= "# Please note that other plugins and resources write to this file. If the time-stamp above is different\n"; $update_msg .= "# than the current time-stamp on the file system then another resource has updated this file.\n"; $update_msg .= "# Duplicator only writes to this file once during the install process while running the installer.php file.\n"; $empty_htaccess = false; $query_result = @mysqli_query($dbh, "SELECT option_value FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE option_name = 'permalink_structure' "); //If the permalink is set to Plain then don't update the rewrite rules if ($query_result) { $row = @mysqli_fetch_array($query_result); if ($row != null) { $permalink_structure = trim($row[0]); $empty_htaccess = empty($permalink_structure); } } if ($empty_htaccess) { $tmp_htaccess = "{$update_msg}"; DUPX_Log::info("- No permalink structures set creating blank .htaccess file."); } else { $tmp_htaccess = << RewriteEngine On RewriteBase {$newpath} RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . {$newpath}index.php [L] # END WordPress HTACCESS; DUPX_Log::info("- Preparing .htaccess file with basic setup."); } file_put_contents('.htaccess', $tmp_htaccess); @chmod('.htaccess', 0644); DUPX_Log::info("Basic .htaccess file edit complete. If using IIS web.config this process will need to be done manually."); } } ?> 'value1', 'key2' => 'value2') * generated hidden form elements * @return string An html form that will automatically post itself */ public static function post_with_html($url, $data) { $id = uniqid(); $html = "
    \n"; foreach ($data as $name => $value) { $html .= "\n"; } $html .= "
    \n"; $html .= ""; echo $html; } /** * Do an http post request with curl or php code * @param string $url A URL to post to * @param string $params A valid key/pair combo $data = array('key1' => 'value1', 'key2' => 'value2'); * @param string $headers Optional header elements * @return a string or FALSE on failure. */ public static function post($url, $params = array(), $headers = null) { //PHP POST if (!function_exists('curl_init')) { return self::php_get_post($url, $params, $headers = null, 'POST'); } //CURL POST $headers_on = isset($headers) && array_count_values($headers); $params = http_build_query($params); $ch = curl_init(); // Return contents of transfer on curl_exec // Allow self-signed certs curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, $headers_on); if ($headers_on) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } curl_setopt($ch, CURLOPT_POST, count($params)); curl_setopt($ch, CURLOPT_POSTFIELDS, $params); $response = curl_exec($ch); curl_close($ch); return $response; } /** * Do an http post request with curl or php code * @param string $url A URL to get. If $params is not null then all query strings will be removed. * @param string $params A valid key/pair combo $data = array('key1' => 'value1', 'key2' => 'value2'); * @param string $headers Optional header elements * @return a string or FALSE on failure. */ public static function get($url, $params = array(), $headers = null) { //PHP GET if (!function_exists('curl_init')) { return self::php_get_post($url, $params, $headers = null, 'GET'); } //Remove query string if $params are passed $full_url = $url; if (count($params)) { $url = preg_replace('/\?.*/', '', $url); $full_url = $url . '?' . http_build_query($params); } $headers_on = isset($headers) && array_count_values($headers); $ch = curl_init(); // Return contents of transfer on curl_exec // Allow self-signed certs curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_URL, $full_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, $headers_on); if ($headers_on) { curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } $response = curl_exec($ch); curl_close($ch); return $response; } /** * Gets the URL of the current request * @param bool $show_query Include the query string in the URL * @return string A URL */ public static function get_request_uri($show_query = true) { $isSecure = false; if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['SERVER_PORT'] == 443)) { $isSecure = true; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') { $isSecure = true; } $protocol = $isSecure ? 'https' : 'http'; $url = "{$protocol}://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; $url = ($show_query) ? $url : preg_replace('/\?.*/', '', $url); return $url; } /** * Check to see if the internet is accessible * @param string $url A URL e.g without prefix "ajax.googleapis.com" * @param string $port A valid port number * @return bool */ public static function is_url_active($url, $port, $timeout = 5) { if (function_exists('fsockopen')) { $port = isset($port) && is_integer($port) ? $port : 80; $connected = @fsockopen($url, $port, $errno, $errstr, $timeout); //website and port if ($connected) { $is_conn = true; @fclose($connected); } else { $is_conn = false; } return $is_conn; } else { return false; } } public static function parse_host($url) { $url = parse_url(trim($url)); if ($url == false) { return null; } return trim($url['host'] ? $url['host'] : array_shift(explode('/', $url['path'], 2))); } //PHP POST or GET requets private static function php_get_post($url, $params, $headers = null, $method) { $full_url = $url; if ($method == 'GET' && count($params)) { $url = preg_replace('/\?.*/', '', $url); $full_url = $url . '?' . http_build_query($params); } $data = array('http' => array( 'method' => $method, 'content' => http_build_query($params))); if ($headers !== null) { $data['http']['header'] = $headers; } $ctx = stream_context_create($data); $fp = @fopen($full_url, 'rb', false, $ctx); if (!$fp) { throw new Exception("Problem with $full_url, $php_errormsg"); } $response = @stream_get_contents($fp); if ($response === false) { throw new Exception("Problem reading data from $full_url, $php_errormsg"); } return $response; } } ?> in 2004-2006 and placed in # the public domain. Revised in subsequent years, still public domain. # # There's absolutely no warranty. # # The homepage URL for this framework is: # # http://www.openwall.com/phpass/ # # Please be sure to update the Version line if you edit this file in any way. # It is suggested that you leave the main version number intact, but indicate # your project name (after the slash) and add your own revision information. # # Please do not change the "private" password hashing method implemented in # here, thereby making your hashes incompatible. However, if you must, please # change the hash type identifier (the "$P$") to something different. # # Obviously, since this code is in the public domain, the above are not # requirements (there can be none), but merely suggestions. # class DUPX_PasswordHash { var $itoa64; var $iteration_count_log2; var $portable_hashes; var $random_state; function __construct($iteration_count_log2, $portable_hashes) { $this->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) $iteration_count_log2 = 8; $this->iteration_count_log2 = $iteration_count_log2; $this->portable_hashes = $portable_hashes; $this->random_state = microtime(); if (function_exists('getmypid')) $this->random_state .= getmypid(); } function PasswordHash($iteration_count_log2, $portable_hashes) { self::__construct($iteration_count_log2, $portable_hashes); } function get_random_bytes($count) { $output = ''; if (@is_readable('/dev/urandom') && ($fh = @fopen('/dev/urandom', 'rb'))) { $output = fread($fh, $count); fclose($fh); } if (strlen($output) < $count) { $output = ''; for ($i = 0; $i < $count; $i += 16) { $this->random_state = md5(microtime() . $this->random_state); $output .= md5($this->random_state, TRUE); } $output = substr($output, 0, $count); } return $output; } function encode64($input, $count) { $output = ''; $i = 0; do { $value = ord($input[$i++]); $output .= $this->itoa64[$value & 0x3f]; if ($i < $count) $value |= ord($input[$i]) << 8; $output .= $this->itoa64[($value >> 6) & 0x3f]; if ($i++ >= $count) break; if ($i < $count) $value |= ord($input[$i]) << 16; $output .= $this->itoa64[($value >> 12) & 0x3f]; if ($i++ >= $count) break; $output .= $this->itoa64[($value >> 18) & 0x3f]; } while ($i < $count); return $output; } function gensalt_private($input) { $output = '$P$'; $output .= $this->itoa64[min($this->iteration_count_log2 + ((PHP_VERSION >= '5') ? 5 : 3), 30)]; $output .= $this->encode64($input, 6); return $output; } function crypt_private($password, $setting) { $output = '*0'; if (substr($setting, 0, 2) === $output) $output = '*1'; $id = substr($setting, 0, 3); # We use "$P$", phpBB3 uses "$H$" for the same thing if ($id !== '$P$' && $id !== '$H$') return $output; $count_log2 = strpos($this->itoa64, $setting[3]); if ($count_log2 < 7 || $count_log2 > 30) return $output; $count = 1 << $count_log2; $salt = substr($setting, 4, 8); if (strlen($salt) !== 8) return $output; # We were kind of forced to use MD5 here since it's the only # cryptographic primitive that was available in all versions # of PHP in use. To implement our own low-level crypto in PHP # would have resulted in much worse performance and # consequently in lower iteration counts and hashes that are # quicker to crack (by non-PHP code). $hash = md5($salt . $password, TRUE); do { $hash = md5($hash . $password, TRUE); } while (--$count); $output = substr($setting, 0, 12); $output .= $this->encode64($hash, 16); return $output; } function gensalt_blowfish($input) { # This one needs to use a different order of characters and a # different encoding scheme from the one in encode64() above. # We care because the last character in our encoded string will # only represent 2 bits. While two known implementations of # bcrypt will happily accept and correct a salt string which # has the 4 unused bits set to non-zero, we do not want to take # chances and we also do not want to waste an additional byte # of entropy. $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; $output = '$2a$'; $output .= chr(ord('0') + $this->iteration_count_log2 / 10); $output .= chr(ord('0') + $this->iteration_count_log2 % 10); $output .= '$'; $i = 0; do { $c1 = ord($input[$i++]); $output .= $itoa64[$c1 >> 2]; $c1 = ($c1 & 0x03) << 4; if ($i >= 16) { $output .= $itoa64[$c1]; break; } $c2 = ord($input[$i++]); $c1 |= $c2 >> 4; $output .= $itoa64[$c1]; $c1 = ($c2 & 0x0f) << 2; $c2 = ord($input[$i++]); $c1 |= $c2 >> 6; $output .= $itoa64[$c1]; $output .= $itoa64[$c2 & 0x3f]; } while (1); return $output; } function HashPassword($password) { $random = ''; if (CRYPT_BLOWFISH === 1 && !$this->portable_hashes) { $random = $this->get_random_bytes(16); $hash = crypt($password, $this->gensalt_blowfish($random)); if (strlen($hash) === 60) return $hash; } if (strlen($random) < 6) $random = $this->get_random_bytes(6); $hash = $this->crypt_private($password, $this->gensalt_private($random)); if (strlen($hash) === 34) return $hash; # Returning '*' on error is safe here, but would _not_ be safe # in a crypt(3)-like function used _both_ for generating new # hashes and for validating passwords against existing hashes. return '*'; } function CheckPassword($password, $stored_hash) { $hash = $this->crypt_private($password, $stored_hash); if ($hash[0] === '*') $hash = crypt($password, $stored_hash); # This is not constant-time. In order to keep the code simple, # for timing safety we currently rely on the salts being # unpredictable, which they are at least in the non-fallback # cases (that is, when we use /dev/urandom and bcrypt). return $hash === $stored_hash; } } ?> CheckPassword(base64_encode($_POST['secure-pass']), $GLOBALS['FW_SECUREPASS']); if (! $pass_check) { die("Unauthorized Access: Please provide a password!"); } } //Alternative control switch structer will not work in this case //see: http://php.net/manual/en/control-structures.alternative-syntax.php //Some clients will create double spaces such as the FTP client which //will break example found online switch ($_POST['action_ajax']) : case "1": ?>open($GLOBALS['FW_PACKAGE_NAME']) === TRUE) { DUPX_Log::info("\n>>> START EXTRACTION:"); if (!$zip->extractTo($target)) { DUPX_Log::error(ERR_ZIPEXTRACTION); } $log = print_r($zip, true); //Keep original timestamp on the file if ($_POST['archive_filetime'] == 'original') { $log .= "File timestamp is 'Original' mode.\n"; for ($idx = 0; $s = $zip->statIndex($idx); $idx++) { touch($target.DIRECTORY_SEPARATOR.$s['name'], $s['mtime']); } } else { $now = date("Y-m-d H:i:s"); $log .= "File timestamp is 'Current' mode: {$now}\n"; } $close_response = $zip->close(); $log .= "<<< EXTRACTION COMPLETE: " . var_export($close_response, true); DUPX_Log::info($log); } else { DUPX_Log::error(ERR_ZIPOPEN); } } //=============================== //RESET SERVER CONFIG FILES //=============================== if ($_POST['retain_config']) { DUPX_Log::info("\nNOTICE: Manual update of permalinks required see: Admin > Settings > Permalinks > Click Save Changes"); DUPX_Log::info("Retaining the original htaccess, user.ini or web.config files may cause issues with the setup of this site."); DUPX_Log::info("If you run into issues during or after the install process please uncheck the 'Config Files' checkbox labeled:"); DUPX_Log::info("'Retain original .htaccess, .user.ini and web.config' from Step 1 and re-run the installer. Backups of the"); DUPX_Log::info("orginal config files will be made and can be merged per required directive."); } else { DUPX_ServerConfig::reset(); } //FINAL RESULTS $ajax1_end = DUPX_U::getMicrotime(); $ajax1_sum = DUPX_U::elapsedTime($ajax1_end, $ajax1_start); DUPX_Log::info("\nSTEP-1 COMPLETE @ " . @date('h:i:s') . " - RUNTIME: {$ajax1_sum}"); $JSON['pass'] = 1; echo json_encode($JSON); error_reporting($ajax1_error_level); die(''); ?>Success" : "
    Fail
    "; $tstDB = ($dbFound) ? "
    Success
    " : "
    Fail
    "; $dbversion_info = DUPX_DB::getServerInfo($dbConn); $dbversion_info = empty($dbversion_info) ? 'no connection' : $dbversion_info; $dbversion_info_fail = $dbConn && version_compare(DUPX_DB::getVersion($dbConn), '5.5.3') < 0; $dbversion_compat = DUPX_DB::getVersion($dbConn); $dbversion_compat = empty($dbversion_compat) ? 'no connection' : $dbversion_compat; $dbversion_compat_fail = $dbConn && version_compare($dbversion_compat, $GLOBALS['FW_VERSION_DB']) < 0; $tstInfo = ($dbversion_info_fail) ? "
    ".DUPX_U::esc_html($dbversion_info)."
    " : "
    ".DUPX_U::esc_html($dbversion_info)."
    "; $tstCompat = ($dbversion_compat_fail) ? "
    This Server: [".DUPX_U::esc_html($dbversion_compat)."] -- Package Server: [".DUPX_U::esc_html($GLOBALS['FW_VERSION_DB'])."]
    " : "
    This Server: [".DUPX_U::esc_html($dbversion_compat)."] -- Package Server: [".DUPX_U::esc_html($GLOBALS['FW_VERSION_DB'])."]
    "; $html .= "
    Using Connection String:
    Host=".DUPX_U::esc_html($_POST['dbhost'])."; Database=".DUPX_U::esc_html($_POST['dbname'])."; Uid=".DUPX_U::esc_html($_POST['dbuser'])."; Pwd=".DUPX_U::esc_html($_POST['dbpass'])."; {$port_view}
    Host: ".$tstSrv."
    Database: ".$tstDB."
    Version: ".$tstInfo."
    Compatibility: ".$tstCompat."
    "; //-------------------------------- //WARNING: Unable to connect $html .= (!$dbConn || !$dbFound) ? "
    " . ERR_DBCONNECT_INFO . "
    " : ''; //WARNING: DB has tables with create option if ($_POST['dbaction'] == 'create') { $tblcount = DUPX_DB::countTables($dbConn, $_POST['dbname']); $html .= ($tblcount > 0) ? "
    WARNING: " . sprintf(ERR_DBEMPTY, DUPX_U::esc_html($_POST['dbname']), DUPX_U::esc_html($tblcount)) . "
    " : ''; } //WARNNG: Input has utf8 $dbConnItems = array($_POST['dbhost'], $_POST['dbuser'], $_POST['dbname'],$_POST['dbpass']); $dbUTF8_tst = false; foreach ($dbConnItems as $value) { if (DUPX_U::isNonASCII($value)) { $dbUTF8_tst = true; break; } } //WARNING: UTF8 Data in Connection String $html .= (!$dbConn && $dbUTF8_tst) ? "
    WARNING: " . ERR_TESTDB_UTF8 . "
    " : ''; //NOTICE: Version Too Low $html .= ($dbversion_info_fail) ? "
    NOTICE: " . ERR_TESTDB_VERSION_INFO . "
    " : ''; //NOTICE: Version Incompatibility $html .= ($dbversion_compat_fail) ? "
    NOTICE: " . ERR_TESTDB_VERSION_COMPAT . "
    " : ''; $html .= "
    "; die($html); } //=============================== //ERROR MESSAGES //=============================== //ERR_MAKELOG ($GLOBALS['LOG_FILE_HANDLE'] != false) or DUPX_Log::error(ERR_MAKELOG); //ERR_MYSQLI_SUPPORT function_exists('mysqli_connect') or DUPX_Log::error(ERR_MYSQLI_SUPPORT); //ERR_DBCONNECT $dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], null, $_POST['dbport']); @mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME'])); ($dbh) or DUPX_Log::error(ERR_DBCONNECT . mysqli_connect_error()); if ($_POST['dbaction'] == 'empty') { mysqli_select_db($dbh, $_POST['dbname']) or DUPX_Log::error(sprintf(ERR_DBCREATE, $_POST['dbname'])); } //ERR_DBEMPTY if ($_POST['dbaction'] == 'create' ) { $tblcount = DUPX_DB::countTables($dbh, $_POST['dbname']); if ($tblcount > 0) { DUPX_Log::error(sprintf(ERR_DBEMPTY, $_POST['dbname'], $tblcount)); } } $log = <<= $php_mem_range && $php_mem_range != 0) { $db_file_size = DUPX_U::readableByteSize($db_file_size); $msg = "\nWARNING: The database script is '{$db_file_size}' in size. The PHP memory allocation is set\n"; $msg .= "at '{$php_mem}'. There is a high possibility that the installer script will fail with\n"; $msg .= "a memory allocation error when trying to load the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file. It is\n"; $msg .= "recommended to increase the 'memory_limit' setting in the php.ini config file.\n"; $msg .= "see: {$faq_url}{$utm_prefix}inst_step2_lgdbscript#faq-trouble-056-q \n"; DUPX_Log::info($msg); } @chmod("{$root_path}/dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", 0777); $sql_file = file_get_contents("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", true); //ERROR: Reading database.sql file if ($sql_file === FALSE || strlen($sql_file) < 10) { $msg = "Unable to read the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file from the archive. Please check these items:
    "; $msg .= "1. Validate permissions and/or group-owner rights on these items:
    "; $msg .= " - File: dup-database__{$GLOBALS['PACKAGE_HASH']}.sql
    - Directory: [{$root_path}]
    "; $msg .= "see: {$faq_url}#faq-trouble-055-q
    "; $msg .= "2. Validate the dup-database__{$GLOBALS['PACKAGE_HASH']}.sql file exists and is in the root of the archive.zip file
    "; $msg .= "see: {$faq_url}#faq-installer-020-q
    "; DUPX_Log::error($msg); } //Removes invalid space characters //Complex Subject See: http://webcollab.sourceforge.net/unicode.html if ($_POST['dbnbsp']) { DUPX_Log::info("NOTICE: Ran fix non-breaking space characters\n"); $sql_file = preg_replace('/\xC2\xA0/', ' ', $sql_file); } //Write new contents to install-data.sql $sql_file_copy_status = file_put_contents($GLOBALS['SQL_FILE_NAME'], $sql_file); $sql_result_file_data = explode(";\n", $sql_file); $sql_result_file_length = count($sql_result_file_data); $sql_result_file_path = "{$root_path}/{$GLOBALS['SQL_FILE_NAME']}"; $sql_file = null; $db_collatefb_log = ''; if($_POST['dbcollatefb']){ $supportedCollations = DUPX_DB::getSupportedCollationsList($dbh); $collation_arr = array( 'utf8mb4_unicode_520_ci', 'utf8mb4_unicode_520', 'utf8mb4_unicode_ci', 'utf8mb4', 'utf8_unicode_520_ci', 'utf8_unicode_520', 'utf8_unicode_ci', 'utf8' ); $latest_supported_collation = ''; $latest_supported_index = -1; foreach ($collation_arr as $key => $val){ if(in_array($val,$supportedCollations)){ $latest_supported_collation = $val; $latest_supported_index = $key; break; } } //No need to replace if current DB is up to date if($latest_supported_index != 0){ for($i=0; $i < $latest_supported_index; $i++){ foreach ($sql_result_file_data as $index => $col_sql_query){ if(strpos($col_sql_query,$collation_arr[$i]) !== false){ $sql_result_file_data[$index] = str_replace($collation_arr[$i], $latest_supported_collation, $col_sql_query); if(strpos($collation_arr[$i],'utf8mb4') !== false && strpos($latest_supported_collation,'utf8mb4') === false){ $sql_result_file_data[$index] = str_replace('utf8mb4','utf8',$sql_result_file_data[$index]); } $sub_query = str_replace("\n", '', substr($col_sql_query, 0, 75)); $db_collatefb_log .= " - Collation '{$collation_arr[$i]}' set to '{$latest_supported_collation}' on query [{$sub_query}...]\n"; } } } } } //WARNING: Create installer-data.sql failed if ($sql_file_copy_status === FALSE || filesize($sql_result_file_path) == 0 || !is_readable($sql_result_file_path)) { $sql_file_size = DUPX_U::readableByteSize(filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql")); $msg = "\nWARNING: Unable to properly copy dup-database__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size}) to {$GLOBALS['SQL_FILE_NAME']}. Please check these items:\n"; $msg .= "- Validate permissions and/or group-owner rights on dup-database__{$GLOBALS['PACKAGE_HASH']}.sql and directory [{$root_path}] \n"; $msg .= "- see: {$faq_url}{$utm_prefix}inst_step2_copydbsql#faq-trouble-055-q \n"; DUPX_Log::info($msg); } //================================= //START DB RUN @mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME'])); @mysqli_query($dbh, "SET max_allowed_packet = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_PACKETS'])); DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); //Will set mode to null only for this db handle session //sql_mode can cause db create issues on some systems $qry_session_custom = true; switch ($_POST['dbmysqlmode']) { case 'DISABLE': @mysqli_query($dbh, "SET SESSION sql_mode = ''"); break; case 'CUSTOM': $dbmysqlmode_opts = $_POST['dbmysqlmode_opts']; $qry_session_custom = @mysqli_query($dbh, "SET SESSION sql_mode = '".mysqli_real_escape_string($dbh, $dbmysqlmode_opts)."'"); if ($qry_session_custom == false) { $sql_error = mysqli_error($dbh); $log = "WARNING: Trying to set a custom sql_mode setting issue has been detected:\n{$sql_error}.\n"; $log .= "For more details visit: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html\n"; } break; } //Set defaults in-case the variable could not be read $dbvar_maxtime = DUPX_DB::getVariable($dbh, 'wait_timeout'); $dbvar_maxpacks = DUPX_DB::getVariable($dbh, 'max_allowed_packet'); $dbvar_sqlmode = DUPX_DB::getVariable($dbh, 'sql_mode'); $dbvar_maxtime = is_null($dbvar_maxtime) ? 300 : $dbvar_maxtime; $dbvar_maxpacks = is_null($dbvar_maxpacks) ? 1048576 : $dbvar_maxpacks; $dbvar_sqlmode = empty($dbvar_sqlmode) ? 'NOT_SET' : $dbvar_sqlmode; $dbvar_version = DUPX_DB::getVersion($dbh); $sql_file_size1 = DUPX_U::readableByteSize(@filesize("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql")); $sql_file_size2 = DUPX_U::readableByteSize(@filesize("{$GLOBALS['SQL_FILE_NAME']}")); $db_collatefb = isset($_POST['dbcollatefb']) ? 'On' : 'Off'; DUPX_Log::info("--------------------------------------"); DUPX_Log::info("DATABASE ENVIRONMENT"); DUPX_Log::info("--------------------------------------"); DUPX_Log::info("MYSQL VERSION:\tThis Server: {$dbvar_version} -- Build Server: {$GLOBALS['FW_VERSION_DB']}"); DUPX_Log::info("FILE SIZE:\tdup-database__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size1}) - dup-installer-data__{$GLOBALS['PACKAGE_HASH']}.sql ({$sql_file_size2})"); DUPX_Log::info("TIMEOUT:\t{$dbvar_maxtime}"); DUPX_Log::info("MAXPACK:\t{$dbvar_maxpacks}"); DUPX_Log::info("SQLMODE:\t{$dbvar_sqlmode}"); DUPX_Log::info("NEW SQL FILE:\t[{$sql_result_file_path}]"); DUPX_Log::info("COLLATE RESET:\t{$db_collatefb}\n{$db_collatefb_log}"); if ($qry_session_custom == false) { DUPX_Log::info("\n{$log}\n"); } //CREATE DB switch ($_POST['dbaction']) { case "create": mysqli_query($dbh, "CREATE DATABASE IF NOT EXISTS `".mysqli_real_escape_string($dbh, $_POST['dbname'])."`"); mysqli_select_db($dbh, mysqli_real_escape_string($dbh, $_POST['dbname'])) or DUPX_Log::error(sprintf(ERR_DBCONNECT_CREATE, $_POST['dbname'])); break; case "empty": //DROP DB TABLES $drop_log = "Database already empty. Ready for install."; $sql = "SHOW FULL TABLES WHERE Table_Type != 'VIEW'"; $found_tables = null; if ($result = mysqli_query($dbh, $sql)) { while ($row = mysqli_fetch_row($result)) { $found_tables[] = $row[0]; } if (count($found_tables) > 0) { foreach ($found_tables as $table_name) { $sql = "DROP TABLE `".mysqli_real_escape_string($dbh, $_POST['dbname'])."`.`".mysqli_real_escape_string($dbh, $table_name)."`"; if (!$result = mysqli_query($dbh, $sql)) { DUPX_Log::error(sprintf(ERR_DBTRYCLEAN, $_POST['dbname'])); } } } $drop_log = count($found_tables); } break; } //WRITE DATA DUPX_Log::info("--------------------------------------"); DUPX_Log::info("DATABASE RESULTS"); DUPX_Log::info("--------------------------------------"); $profile_start = DUPX_U::getMicrotime(); $fcgi_buffer_pool = 5000; $fcgi_buffer_count = 0; $dbquery_rows = 0; $dbtable_rows = 1; $dbquery_errs = 0; $counter = 0; @mysqli_autocommit($dbh, false); while ($counter < $sql_result_file_length) { $query_strlen = strlen(trim($sql_result_file_data[$counter])); if ($dbvar_maxpacks < $query_strlen) { DUPX_Log::info("**ERROR** Query size limit [length={$query_strlen}] [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]"); $dbquery_errs++; } elseif ($query_strlen > 0) { @mysqli_free_result(@mysqli_query($dbh, ($sql_result_file_data[$counter]))); $err = mysqli_error($dbh); //Check to make sure the connection is alive if (!empty($err)) { if (!mysqli_ping($dbh)) { mysqli_close($dbh); $dbh = DUPX_DB::connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname'], $_POST['dbport'] ); // Reset session setup @mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME'])); DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); } DUPX_Log::info("**ERROR** database error write '{$err}' - [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]"); $dbquery_errs++; //Buffer data to browser to keep connection open } else { if ($GLOBALS['DB_FCGI_FLUSH'] && $fcgi_buffer_count++ > $fcgi_buffer_pool) { $fcgi_buffer_count = 0; DUPX_U::fcgiFlush(); } $dbquery_rows++; } } $counter++; } @mysqli_commit($dbh); @mysqli_autocommit($dbh, true); DUPX_Log::info("ERRORS FOUND:\t{$dbquery_errs}"); DUPX_Log::info("TABLES DROPPED:\t{$drop_log}"); DUPX_Log::info("QUERIES RAN:\t{$dbquery_rows}\n"); $dbtable_count = 0; if ($result = mysqli_query($dbh, "SHOW TABLES")) { while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) { $table_rows = DUPX_DB::countTableRows($dbh, $row[0]); $dbtable_rows += $table_rows; DUPX_Log::info("{$row[0]}: ({$table_rows})"); $dbtable_count++; } @mysqli_free_result($result); } if ($dbtable_count == 0) { DUPX_Log::error("No tables where created during step 2 of the install. Please review the ".$GLOBALS["LOG_FILE_NAME"]." file for ERROR messages. You may have to manually run the installer-data_[HASH].sql with a tool like phpmyadmin to validate the data input. If you have enabled compatibility mode during the package creation process then the database server version your using may not be compatible with this script.\n"); } //DATA CLEANUP: Perform Transient Cache Cleanup //Remove all duplicator entries and record this one since this is a new install. $dbdelete_count = 0; @mysqli_query($dbh, "DELETE FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."duplicator_packages`"); $dbdelete_count1 = @mysqli_affected_rows($dbh) or 0; @mysqli_query($dbh, "DELETE FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE `option_name` LIKE ('_transient%') OR `option_name` LIKE ('_site_transient%')"); $dbdelete_count2 = @mysqli_affected_rows($dbh) or 0; $dbdelete_count = (abs($dbdelete_count1) + abs($dbdelete_count2)); DUPX_Log::info("\nRemoved '{$dbdelete_count}' cache/transient rows"); //Reset Duplicator Options foreach ($GLOBALS['FW_OPTS_DELETE'] as $value) { mysqli_query($dbh, "DELETE FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE `option_name` = '".mysqli_real_escape_string($dbh, $value)."'"); } @mysqli_close($dbh); //FINAL RESULTS $profile_end = DUPX_U::getMicrotime(); $ajax2_end = DUPX_U::getMicrotime(); $ajax1_sum = DUPX_U::elapsedTime($ajax2_end, $ajax2_start); DUPX_Log::info("\nCREATE/INSTALL RUNTIME: " . DUPX_U::elapsedTime($profile_end, $profile_start)); DUPX_Log::info('STEP-2 COMPLETE @ ' . @date('h:i:s') . " - RUNTIME: {$ajax1_sum}"); $JSON['pass'] = 1; $JSON['table_count'] = $dbtable_count; $JSON['table_rows'] = $dbtable_rows; $JSON['query_errs'] = $dbquery_errs; echo json_encode($JSON); error_reporting($ajax1_error_level); die(''); ?> HOST: {$_POST['dbhost']}
    DATABASE: {$_POST['dbname']}
    "; $msg .= "Connection Error: {$dbConnError}"; DUPX_Log::error($msg); } $charset_server = @mysqli_character_set_name($dbh); @mysqli_query($dbh, "SET wait_timeout = ".mysqli_real_escape_string($dbh, $GLOBALS['DB_MAX_TIME'])); DUPX_DB::setCharset($dbh, $_POST['dbcharset'], $_POST['dbcollate']); //LOGGING $POST_LOG = $_POST; unset($POST_LOG['tables']); unset($POST_LOG['plugins']); unset($POST_LOG['dbpass']); ksort($POST_LOG); $date = @date('h:i:s'); $charset_client = @mysqli_character_set_name($dbh); $log = << 0)) ? print_r($_POST['tables'], true) : 'No tables selected to update'; $log .= "--------------------------------------\n"; $log .= "KEEP PLUGINS ACTIVE\n"; $log .= "--------------------------------------\n"; $log .= (isset($_POST['plugins']) && count($_POST['plugins'] > 0)) ? print_r($_POST['plugins'], true) : 'No plugins selected for activation'; DUPX_Log::info($log, 2); //UPDATE SETTINGS $blog_name = $_POST['blogname']; $plugin_list = (isset($_POST['plugins'])) ? $_POST['plugins'] : array(); // Force Duplicator active so we the security cleanup will be available if (!in_array('duplicator/duplicator.php', $plugin_list)) { $plugin_list[] = 'duplicator/duplicator.php'; } $serial_plugin_list = @serialize($plugin_list); mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '{$blog_name}' WHERE option_name = 'blogname' "); mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '{$serial_plugin_list}' WHERE option_name = 'active_plugins' "); $log = "--------------------------------------\n"; $log .= "SERIALIZER ENGINE\n"; $log .= "[*] scan every column\n"; $log .= "[~] scan only text columns\n"; $log .= "[^] no searchable columns\n"; $log .= "--------------------------------------"; DUPX_Log::info($log); $url_old_json = str_replace('"', "", json_encode($_POST['url_old'])); $url_new_json = str_replace('"', "", json_encode($_POST['url_new'])); $path_old_json = str_replace('"', "", json_encode($_POST['path_old'])); $path_new_json = str_replace('"', "", json_encode($_POST['path_new'])); //DIRS PATHS array_push($GLOBALS['REPLACE_LIST'], array('search' => $_POST['path_old'], 'replace' => $_POST['path_new']), array('search' => $path_old_json, 'replace' => $path_new_json), array('search' => urlencode($_POST['path_old']), 'replace' => urlencode($_POST['path_new'])), array('search' => rtrim(DUPX_U::unsetSafePath($_POST['path_old']), '\\'), 'replace' => rtrim($_POST['path_new'], '/')) ); //SEARCH WITH NO PROTOCAL: RAW "//" $url_old_raw = str_ireplace(array('http://', 'https://'), '//', $_POST['url_old']); $url_new_raw = str_ireplace(array('http://', 'https://'), '//', $_POST['url_new']); $url_old_raw_json = str_replace('"', "", json_encode($url_old_raw)); $url_new_raw_json = str_replace('"', "", json_encode($url_new_raw)); array_push($GLOBALS['REPLACE_LIST'], //RAW array('search' => $url_old_raw, 'replace' => $url_new_raw), array('search' => $url_old_raw_json, 'replace' => $url_new_raw_json), array('search' => urlencode($url_old_raw), 'replace' => urlencode($url_new_raw)) ); //SEARCH HTTP(S) EXPLICIT REQUEST //Because the raw replace above has already changed all urls just fix https/http issue //if the user has explicitly asked other-wise word boundary issues will occur: //Old site: http://mydomain.com/somename/ //New site: http://mydomain.com/somename-dup/ //Result: http://mydomain.com/somename-dup-dup/ if (stristr($_POST['url_old'], 'http:') && stristr($_POST['url_new'], 'https:') ) { $url_old_http = str_ireplace('https:', 'http:', $_POST['url_new']); $url_new_http = $_POST['url_new']; $url_old_http_json = str_replace('"', "", json_encode($url_old_http)); $url_new_http_json = str_replace('"', "", json_encode($url_new_http)); } elseif(stristr($_POST['url_old'], 'https:') && stristr($_POST['url_new'], 'http:')) { $url_old_http = str_ireplace('http:', 'https:', $_POST['url_new']); $url_new_http = $_POST['url_new']; $url_old_http_json = str_replace('"', "", json_encode($url_old_http)); $url_new_http_json = str_replace('"', "", json_encode($url_new_http)); } if(isset($url_old_http)){ array_push($GLOBALS['REPLACE_LIST'], array('search' => $url_old_http, 'replace' => $url_new_http), array('search' => $url_old_http_json, 'replace' => $url_new_http_json), array('search' => urlencode($url_old_http), 'replace' => urlencode($url_new_http)) ); } //Remove trailing slashes function _dupx_array_rtrim(&$value) { $value = rtrim($value, '\/'); } array_walk_recursive($GLOBALS['REPLACE_LIST'], _dupx_array_rtrim); @mysqli_autocommit($dbh, false); $report = DUPX_UpdateEngine::load($dbh, $GLOBALS['REPLACE_LIST'], $_POST['tables'], $_POST['fullsearch']); @mysqli_commit($dbh); @mysqli_autocommit($dbh, true); //BUILD JSON RESPONSE $JSON = array(); $JSON['step2'] = json_decode(urldecode($_POST['json'])); $JSON['step3'] = $report; $JSON['step3']['warn_all'] = 0; $JSON['step3']['warnlist'] = array(); DUPX_UpdateEngine::logStats($report); DUPX_UpdateEngine::logErrors($report); //Reset the postguid data if ($_POST['postguid']) { mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."posts` SET guid = REPLACE(guid, '".mysqli_real_escape_string($dbh, $_POST['url_new'])."', '".mysqli_real_escape_string($dbh, $_POST['url_old'])."')"); $update_guid = @mysqli_affected_rows($dbh) or 0; DUPX_Log::info("Reverted '{$update_guid}' post guid columns back to '{$_POST['url_old']}'"); } /** FINAL UPDATES: Must happen after the global replace to prevent double pathing http://xyz.com/abc01 will become http://xyz.com/abc0101 with trailing data */ mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '".mysqli_real_escape_string($dbh, $_POST['url_new'])."' WHERE option_name = 'home' "); mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` SET option_value = '".mysqli_real_escape_string($dbh, $_POST['siteurl'])."' WHERE option_name = 'siteurl' "); mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` (option_value, option_name) VALUES('".mysqli_real_escape_string($dbh, $_POST['exe_safe_mode'])."','duplicator_exe_safe_mode')"); //=============================================== //CONFIGURATION FILE UPDATES //=============================================== DUPX_Log::info("\n===================================="); DUPX_Log::info('CONFIGURATION FILE UPDATES:'); DUPX_Log::info("====================================\n"); DUPX_WPConfig::updateStandard(); $config_file = DUPX_WPConfig::updateExtended(); DUPX_Log::info("UPDATED WP-CONFIG: {$root_path}/wp-config.php' (if present)"); //Web Server Config Updates if (!isset($_POST['url_new']) || $_POST['retain_config']) { DUPX_Log::info("\nNOTICE: Manual update of permalinks required see: Admin > Settings > Permalinks > Click Save Changes"); DUPX_Log::info("Retaining the original htaccess, user.ini or web.config files may cause issues with the setup of this site."); DUPX_Log::info("If you run into issues during or after the install process please uncheck the 'Config Files' checkbox labeled:"); DUPX_Log::info("'Retain original .htaccess, .user.ini and web.config' from Step 1 and re-run the installer. Backups of the"); DUPX_Log::info("orginal config files will be made and can be merged per required directive."); } else { DUPX_ServerConfig::setup($dbh); } //=============================================== //GENERAL UPDATES & CLEANUP //=============================================== DUPX_Log::info("\n===================================="); DUPX_Log::info('GENERAL UPDATES & CLEANUP:'); DUPX_Log::info("====================================\n"); /** CREATE NEW USER LOGIC */ if (strlen($_POST['wp_username']) >= 4 && strlen($_POST['wp_password']) >= 6) { $post_wp_username = DUPX_U::sanitize_text_field($_POST['wp_username']); $post_wp_password = DUPX_U::sanitize_text_field($_POST['wp_password']); $post_wp_username = mysqli_real_escape_string($dbh, $post_wp_username); $post_wp_password = mysqli_real_escape_string($dbh, $post_wp_password); $newuser_check = mysqli_query($dbh, "SELECT COUNT(*) AS count FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."users` WHERE user_login = '{$post_wp_username}' "); $newuser_row = mysqli_fetch_row($newuser_check); $newuser_count = is_null($newuser_row) ? 0 : $newuser_row[0]; if ($newuser_count == 0) { $newuser_datetime = @date("Y-m-d H:i:s"); $newuser_security = mysqli_real_escape_string($dbh, 'a:1:{s:13:"administrator";s:1:"1";}'); $newuser_test1 = @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."users` (`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) VALUES ('{$post_wp_username}', MD5('{$post_wp_password}'), '{$post_wp_username}', '', '{$newuser_datetime}', '', '0', '{$post_wp_username}')"); $newuser_insert_id = mysqli_insert_id($dbh); $newuser_test2 = @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', '".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."capabilities', '{$newuser_security}')"); $newuser_test3 = @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', '".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."user_level', '10')"); //Misc Meta-Data Settings: @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', 'rich_editing', 'true')"); @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', 'admin_color', 'fresh')"); @mysqli_query($dbh, "INSERT INTO `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."usermeta` (`user_id`, `meta_key`, `meta_value`) VALUES ('{$newuser_insert_id}', 'nickname', '{$post_wp_username}')"); if ($newuser_test1 && $newuser_test2 && $newuser_test3) { DUPX_Log::info("NEW WP-ADMIN USER: New username '{$_POST['wp_username']}' was created successfully \n "); } else { $newuser_warnmsg = "NEW WP-ADMIN USER: Failed to create the user '{".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."}' \n "; $JSON['step3']['warnlist'][] = $newuser_warnmsg; DUPX_Log::info($newuser_warnmsg); } } else { $newuser_warnmsg = "NEW WP-ADMIN USER: Username '{$_POST['wp_username']}' already exists in the database. Unable to create new account \n"; $JSON['step3']['warnlist'][] = $newuser_warnmsg; DUPX_Log::info($newuser_warnmsg); } } /** ============================== * MU Updates*/ $mu_newDomain = parse_url($_POST['url_new']); $mu_oldDomain = parse_url($_POST['url_old']); $mu_newDomainHost = $mu_newDomain['host']; $mu_oldDomainHost = $mu_oldDomain['host']; $mu_newUrlPath = parse_url($_POST['url_new'], PHP_URL_PATH); $mu_oldUrlPath = parse_url($_POST['url_old'], PHP_URL_PATH); //Force a path for PATH_CURRENT_SITE $mu_newUrlPath = (empty($mu_newUrlPath) || ($mu_newUrlPath == '/')) ? '/' : rtrim($mu_newUrlPath, '/') . '/'; $mu_oldUrlPath = (empty($mu_oldUrlPath) || ($mu_oldUrlPath == '/')) ? '/' : rtrim($mu_oldUrlPath, '/') . '/'; $mu_updates = @mysqli_query($dbh, "UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."blogs` SET domain = '".mysqli_real_escape_string($dbh, $mu_newDomainHost)."' WHERE domain = '".mysqli_real_escape_string($dbh, $mu_oldDomainHost)."'"); if ($mu_updates) { DUPX_Log::info("Update MU table blogs: domain {$mu_newDomainHost} "); DUPX_Log::info("UPDATE `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."blogs` SET domain = '".mysqli_real_escape_string($dbh, $mu_newDomainHost)."' WHERE domain = '".mysqli_real_escape_string($dbh, $mu_oldDomainHost)."'"); } //Create snapshots directory in order to //compensate for permissions on some servers if (!file_exists(DUPLICATOR_SSDIR_NAME)) { mkdir(DUPLICATOR_SSDIR_NAME, 0755); DUPX_Log::info("- Created directory ". DUPLICATOR_SSDIR_NAME); } $fp = fopen(DUPLICATOR_SSDIR_NAME . '/index.php', 'w'); fclose($fp); DUPX_Log::info("- Created file ". DUPLICATOR_SSDIR_NAME . '/index.php'); //=============================================== //NOTICES TESTS //=============================================== DUPX_Log::info("\n===================================="); DUPX_Log::info("NOTICES"); DUPX_Log::info("====================================\n"); $config_vars = array('WPCACHEHOME', 'COOKIE_DOMAIN', 'WP_SITEURL', 'WP_HOME', 'WP_TEMP_DIR'); $config_found = DUPX_U::getListValues($config_vars, $config_file); //Config File: if (! empty($config_found)) { $msg = "NOTICE: The wp-config.php has the following values set [" . implode(", ", $config_found) . "]. \n"; $msg .= 'Please validate these values are correct in your wp-config.php file. See the codex link for more details: https://codex.wordpress.org/Editing_wp-config.php'; $JSON['step3']['warnlist'][] = $msg; DUPX_Log::info($msg); } //Database: $result = @mysqli_query($dbh, "SELECT option_value FROM `".mysqli_real_escape_string($dbh, $GLOBALS['FW_TABLEPREFIX'])."options` WHERE option_name IN ('upload_url_path','upload_path')"); if ($result) { while ($row = mysqli_fetch_row($result)) { if (strlen($row[0])) { $msg = "NOTICE: The media settings values in the table '{$GLOBALS['FW_TABLEPREFIX']}options' has at least one the following values ['upload_url_path','upload_path'] set. \n"; $msg .= "Please validate these settings by logging into your wp-admin and going to Settings->Media area and validating the 'Uploading Files' section"; $JSON['step3']['warnlist'][] = $msg; DUPX_Log::info($msg); break; } } } if (empty($JSON['step3']['warnlist'])) { DUPX_Log::info("No Notices Found\n"); } $JSON['step3']['warn_all'] = empty($JSON['step3']['warnlist']) ? 0 : count($JSON['step3']['warnlist']); mysqli_close($dbh); $ajax2_end = DUPX_U::getMicrotime(); $ajax2_sum = DUPX_U::elapsedTime($ajax2_end, $ajax2_start); DUPX_Log::info("\nSTEP 3 COMPLETE @ " . @date('h:i:s') . " - RUNTIME: {$ajax2_sum}\n\n"); $JSON['step3']['pass'] = 1; error_reporting($ajax2_error_level); die(json_encode($JSON)); ?> Duplicator
      Duplicator
    version:
    help '; echo ($GLOBALS['FW_SECUREON']) ? 'locked' : 'unlocked'; ?>
    CheckPassword(base64_encode($_POST['secure-pass']), $GLOBALS['FW_SECUREPASS']); //FORWARD: password not enabled if (! $GLOBALS['FW_SECUREON'] && ! $_GET['debug']) { DUPX_HTTP::post_with_html($page_url, array('action_step' => '1', 'csrf_token' => DUPX_CSRF::generate('step1'))); exit; } //POSTBACK: valid password if ($pass_check) { DUPX_HTTP::post_with_html($page_url, array( 'action_step' => '1', 'csrf_token' => DUPX_CSRF::generate('step1'), 'secure-pass' => $_POST['secure-pass'])); exit; } //ERROR: invalid password if ($_POST['secure-try'] && ! $pass_check) { $page_err = 1; } ?>
    Installer Password

    Invalid Password! Please try again. If the problem persists see the more details link below.

    This file was password protected when it was created. If you do not remember the password check the details of the package on the site where it was created or visit the online FAQ for more details.



    90) ? 'Pass' : 'Fail'; //ARCHIVE FORMAT if ($arcStatus) { if (class_exists('ZipArchive')){ $zip = new ZipArchive(); if($zip->open($GLOBALS['ARCHIVE_PATH']) === TRUE ) { $arcFilePath = basename($GLOBALS['ARCHIVE_PATH']); $arcFilePath = substr($arcFilePath, 0, strrpos($arcFilePath, ".")); //Some systems the __MACOSX folder can cause issues on others it works fine removing //until further reports are discovered, removed on 04-06-2018 //$badFiles = array('__MACOSX', $arcFilePath); $badFiles = array('', $arcFilePath); $goodFiles = array("dup-database__{$GLOBALS['PACKAGE_HASH']}.sql", 'installer-backup.php'); $goodFilesFound = true; $badFilesFound = false; foreach ($badFiles as $val) { if (is_numeric($zip->locateName("{$val}/"))) { $badFilesFound = true; break; } } foreach ($goodFiles as $val) { if ($zip->locateName($val) !== true) { $goodFilesFound = false; } } $arcFormat = ($goodFilesFound == false && $badFilesFound == true) ? 'Fail' : 'Pass'; } } else { $arcFormat = 'NoZipArchive'; } } $all_arc = ($arcStatus == 'Pass' && $arcFormat != 'Fail' && $arcSizeStatus == 'Pass') ? 'Pass' : 'Fail'; //REQUIRMENTS $req = array(); $req['01'] = DUPX_Server::isDirWritable($GLOBALS["CURRENT_ROOT_PATH"]) ? 'Pass' : 'Fail'; $req['02'] = 'Pass'; //Place-holder for future check $req['03'] = 'Pass'; //Place-holder for future check; $req['04'] = function_exists('mysqli_connect') ? 'Pass' : 'Fail'; $req['05'] = DUPX_Server::$php_version_safe ? 'Pass' : 'Fail'; $all_req = in_array('Fail', $req) ? 'Fail' : 'Pass'; //NOTICES $openbase = ini_get("open_basedir"); $scanfiles = @scandir($GLOBALS["CURRENT_ROOT_PATH"]); $scancount = is_array($scanfiles) ? (count($scanfiles)) : -1; $datetime1 = $GLOBALS['FW_CREATED']; $datetime2 = date("Y-m-d H:i:s"); $fulldays = round(abs(strtotime($datetime1) - strtotime($datetime2))/86400); $root_path = DUPX_U::setSafePath($GLOBALS['CURRENT_ROOT_PATH']); $wpconf_path = "{$root_path}/wp-config.php"; $max_time_zero = @set_time_limit(0); $max_time_size = 314572800; //300MB $max_time_ini = ini_get('max_execution_time'); $max_time_warn = (is_numeric($max_time_ini) && $max_time_ini < 31 && $max_time_ini > 0) && $arcSize > $max_time_size; $notice = array(); if (!$GLOBALS['FW_ARCHIVE_ONLYDB']) { $notice['01'] = ! file_exists($wpconf_path) ? 'Good' : 'Warn'; $notice['02'] = $scancount <= 35 ? 'Good' : 'Warn'; } $notice['03'] = $fulldays <= 120 ? 'Good' : 'Warn'; $notice['04'] = 'Good'; //Place-holder for future check $notice['05'] = DUPX_Server::$php_version_53_plus ? 'Good' : 'Warn'; $notice['06'] = empty($openbase) ? 'Good' : 'Warn'; $notice['07'] = ! $max_time_warn ? 'Good' : 'Warn'; $all_notice = in_array('Warn', $notice) ? 'Warn' : 'Good'; //SUMMATION $req_success = ($all_req == 'Pass'); $req_notice = ($all_notice == 'Good'); $all_success = ($req_success && $req_notice); $agree_msg = "To enable this button the checkbox above under the 'Terms & Notices' must be checked."; //Get Size Data $projectedSize = DUPX_U::readableByteSize($GLOBALS['FW_PACKAGE_EST_SIZE']); $actualSize = DUPX_U::readableByteSize($arcSize); ?>
    Step 1 of 4: Deployment








    This installation will not be able to proceed until the 'Archive' and 'Validation' sections pass. Please adjust your servers settings or contact your server administrator, hosting provider or visit the resources below for additional help.








    Step 2 of 4: Install Database
    Action:
    Host:
    Database:
    User:
    Password:







    cPanel Connectivity

    This server does not appear to support cPanel!
    Consider upgrading to a host that does.
    Want even easier installs? Duplicator Pro allows the following right from the installer:
    • Directly login to cPanel
    • Instantly create new databases & users
    • Preview and select existing databases & users
    Note: Hosts that support cPanel provide remote access to server resources, allowing operations such as direct database and user creation. Since the Duplicator Pro installer can directly access cPanel, it dramatically speeds up your workflow.
    Step 3 of 4: Update Data
    URL: get
    Path:
    Title:


    Step 4 of 4: Test Site

    Click the 'Admin Login' button to login and finalize this install.

    Update of Permalinks required see: Admin > Settings > Permalinks > Save

    Safe Mode
    Safe mode has deactivated all plugins. Please be sure to enable your plugins after logging in. If you notice that problems arise when activating the plugins then active them one-by-one to isolate the plugin that could be causing the issue.
    IMPORTANT FINAL STEPS: Login into the WordPress Admin to remove all installation files and keep this site secure. This install is not complete until the installer files are removed!


    Additional Notes:
    • Review Migration Report
          Install Notices: ()   Update Notices: ()     General Notices: ()
    • Review this sites front-end or re-run the installer and go back to step 1.
    • If the .htaccess file was reset some plugin settings might need to be re-saved.
    • For additional help and questions visit the online FAQs.





    For complete help visit the Online Knowledge-Base
    Features available only in Duplicator Pro are flagged with a pro tag.

    Installer Security

    The installer security screen will allow for basic password protection on the installer. The password is set at package creation time. The password input on this screen must be entered before proceeding with an install. This setting is optional and can be turned on/off via the package creation screens.

    If you do not recall the password then login to the site where the package was created and click the details of the package to view the original password. To validate the password just typed you can toggle the view by clicking on the lock icon. For detail on how to override this setting visit the online FAQ for more details.
    Option Details
    Locked "Locked" means a password is protecting each step of the installer. This option is recommended on all installers that are accessible via a public URL but not required.
    Unlocked "Unlocked" means that if your installer is on a public server that anyone can access it. This is a less secure way to run your installer. If you are running the installer very quickly then removing all the installer files, then the chances of exposing it is going to be low depending on your sites access history.

    While it is not required to have a password set it is recommended. If your URL has little to no traffic or has never been the target of an attack then running the installer without a password is going to be relatively safe if ran quickly. However, a password is always a good idea. Also, it is absolutely required and recommended to remove all installer files after installation is completed by logging into the WordPress admin and following the Duplicator prompts.

    Note: Even though the installer has a password protection feature, it should only be used for the short term while the installer is being used. All installer files should and must be removed after the install is completed. Files should not to be left on the server for any long duration of time to prevent any security related issues.

    Step 1 of 4: Deployment

    There are currently several modes that the installer can be in. The mode will be shown at the top of each screen. Below is an overview of the various modes.
    Option Details
    Standard Install This mode indicates that the installer and archive have been placed into an empty directory and the site is ready for a fresh/new redeployment. This is the most common mode and the mode that has been around the longest.
    Standard Install
    Database Only
    This mode indicates that the installer and archive were manually moved or transferred to a location and that only the Database will be installed at this location.
    Overwrite Install This mode indicates that the installer was started in a location that contains an existing site -or- the archive file was imported into an existing site using Duplicator Pro on the destination site (see Duplicator Pro > Tools > Import). In both cases the existing site will be overwritten.
    Overwrite Install
    Database Only
    This mode indicates that the installer was started in a location that contains an existing site -or- the archive file was imported into an existing site using Duplicator Pro on the destination site (see Duplicator Pro > Tools > Import). In both cases the existing site's database will be overwritten.


    The "Extract Archive" screen is separated into four sections:

    Archive

    This is the archive file the installer must use in order to extract the web site files and database. The 'Name' is a unique key that ties both the archive and installer together. The installer needs the archive file name to match the 'Name' value exactly character for character in order for this section to get a pass status.

    If the archive name is ever changed then it should be renamed back to the 'Name' value in order for the installer to properly identify it as part of a complete package. Additional information such as the archive size and the package notes are mentioned in this section.

    Validation

    This section shows the installers system requirements and notices. All requirements must pass in order to proceed to Step 2. Each requirement will show a Pass/Fail status. Notices on the other hand are not required in order to continue with the install.

    Notices are simply checks that will help you identify any possible issues that might occur. If this section shows a Good/Warn for various checks. Click on the title link and read the overview for how to solve the test.

    Multisite pro

    The multisite option allows users with a Pro Business or Gold license to perform additional multi-site tasks. All licenses can backup & migrate standalone sites and full multisite networks. Multisite Plus+ (business and above) adds the ability to install a subsite as a standalone site.

    Options

    The options for step 1 can help better prepare your site should your server need additional settings beyond most general configuration.
    Option Details
    General Options
    Extraction Manual Archive Extraction
    Set the Extraction value to "Manual Archive Extraction" when the archive file has already been manually extracted on the server. This can be done through your hosts control panel such as cPanel or by your host directly. This setting can be helpful if you have a large archive files or are having issues with the installer extracting the file due to timeout issues.

    PHP ZipArchive
    This extraction method will use the PHP ZipArchive code to extract the archive zip file.

    Shell-Exec Unzip
    This extraction method will use the PHP shell_exec to call the system unzip command on the server. This is the default mode that is used if its avail on the server.

    Permissions All Files: Check the 'All Files' check-box and enter in the desired chmod command to recursively set the octal value on all the files being extracted. Typically this value is 644 on most servers and hosts.

    All Directories: Check the 'All Directories' check-box and enter in the desired chmod command to recursively set octal value on all the directories being extracted. Typically this value is 755 on most servers and hosts.
    Advanced Options
    Safe Mode Safe mode is designed to configure the site with specific options at install time to help over come issues that may happen during the install were the site is having issues. These options should only be used if you run into issues after you have tried to run an install.

    Basic: This safe mode option will disable all the plugins at install time. When this option is set you will need to re-enable all plugins after the install has full ran.

    Advanced: This option applies all settings used in basic and will also de-activate and reactivate your theme when logging in for the first time. This options should be used only if the Basic option did not work.
    Config Files When dealing with configuration files (.htaccess, web.config and .user.ini) the installer can apply different modes:

    Create New: This is the default recommended option which will create either a new .htaccess or web.config file. The new file is streamlined to help guarantee no conflicts are created during install. The config files generated with this mode will be simple and basic. The WordFence .user.ini file if present will be removed.

    Restore Original: This option simply renames the htaccess.orig or web.config.orig files to .htaccess or web.config. The *.orig files come from the original web server where the package was built. Please note this option will cause issues with the install process if the configuration files are not properly setup to handle the new server environment. This is an advanced option and should only be used if you know how to properly configure your web servers configuration.

    Additional Notes: Inside the archive.zip will be a copy of the original .htaccess (Apache) or the web.config (IIS) files that were setup with your packaged site. They are both renamed to htaccess.orig and web.config.orig. Using either Create New or Restore Original if any existing config files exist for the extraction process they will be backed up with a .bak extension.

    File Times When the archive is extracted should it show the current date-time or keep the original time it had when it was built. This setting will be applied to all files and directories.
    Logging The level of detail that will be sent to the log file (dup-installer-log_[HASH].txt). The recommend setting for most installs should be 'Light'. Note if you use Debug the amount of data written can be very large. Debug is only recommended for support.


    Notices

    To proceed with the install users must check the checkbox labeled " I have read and accept all terms & notices". This means you accept the term of using the software and are aware of any notices.


    Step 2 of 4: Install Database

    Basic/cPanel:

    There are currently two options you can use to perform the database setup. The "Basic" option requires knowledge about the existing server and on most hosts will require that the database be setup ahead of time. The cPanel option is for hosts that support cPanel Software. This option will automatically show you the existing databases and users on your cPanel server and allow you to create new databases directly from the installer.

    cPanel Login pro

    The cPanel connectivity option is only available for Duplicator Pro.
    Option Details
    Host This should be the primary domain account URL that is associated with your host. Most hosts will require you to register a primary domain name. This should be the URL that you place in the host field. For example if your primary domain name is "mysite.com" then you would enter in "https://mysite.com:2083". The port 2038 is the common port number that cPanel works on. If you do not know your primary domain name please contact your hosting provider or server administrator.
    Username The cPanel username used to login to your cPanel account. This is not the same thing as your WordPress administrator account. If your unsure of this name please contact your hosting provider or server administrator.
    Password The password of the cPanel user
    Troubleshoot Common cPanel Connection Issues:
    - Your host does not use cPanel Software
    - Your host has disabled cPanel API access
    - Your host has configured cPanel to work differently (please contact your host)
    - View a list of valid cPanel Supported Hosts


    Setup

    The database setup options allow you to connect to an existing database or in the case of cPanel connect or create a new database.
    Option Details
    Action Create New Database: Will attempt to create a new database if it does not exist. When using the 'Basic' option this option will not work on many hosting providers as the ability to create new databases is normally locked down. If the database does not exist then you will need to login to your control panel and create the database. If your host supports 'cPanel' then you can use this option to create a new database after logging in via your cPanel account.

    Connect and Remove All Data: This options will DELETE all tables in the database you are connecting to. Please make sure you have backups of all your data before using an portion of the installer, as this option WILL remove all data.

    Connect and Backup Any Existing Data:pro This options will RENAME all tables in the database you are connecting to with a prefix of "".

    Manual SQL Execution:pro This options requires that you manually run your own SQL import to an existing database before running the installer. When this action is selected the dup-database_[hash].sql file found inside the dup-installer folder of the archive.zip file will NOT be ran. The database your connecting to should already be a valid WordPress installed database. This option is viable when you need to run advanced search and replace options on the database.

    Host The name of the host server that the database resides on. Many times this will be 'localhost', however each hosting provider will have it's own naming convention please check with your server administrator or host to valid for sure the name needed. To add a port number just append it to the host i.e. 'localhost:3306'.
    Database The name of the database to which this installation will connect and install the new tables and data into. Some hosts will require a prefix while others do not. Be sure to know exactly how your host requires the database name to be entered.
    User The name of a MySQL database server user. This is special account that has privileges to access a database and can read from or write to that database. This is not the same thing as your WordPress administrator account.
    Password The password of the MySQL database server user.


    Options

    Option Details
    Prefixpro* By default, databases are prefixed with the cPanel account's username (for example, myusername_databasename). However you can ignore this option if your host does not use the default cPanel username prefix schema. Check the 'Ignore cPanel Prefix' and the username prefixes will be ignored. This will still require you to enter in the cPanels required setup prefix if they require one. The checkbox will be set to read-only if your host has disabled prefix settings. Please see your host full requirements when using the cPanel options.
    Legacy When creating a database table, the Mysql version being used may not support the collation type of the Mysql version where the table was created. In this scenario, the installer will fallback to a legacy collation type to try and create the table. This value should only be checked if you receive an error when testing the database.

    For example, if the database was created on MySQL 5.7 and the tables collation type was 'utf8mb4_unicode_520_ci', however your trying to run the installer on an older MySQL 5.5 engine that does not support that type then an error will be thrown. If this option is checked then the legacy setting will try to use 'utf8mb4_unicode_520', then 'utf8mb4', then 'utf8' and so on until it runs out of options.

    For more information about this feature see the online FAQ question titled "What is compatibility mode & 'unknown collation' errors"
    Spacing The process will remove utf8 characters represented as 'xC2' 'xA0' and replace with a uniform space. Use this option if you find strange question marks in you posts
    Mode The MySQL mode option will allow you to set the mode for this session. It is very useful when running into conversion issues. For a full overview please see the MySQL mode documentation specific to your version.
    Charset When the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your databases character set should be.
    Collation When the database is populated from the SQL script it will use this value as part of its connection. Only change this value if you know what your databases collation set should be.
    *cPanel Only Option

    Validation

    Testing the database connection is important and can help isolate possible issues that may arise with database version and compatibility issues.
    Option Details
    Test
    Database
    The 'Test Database' button will help validate if the connection parameters are correct for this server and help with details about any issues that may arise.
    Troubleshoot Common Database Connection Issues:
    - Double check case sensitive values 'User', 'Password' & the 'Database Name'
    - Validate the database and database user exist on this server
    - Check if the database user has the correct permission levels to this database
    - The host 'localhost' may not work on all hosting providers
    - Contact your hosting provider for the exact required parameters
    - Visit the online resources 'Common FAQ page'



    Step 3 of 4: Update Data

    New Settings

    These are the new values (URL, Path and Title) you can update for the new location at which your site will be installed at.

    Replace pro

    This section will allow you to add as many custom search and replace items that you would like. For example you can search for other URLs to replace. Please use high caution when using this feature as it can have unintended consequences as it will search the entire database. It is recommended to only use highly unique items such as full URL or file paths with this option.

    Options

    Option Details
    New Admin Account
    Username A new WordPress username to create. This will create a new WordPress administrator account. Please note that usernames are not changeable from the within the UI.
    Password The new password for the new user. Must be at least 6 characters long.
    Scan Options
    Cleanup pro The checkbox labeled Remove schedules & storage endpoints will empty the Duplicator schedule and storage settings. This is recommended to keep enabled so that you do not have unwanted schedules and storage options enabled.
    Old URL The old URL of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons
    Old Path The old path of the original values that the package was created with. These values should not be changed, unless you know the underlying reasons
    Site URL For details see WordPress Site URL & Alternate Directory. If you're not sure about this value then leave it the same as the new settings URL.
    Scan Tables Select the tables to be updated. This process will update all of the 'Old Settings' with the 'New Settings'. Hold down the 'ctrl key' to select/deselect multiple.
    Activate Plugins These plug-ins are the plug-ins that were activated when the package was created and represent the plug-ins that will be activated after the install.
    Full Search Full search forces a scan of every single cell in the database. If it is not checked then only text based columns are searched which makes the update process much faster. Use this option if you have issues with data not updating correctly.
    Post GUID If your moving a site keep this value checked. For more details see the notes on GUIDS. Changing values in the posts table GUID column can change RSS readers to evaluate that the posts are new and may show them in feeds again.
    WP-Config File
    Config SSL Turn off SSL support for WordPress. This sets FORCE_SSL_ADMIN in your wp-config file to false if true, otherwise it will create the setting if not set. The "Enforce on Login" will turn off SSL support for WordPress Logins.
    Config Cache Turn off Cache support for WordPress. This sets WP_CACHE in your wp-config file to false if true, otherwise it will create the setting if not set. The "Keep Home Path" sets WPCACHEHOME in your wp-config file to nothing if true, otherwise nothing is changed.



    Step 4 of 4: Test Site

    Final Steps

    Review Install Report
    The install report is designed to give you a synopsis of the possible errors and warnings that may exist after the installation is completed.

    Test Site
    After the install is complete run through your entire site and test all pages and posts.

    Final Security Cleanup
    When completed with the installation please delete all installation files. Leaving these files on your server can impose a security risk! You can remove all the security files by logging into your WordPress admin and following the remove notification links. Be sure all these files are removed. Optionally it is also recommended to remove the archive.zip file.
    • installer.php
    • installer-backup.php
    • dup-installer-data_[HASH].sql
    • dup-database_[HASH].sql
    • dup-installer-log_[HASH].txt
    • [HASH]_archive.zip


    Troubleshooting Tips

    Common Quick Fix Issues:
    • Use an approved hosting provider
    • Validate directory and file permissions (see below)
    • Validate web server configuration file (see below)
    • Clear your browsers cache
    • Deactivate and reactivate all plugins
    • Resave a plugins settings if it reports errors
    • Make sure your root directory is empty
    Permissions:
    Not all operating systems are alike. Therefore, when you move a package (zip file) from one location to another the file and directory permissions may not always stick. If this is the case then check your WordPress directories and make sure it's permissions are set to 755. For files make sure the permissions are set to 644 (this does not apply to windows servers). Also pay attention to the owner/group attributes. For a full overview of the correct file changes see the WordPress permissions codex

    Web server configuration files:
    For Apache web server the root .htaccess file was copied to htaccess.orig. A new stripped down .htaccess file was created to help simplify access issues. For IIS web server the web.config file was copied to web.config.orig, however no new web.config file was created. If you have not altered this file manually then resaving your permalinks and resaving your plugins should resolve most all changes that were made to the root web configuration file. If your still experiencing issues then open the .orig file and do a compare to see what changes need to be made.

    Plugin Notes:
    It's impossible to know how all 3rd party plugins function. The Duplicator attempts to fix the new install URL for settings stored in the WordPress options table. Please validate that all plugins retained there settings after installing. If you experience issues try to bulk deactivate all plugins then bulk reactivate them on your new duplicated site. If you run into issues were a plugin does not retain its data then try to resave the plugins settings.

    Cache Systems:
    Any type of cache system such as Super Cache, W3 Cache, etc. should be emptied before you create a package. Another alternative is to include the cache directory in the directory exclusion path list found in the options dialog. Including a directory such as \pathtowordpress\wp-content\w3tc\ (the w3 Total Cache directory) will exclude this directory from being packaged. In is highly recommended to always perform a cache empty when you first fire up your new site even if you excluded your cache directory.

    Trying Again:
    If you need to retry and reinstall this package you can easily run the process again by deleting all files except the installer and package file and then browse to the installer again.

    Additional Notes:
    If you have made changes to your PHP files directly this might have an impact on your duplicated site. Be sure all changes made will correspond to the sites new location. Only the package (zip file) and the installer (php file) should be in the directory where you are installing the site. Please read through our knowledge base before submitting any issues. If you have a large log file that needs evaluated please email the file, or attach it to a help ticket.

    For additional help please visit the online resources