PageRenderTime 85ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 3ms

/wp-snapshots/511a4b30d372c5933_20130212_wastark_installer.php

https://bitbucket.org/nathancorbier/wastark.com
PHP | 3222 lines | 2522 code | 365 blank | 335 comment | 258 complexity | 022e0d5132ab95cfeae8e25c4fddf91e MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*
  3. Copyright 2011-12 Cory Lamle lifeinthegrid.com
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License, version 2, as
  6. published by the Free Software Foundation.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  14. SOURCE CONTRIBUTORS:
  15. Gaurav Aggarwal
  16. David Coveney of Interconnect IT Ltd
  17. https://github.com/interconnectit/Search-Replace-DB/
  18. */
  19. //DOWNLOAD ONLY:
  20. if ( isset($_GET['get']) && file_exists($_GET['file'])) {
  21. if (strstr($_GET['file'], '_installer.php') || strstr($_GET['file'], 'installer.rescue.php')) {
  22. header('Content-Description: File Transfer');
  23. header('Content-Type: application/octet-stream');
  24. header('Content-Disposition: attachment; filename=installer.php');
  25. header('Content-Transfer-Encoding: binary');
  26. header('Expires: 0');
  27. header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  28. header('Pragma: public');
  29. header('Content-Length: ' . filesize($_GET['file']));
  30. @ob_clean();
  31. @flush();
  32. if (@readfile($_GET['file']) == false) {
  33. $data = file_get_contents($_GET['file']);
  34. if ($data == false) {
  35. die("Unable to read installer file. The server currently has readfile and file_get_contents disabled on this server. Please contact your server admin to remove this restriction");
  36. } else {
  37. print $data;
  38. }
  39. }
  40. exit;
  41. } else {
  42. header("HTML/1.1 404 Not Found", true, 404);
  43. header("Status: 404 Not Found");
  44. }
  45. }
  46. //Prevent Access from rovers or direct browsing in snapshop directory
  47. if (file_exists('dtoken.php')) {
  48. exit;
  49. }
  50. ?>
  51. <?php if ( false ) :?>
  52. <!DOCTYPE html>
  53. <html>
  54. <head>
  55. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  56. <title>Error: PHP is not running</title>
  57. </head>
  58. <body>
  59. <h2>Error: PHP is not running</h2>
  60. <p>Duplicator requires that your web server is running PHP. Your server does not have PHP installed, or PHP is turned off.</p>
  61. </body>
  62. </html>
  63. <?php endif; ?>
  64. <?php
  65. /* ==============================================================================================
  66. ADVANCED FEATURES - Allows admins to perform aditional logic on the import.
  67. $GLOBALS['TABLES_SKIP_COLS']
  68. Add Known column names of tables you don't want the search and replace logic to run on.
  69. $GLOBALS['REPLACE_LIST']
  70. Add additional search and replace items add list here
  71. Example: array(array('search'=> '/html/oldpath/images', 'replace'=> '/html/newpath/images'));
  72. ================================================================================================= */
  73. $GLOBALS['FW_TABLEPREFIX'] = 'wp_';
  74. $GLOBALS['FW_URL_OLD'] = 'http://wastark.com';
  75. $GLOBALS['FW_URL_NEW'] = '';
  76. $GLOBALS['FW_PACKAGE_NAME'] = '511a4b30d372c5933_20130212_wastark_package.zip';
  77. $GLOBALS['FW_SECURE_NAME'] = '511a4b30d372c5933_20130212_wastark';
  78. $GLOBALS['FW_DBHOST'] = 'localhost';
  79. $GLOBALS['FW_DBNAME'] = '';
  80. $GLOBALS['FW_DBUSER'] = '';
  81. $GLOBALS['FW_BLOGNAME'] = 'W. A. Stark';
  82. $GLOBALS['FW_RESCUE_FLAG'] = '';
  83. $GLOBALS['FW_WPROOT'] = '/home/starehcf/public_html/wastark.com/';
  84. //DATABASE SETUP: all time in seconds
  85. $GLOBALS['DB_MAX_TIME'] = 5000;
  86. $GLOBALS['DB_MAX_PACKETS'] = 268435456;
  87. ini_set('mysql.connect_timeout', '5000');
  88. //PHP SETUP: all time in seconds
  89. ini_set('memory_limit', '5000M');
  90. ini_set("max_execution_time", '5000');
  91. ini_set("max_input_time", '5000');
  92. ini_set('default_socket_timeout', '5000');
  93. @set_time_limit(0);
  94. $GLOBALS['DBCHARSET_DEFAULT'] = 'utf8';
  95. $GLOBALS['DBCOLLATE_DEFAULT'] = 'utf8_general_ci';
  96. //UPDATE TABLE SETTINGS
  97. $GLOBALS['TABLES_SKIP_COLS'] = array('');
  98. $GLOBALS['REPLACE_LIST'] = array();
  99. /* ================================================================================================
  100. END ADVANCED FEATURES: Do not edit below here.
  101. =================================================================================================== */
  102. //CONSTANTS
  103. define("DUPLICATOR_SSDIR_NAME", 'wp-snapshots'); //This should match DUPLICATOR_SSDIR_NAME in duplicator.php
  104. //GLOBALS
  105. $GLOBALS['DUPLICATOR_INSTALLER_VERSION'] = '0.4.2';
  106. $GLOBALS["SQL_FILE_NAME"] = "installer-data.sql";
  107. $GLOBALS["LOG_FILE_NAME"] = "installer-log.txt";
  108. $GLOBALS['SEPERATOR1'] = str_repeat("********", 10);
  109. $GLOBALS['LOGGING'] = isset($_POST['logging']) ? $_POST['logging'] : 1;
  110. $GLOBALS['CURRENT_ROOT_PATH'] = dirname(__FILE__);
  111. $GLOBALS['CHOWN_ROOT_PATH'] = @chmod("{$GLOBALS['CURRENT_ROOT_PATH']}", 0755);
  112. $GLOBALS['CHOWN_LOG_PATH'] = @chmod("{$GLOBALS['CURRENT_ROOT_PATH']}/{$GLOBALS['LOG_FILE_NAME']}", 0644);
  113. $GLOBALS['URL_SSL'] = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? true : false;
  114. $GLOBALS['URL_PATH'] = ($GLOBALS['URL_SSL'])
  115. ? "https://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}"
  116. : "http://{$_SERVER['SERVER_NAME']}{$_SERVER['REQUEST_URI']}";
  117. //SHARED POST PARMS
  118. $_POST['action_step'] = isset($_POST['action_step']) ? $_POST['action_step'] : "0";
  119. $_POST['dbhost'] = isset($_POST['dbhost']) ? trim($_POST['dbhost']) : null;
  120. $_POST['dbuser'] = isset($_POST['dbuser']) ? trim($_POST['dbuser']) : null;
  121. $_POST['dbpass'] = isset($_POST['dbpass']) ? trim($_POST['dbpass']) : null;
  122. $_POST['dbname'] = isset($_POST['dbname']) ? trim($_POST['dbname']) : null;
  123. $_POST['dbcharset'] = isset($_POST['dbcharset']) ? trim($_POST['dbcharset']) : $GLOBALS['DBCHARSET_DEFAULT'];
  124. $_POST['dbcollate'] = isset($_POST['dbcollate']) ? trim($_POST['dbcollate']) : $GLOBALS['DBCOLLATE_DEFAULT'];
  125. //Restart log if user starts from step 1
  126. if ($_POST['action_step'] == 1) {
  127. $GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_NAME'], "w+");
  128. } else {
  129. $GLOBALS['LOG_FILE_HANDLE'] = @fopen($GLOBALS['LOG_FILE_NAME'], "a+");
  130. }
  131. ?>
  132. <?php
  133. /** ******************************************************
  134. * CLASS::DupUtil
  135. * Various Static Utility methods for working with the installer */
  136. class DupUtil {
  137. /** METHOD: LOG
  138. * Used to write debug info to the output page
  139. * @param string $msg A a message that belongs to a unique title block
  140. * @param int $loglevel Log level
  141. * @param bool $newline Insert a newline
  142. */
  143. static public function log ($msg, $logging = 1) {
  144. if ($logging <= $GLOBALS["LOGGING"] ) {
  145. @fwrite($GLOBALS["LOG_FILE_HANDLE"], "{$msg}\n");
  146. }
  147. }
  148. /** METHOD: GET_MICROTIME
  149. * Get current microtime as a float. Can be used for simple profiling.
  150. */
  151. static public function get_microtime() {
  152. return microtime(true);
  153. }
  154. /** METHOD: ELAPSED_TIME
  155. * Return a string with the elapsed time.
  156. * Order of $end and $start can be switched.
  157. */
  158. static public function elapsed_time($end, $start) {
  159. return sprintf("%.4f sec.", abs($end - $start));
  160. }
  161. /** METHOD: ESC_HTML_ATTR
  162. * @param string $string Thing that needs escaping
  163. * @param bool $echo Do we echo or return?
  164. * @return string Escaped string.
  165. */
  166. static public function esc_html_attr( $string = '', $echo = false ) {
  167. $output = htmlentities( $string, ENT_QUOTES, 'UTF-8' );
  168. if ( $echo )
  169. echo $output;
  170. else
  171. return $output;
  172. }
  173. /** METHOD: TABLE_COUNT
  174. * Count the tables in a given database
  175. * @param string $_POST['dbname'] Database to count tables in
  176. */
  177. static public function dbtable_count($conn, $dbname) {
  178. $res = mysqli_query($conn, "SELECT COUNT(*) AS count FROM information_schema.tables WHERE table_schema = '{$dbname}' ");
  179. $row = mysqli_fetch_row($res);
  180. return is_null($row) ? 0 : $row[0];
  181. }
  182. /** METHOD: TABLE_ROW_COUNT
  183. * Returns the table count
  184. * @param string $conn A valid link resource
  185. * @param string $table_name A valid table name
  186. */
  187. static public function table_row_count($conn, $table_name) {
  188. $total = mysqli_query($conn, "SELECT COUNT(*) FROM `$table_name`");
  189. if ($total) {
  190. $total = @mysqli_fetch_array($total);
  191. return $total[0];
  192. } else {
  193. return 0;
  194. }
  195. }
  196. /** METHOD: ADD_ENDING_SLASH
  197. * Adds a slash to the end of a path
  198. * @param string $path A path
  199. */
  200. static public function add_slash($path){
  201. $last_char = substr($path, strlen($path)-1, 1);
  202. if ($last_char != '/' ) {
  203. $path .= '/';
  204. }
  205. return $path;
  206. }
  207. /** METHOD: SET_SAFE_PATH
  208. * Makes path safe for any OS
  209. * Paths should ALWAYS READ be "/"
  210. * uni: /home/path/file.xt
  211. * win: D:/home/path/file.txt
  212. * @param string $path The path to make safe
  213. */
  214. static public function set_safe_path($path) {
  215. return str_replace("\\", "/", $path);
  216. }
  217. static public function unset_safe_path($path) {
  218. return str_replace("/", "\\", $path);
  219. }
  220. /** METHOD: FCGI_FLUSH
  221. * PHP_SAPI for fcgi requires a data flush of at least 256
  222. * bytes every 40 seconds or else it forces a script hault
  223. */
  224. static public function fcgi_flush() {
  225. echo(str_repeat(' ',256));
  226. @flush();
  227. }
  228. /** METHOD: COPY_FILE
  229. * A safe method used to copy larger files
  230. * @param string $source The path to the file being copied
  231. * @param string $destination The path to the file being made
  232. */
  233. static public function copy_file($source, $destination) {
  234. $sp = fopen($source, 'r');
  235. $op = fopen($destination, 'w');
  236. while (!feof($sp)) {
  237. $buffer = fread($sp, 512); // use a buffer of 512 bytes
  238. fwrite($op, $buffer);
  239. }
  240. // close handles
  241. fclose($op);
  242. fclose($sp);
  243. }
  244. /** METHOD: string_has_value
  245. * Finds a string in a file and returns true if found
  246. * @param array $list A list of strings to search for
  247. * @param string $haystack The string to search in
  248. */
  249. static public function string_has_value($list, $file) {
  250. foreach($list as $var) {
  251. if (strstr($file, $var) !== false ) {
  252. return true;
  253. }
  254. }
  255. return false;
  256. }
  257. /** METHOD: get_active_plugins
  258. * Returns the active plugins for a package
  259. * @param conn $dbh A database connection handle
  260. * @return array $list A list of active plugins
  261. */
  262. static public function get_active_plugins($dbh) {
  263. $query = @mysqli_query($dbh, "SELECT option_value FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE option_name = 'active_plugins' ");
  264. if ($query) {
  265. $row = mysqli_fetch_array($query);
  266. $all_plugins = unserialize($row[0]);
  267. if (is_array($all_plugins)) {
  268. return $all_plugins;
  269. }
  270. }
  271. return array();
  272. }
  273. /** METHOD: get_database_tables
  274. * Returns the tables for a database
  275. * @param conn $dbh A database connection handle
  276. * @return array $list A list of all table names
  277. */
  278. static public function get_database_tables($dbh) {
  279. $query = @mysqli_query($dbh, 'SHOW TABLES');
  280. if ($query ) {
  281. while ($table = mysqli_fetch_array($query )) {
  282. $all_tables[] = $table[ 0 ];
  283. }
  284. if (is_array($all_tables)) {
  285. return $all_tables;
  286. }
  287. }
  288. return array();
  289. }
  290. /**
  291. * MySQL database version number
  292. * @param conn $dbh Database connection handle
  293. * @return false|string false on failure, version number on success
  294. */
  295. static public function mysql_version($dbh) {
  296. if (function_exists( 'mysqli_get_server_info' ) ) {
  297. return preg_replace( '/[^0-9.].*/', '', mysqli_get_server_info( $dbh ) );
  298. } else {
  299. return 0;
  300. }
  301. }
  302. /**
  303. * MySQL server variable
  304. * @param conn $dbh Database connection handle
  305. * @return string the server variable to query for
  306. */
  307. static public function mysql_variable_value($dbh, $variable) {
  308. $result = @mysqli_query($dbh, "SHOW VARIABLES LIKE '{$variable}'");
  309. $row = mysqli_fetch_array($result);
  310. @mysqli_free_result($result);
  311. return isset($row[1]) ? $row[1] : null;
  312. }
  313. /**
  314. * Determine if a MySQL database supports a particular feature
  315. * @param conn $dbh Database connection handle
  316. * @param string $feature the feature to check for
  317. * @return bool
  318. */
  319. static public function mysql_has_ability($dbh, $feature) {
  320. $version = self::mysql_version($dbh);
  321. switch ( strtolower( $feature ) ) {
  322. case 'collation' :
  323. case 'group_concat' :
  324. case 'subqueries' :
  325. return version_compare( $version, '4.1', '>=' );
  326. case 'set_charset' :
  327. return version_compare($version, '5.0.7', '>=');
  328. };
  329. return false;
  330. }
  331. /**
  332. * Sets the MySQL connection's character set.
  333. * @param resource $dbh The resource given by mysqli_connect
  334. * @param string $charset The character set (optional)
  335. * @param string $collate The collation (optional)
  336. */
  337. static public function mysql_set_charset($dbh, $charset = null, $collate = null) {
  338. $charset = ( !isset($charset) ) ? $GLOBALS['DBCHARSET_DEFAULT'] : $charset;
  339. $collate = ( !isset($collate) ) ? $GLOBALS['DBCOLLATE_DEFAULT'] : $collate;
  340. if ( self::mysql_has_ability($dbh, 'collation') && !empty( $charset ) ) {
  341. if ( function_exists( 'mysqli_set_charset' ) && self::mysql_has_ability($dbh, 'set_charset') ) {
  342. return mysqli_set_charset($dbh, $charset);
  343. } else {
  344. $sql = " SET NAMES {$charset}";
  345. if ( ! empty( $collate ) )
  346. $sql .= " COLLATE {$collate}";
  347. return mysqli_query($dbh, $sql);
  348. }
  349. }
  350. }
  351. /**
  352. * READABLE_BYTESIZE
  353. * Display human readable byte sizes
  354. * @param string $size The size in bytes
  355. */
  356. static public function readable_bytesize($size) {
  357. try {
  358. $units = array('B', 'KB', 'MB', 'GB', 'TB');
  359. for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
  360. return round($size, 2).$units[$i];
  361. } catch (Exception $e) {
  362. return "n/a";
  363. }
  364. }
  365. }
  366. ?>
  367. <?php
  368. if (isset($_POST['action_ajax'])) {
  369. switch ( $_POST['action_ajax'] ) {
  370. case "1" :?> <?php
  371. //====================================================================================================
  372. //PRECHECKS - Validate and make sure to have a clean enviroment
  373. //====================================================================================================
  374. define('MSG_ERR_CONFIG_FOUND', '<div class="error"><b style="color:#C16C1D;">INSTALL ERROR!</b><br/> A wp-config.php already exists in this location. This error prevents users from accidentally overwriting the wrong directories contents. You have two options: <ul><li>Empty this root directory except for the package and installer and try again.</li><li>Delete just the wp-config.php file and try again. This will over-write all other files in the directory.</li></ul></div>');
  375. define('MSG_ERR_ZIPNOTFOUND', '<div class="error"><b style="color:#C16C1D;">INSTALL ERROR!</b><br/> The packaged zip file was not found. Be sure the zip package is in the same directory as the installer file. 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. </div>');
  376. define('MSG_ERR_ZIPEXTRACTION', '<div class="error"><b style="color:#C16C1D;">INSTALL ERROR!</b><br/> Failed in extracting zip file. Please be sure the archive is completely downloaded. Try to extract the archive manually to make sure the file is not corrupted. </div>');
  377. define('MSG_ERR_ZIPMANUAL', '<div class="error"><b style="color:#C16C1D;">INSTALL ERROR!</b><br/> When choosing manual package extraction, the contents of the package must already be extracted and the wp-config.php and database.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 database.sql files are present. </div>');
  378. define('MSG_ERR_MAKELOG', '<div class="error"><b style="color:#C16C1D;">INSTALL ERROR!</b><br/> PHP is having issues writing to the log file <b>' . DupUtil::set_safe_path($GLOBALS['CURRENT_ROOT_PATH']) . '\installer-log.txt .</b> 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. </div>');
  379. define('MSG_FAIL_MYSQLI_SUPPORT', '<div class="error"><b style="color:#B80000;">PHP MYSQLI NOT ENABLED!</b><br/>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</div>');
  380. define('MSG_FAIL_DBCONNECT', '<div class="error"><b style="color:#B80000;">DATABASE CONNECTION FAILED!</b><br/></div>');
  381. define('MSG_FAIL_DBCONNECT_CREATE', '<div class="error"><b style="color:#B80000;">DATABASE CREATION FAILURE!</b><br/> Unable to create database "%s".<br/> Please try creating the database manually to proceed with installation</div>');
  382. define('MSG_FAIL_DBTRYCLEAN', '<div class="error"><b style="color:#C16C1D;">DATABASE CREATION FAILURE!</b><br/> Unable to remove all tables from database "%s".<br/> Please remove all tables from this database and try the installation again.</div>');
  383. define('MSG_ERR_DBCREATE', '<div class="error"><b style="color:#C16C1D;">INSTALL ERROR!</b><br/> The database "%s" does not exists.<br/> Enable allow database creation to proceed with the installation.</div>');
  384. define('MSG_ERR_DBCLEANCHECK', '<div class="error"><b style="color:#C16C1D;">INSTALL ERROR!</b><br/> The database "%s" has %s tables. The Duplicator only works with an EMPTY database. Enable the "Table Removal" checkbox to delete all tables and proceed with installation. Please backup all your data before proceeding!<br/><br/> Some hosting providers do not allow table removal from scripts like the Duplicator. 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. </div>');
  385. define('MSG_OK_DBPASS', '<div class="error"><b style="color:#006E32;">CONNECTION SUCCESSFUL!</b><br/> With the parameters provided.</div>');
  386. //POST PARAMS
  387. $_POST['dbmake'] = (isset($_POST['dbmake']) && $_POST['dbmake'] == '1') ? true : false;
  388. $_POST['dbclean'] = (isset($_POST['dbclean']) && $_POST['dbclean'] == '1') ? true : false;
  389. $_POST['dbnbsp'] = (isset($_POST['dbnbsp']) && $_POST['dbnbsp'] == '1') ? true : false;
  390. $_POST['no_ssl'] = (isset($_POST['no_ssl']) && $_POST['no_ssl'] == '1') ? true : false;
  391. $_POST['package_name'] = isset($_POST['package_name']) ? $_POST['package_name'] : null;
  392. $_POST['zip_manual'] = (isset($_POST['zip_manual']) && $_POST['zip_manual'] == '1') ? true : false;
  393. //LOGGING
  394. $POST_LOG = $_POST;
  395. unset($POST_LOG['dbpass']);
  396. ksort($POST_LOG);
  397. //PAGE VARS
  398. $back_link = "<div class='tryagain'><a href='javascript:void(0)' onclick='Duplicator.hideErrorResult()' style='color:#444; font-weight:bold'>&laquo; Try Again</a></div>";
  399. $root_path = DupUtil::set_safe_path($GLOBALS['CURRENT_ROOT_PATH']);
  400. $package_path = "{$root_path}/{$_POST['package_name']}";
  401. $package_size = @filesize($package_path);
  402. $ajax1_start = DupUtil::get_microtime();
  403. $JSON = array();
  404. $JSON['pass'] = 0;
  405. //===============================
  406. //DATABASE TEST CONNECTION
  407. //===============================
  408. if (isset($_GET['dbtest'])) {
  409. if (! is_null($_POST['dbname'])) {
  410. $dbh = @mysqli_connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname']);
  411. } else {
  412. $dbh = @mysqli_connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass']);
  413. }
  414. if (! $dbh) {
  415. die(MSG_FAIL_DBCONNECT . mysqli_connect_error());
  416. }
  417. if (! $_POST['dbmake']) {
  418. mysqli_select_db($dbh, $_POST['dbname']) or die(sprintf(MSG_ERR_DBCREATE, $_POST['dbname']));
  419. }
  420. if (! $_POST['dbclean']) {
  421. $tblcount = DupUtil::dbtable_count($dbh, $_POST['dbname']);
  422. if ($tblcount > 0) {
  423. die(sprintf(MSG_ERR_DBCLEANCHECK, $_POST['dbname'], $tblcount ));
  424. }
  425. }
  426. die(MSG_OK_DBPASS);
  427. }
  428. //===============================
  429. //VALIDATION MESSAGES
  430. //===============================
  431. //MSG_ERR_MAKELOG
  432. ($GLOBALS['LOG_FILE_HANDLE'] != false) or die(MSG_ERR_MAKELOG . $back_link);
  433. //MSG_FAIL_MYSQLI_SUPPORT
  434. function_exists('mysqli_connect') or die(MSG_FAIL_MYSQLI_SUPPORT);
  435. //MSG_FAIL_DBCONNECT
  436. $dbh = @mysqli_connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass']);
  437. ($dbh) or die(MSG_FAIL_DBCONNECT . mysqli_connect_error() . $back_link);
  438. if (! $_POST['dbmake']) {
  439. mysqli_select_db($dbh, $_POST['dbname']) or die(sprintf(MSG_ERR_DBCREATE, $_POST['dbname']) . $back_link);
  440. }
  441. //MSG_ERR_DBCLEANCHECK
  442. if (! $_POST['dbclean']) {
  443. $tblcount = DupUtil::dbtable_count($dbh, $_POST['dbname']);
  444. if ($tblcount > 0) {
  445. die(sprintf(MSG_ERR_DBCLEANCHECK, $_POST['dbname'], $tblcount ) . $back_link);
  446. }
  447. }
  448. //MSG_ERR_ZIPMANUAL
  449. if ($_POST['zip_manual']) {
  450. if (! file_exists("wp-config.php") && ! file_exists("database.sql")) {
  451. die(MSG_ERR_ZIPMANUAL . $back_link);
  452. }
  453. } else {
  454. //MSG_ERR_CONFIG_FOUND
  455. (! file_exists('wp-config.php')) or die(MSG_ERR_CONFIG_FOUND . $back_link);
  456. //MSG_ERR_ZIPNOTFOUND
  457. (is_readable("{$package_path}")) or die(MSG_ERR_ZIPNOTFOUND . $back_link);
  458. }
  459. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  460. DupUtil::log('DUPLICATOR INSTALL-LOG');
  461. DupUtil::log('STEP1 START @ ' . @date('h:i:s') );
  462. DupUtil::log('NOTICE: Do not post to public sites or forums');
  463. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  464. DupUtil::log("VERSION:\t{$GLOBALS['DUPLICATOR_INSTALLER_VERSION']}");
  465. DupUtil::log("PHP:\t\t" . phpversion());
  466. DupUtil::log("PHP SAPI:\t" . php_sapi_name());
  467. DupUtil::log("ZIPARCHIVE:\t" . var_export(class_exists('ZipArchive'), true));
  468. DupUtil::log("SERVER:\t\t{$_SERVER['SERVER_SOFTWARE']}");
  469. DupUtil::log("DOC ROOT:\t{$root_path}");
  470. DupUtil::log("DOC ROOT 755:\t" . var_export($GLOBALS['CHOWN_ROOT_PATH'], true));
  471. DupUtil::log("LOG FILE 644:\t" . var_export($GLOBALS['CHOWN_LOG_PATH'], true));
  472. DupUtil::log("BUILD NAME:\t{$GLOBALS['FW_SECURE_NAME']}");
  473. DupUtil::log("REQUEST URL:\t{$GLOBALS['URL_PATH']}");
  474. DupUtil::log("--------------------------------------");
  475. DupUtil::log("POST DATA");
  476. DupUtil::log("--------------------------------------");
  477. DupUtil::log(print_r($POST_LOG, true));
  478. //====================================================================================================
  479. //UNZIP & FILE SETUP - Extract the zip file and prep files
  480. //====================================================================================================
  481. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  482. DupUtil::log('UNZIP & FILE SETUP');
  483. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  484. DupUtil::log("PACKAGE:\t" . $_POST['package_name'] );
  485. DupUtil::log("SIZE:\t\t" . DupUtil::readable_bytesize(@filesize($_POST['package_name'])));
  486. $zip_start = DupUtil::get_microtime();
  487. if ($_POST['zip_manual']) {
  488. DupUtil::log("\n-package extraction is in manual mode-\n");
  489. } else {
  490. if ($GLOBALS['FW_PACKAGE_NAME'] != $_POST['package_name']) {
  491. DupUtil::log("WARNING: This Package Set may be incompatible! \nBelow is a summary of the package this installer was built with and the package used. \nTo guarantee accuracy make sure the installer and package match. For more details see the online FAQs. \ncreated with: {$GLOBALS['FW_PACKAGE_NAME']} \nprocessed with: {$_POST['package_name']} \n");
  492. }
  493. $target = $root_path;
  494. $zip = new ZipArchive();
  495. if ($zip->open($_POST['package_name']) === TRUE) {
  496. @$zip->extractTo($target);
  497. DupUtil::log("INFORMATION:\t" . print_r($zip, true));
  498. $close_response = $zip->close();
  499. DupUtil::log("ZIP CLOSE: " . var_export($close_response, true));
  500. } else {
  501. die(MSG_ERR_ZIPEXTRACTION . $back_link );
  502. }
  503. $zip = null;
  504. }
  505. //===============================
  506. //SCRIPTS: wp-config/database.sql
  507. //===============================
  508. //WP-CONFIG
  509. $patterns = array("/'DB_NAME',\s*'.*?'/",
  510. "/'DB_USER',\s*'.*?'/",
  511. "/'DB_PASSWORD',\s*'.*?'/",
  512. "/'DB_HOST',\s*'.*?'/");
  513. $replace = array("'DB_NAME', " . '\''.$_POST['dbname'].'\'',
  514. "'DB_USER', " . '\''.$_POST['dbuser'].'\'',
  515. "'DB_PASSWORD', " . '\''.$_POST['dbpass'].'\'',
  516. "'DB_HOST', " . '\''.$_POST['dbhost'].'\'');
  517. if ($_POST['no_ssl']) {
  518. array_push($patterns, "/'FORCE_SSL_ADMIN',\s*true/");
  519. array_push($replace, "'FORCE_SSL_ADMIN', false");
  520. }
  521. $wpconfig = @file_get_contents('wp-config.php', true);
  522. $wpconfig = preg_replace($patterns, $replace, $wpconfig);
  523. file_put_contents('wp-config.php', $wpconfig);
  524. $wpconfig = null;
  525. //DATABASE SCRIPT
  526. @chmod("{$root_path}/database.sql", 0777);
  527. $sql_file = @file_get_contents('database.sql', true);
  528. if ($sql_file == false || strlen($sql_file) < 10) {
  529. $sql_file = file_get_contents('installer-data.sql', true);
  530. if ($sql_file == false || strlen($sql_file) < 10) {
  531. DupUtil::log("ERROR: Unable to read from the extracted database.sql file .\nValidate the permissions and/or group-owner rights on directory '{$root_path}'\n");
  532. }
  533. }
  534. //Complex Subject See: http://webcollab.sourceforge.net/unicode.html
  535. //Removes invalid space characters
  536. if ($_POST['dbnbsp']) {
  537. DupUtil::log("ran fix non-breaking space characters\n" );
  538. $sql_file = preg_replace('/\xC2\xA0/',' ',$sql_file);
  539. }
  540. //Write new contents to install-data.sql
  541. @chmod($sql_result_file_path, 0777);
  542. file_put_contents($GLOBALS['SQL_FILE_NAME'], $sql_file);
  543. $sql_result_file_data = explode(";\n", $sql_file);
  544. $sql_result_file_length = count($sql_result_file_data);
  545. $sql_result_file_path = "{$root_path}/{$GLOBALS['SQL_FILE_NAME']}";
  546. $sql_file = null;
  547. if (! is_readable($sql_result_file_path) || filesize($sql_result_file_path) == 0) {
  548. DupUtil::log("ERROR: Unable to create new sql file {$GLOBALS['SQL_FILE_NAME']}.\nValidate the permissions and/or group-owner rights on directory '{$root_path}' and file '{$GLOBALS['SQL_FILE_NAME']}'\n");
  549. }
  550. DupUtil::log("UPDATED SCRIPTS:");
  551. DupUtil::log("\tsql file: '{$sql_result_file_path}'");
  552. DupUtil::log("\twp-config: '{$root_path}/wp-config.php'");
  553. $zip_end = DupUtil::get_microtime();
  554. DupUtil::log("\nSECTION RUNTIME: " . DupUtil::elapsed_time($zip_end, $zip_start));
  555. DupUtil::log("\n");
  556. DupUtil::fcgi_flush();
  557. //====================================================================================================
  558. //DATABASE ROUTINES
  559. //====================================================================================================
  560. @mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}");
  561. @mysqli_query($dbh, "SET max_allowed_packet = {$GLOBALS['DB_MAX_PACKETS']}");
  562. DupUtil::mysql_set_charset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);
  563. //Set defaults incase the variable could not be read
  564. $dbvar_maxtime = DupUtil::mysql_variable_value($dbh, 'wait_timeout');
  565. $dbvar_maxpacks = DupUtil::mysql_variable_value($dbh, 'max_allowed_packet');
  566. $dbvar_maxtime = is_null($dbvar_maxtime) ? 300 : $dbvar_maxtime;
  567. $dbvar_maxpacks = is_null($dbvar_maxpacks) ? 1048576 : $dbvar_maxpacks;
  568. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  569. DupUtil::log('DATABASE-ROUTINES');
  570. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  571. DupUtil::log("--------------------------------------");
  572. DupUtil::log("SERVER ENVIROMENT");
  573. DupUtil::log("--------------------------------------");
  574. DupUtil::log("MYSQL VERSION:\t" . mysqli_get_server_info($dbh));
  575. DupUtil::log("TIMEOUT:\t{$dbvar_maxtime}");
  576. DupUtil::log("MAXPACK:\t{$dbvar_maxpacks}");
  577. //CREATE DB
  578. if ($_POST['dbmake']) {
  579. mysqli_query($dbh, "CREATE DATABASE IF NOT EXISTS `{$_POST['dbname']}`");
  580. mysqli_select_db($dbh, $_POST['dbname'])
  581. or die(sprintf(MSG_FAIL_DBCONNECT_CREATE, $_POST['dbname']) . $back_link);
  582. }
  583. //DROP DB TABLES
  584. $drop_log = "Database already empty. Ready for install.";
  585. if ($_POST['dbclean']) {
  586. $sql = "SHOW TABLES FROM `{$_POST['dbname']}`";
  587. $found_tables = null;
  588. if($result = mysqli_query($dbh, $sql)){
  589. while($row = mysqli_fetch_row($result)){
  590. $found_tables[] = $row[0];
  591. }
  592. if (count($found_tables) > 0) {
  593. foreach($found_tables as $table_name){
  594. $sql = "DROP TABLE `{$_POST['dbname']}`.{$table_name}";
  595. if(! $result = mysqli_query($dbh, $sql)){
  596. die(sprintf(MSG_FAIL_DBTRYCLEAN, $_POST['dbname']) . $back_link);
  597. }
  598. }
  599. }
  600. $drop_log = 'removed (' . count($found_tables) . ') tables';
  601. }
  602. }
  603. //WRITE DATA
  604. DupUtil::log("--------------------------------------");
  605. DupUtil::log("DATABASE RESULTS");
  606. DupUtil::log("--------------------------------------");
  607. $profile_start = DupUtil::get_microtime();
  608. $fcgi_buffer_pool = 5000;
  609. $fcgi_buffer_count = 0;
  610. $dbquery_rows = 0;
  611. $dbquery_errs = 0;
  612. $counter = 0;
  613. @mysqli_autocommit($dbh, false);
  614. while ($counter < $sql_result_file_length) {
  615. $query_strlen = strlen(trim($sql_result_file_data[$counter]));
  616. if ($dbvar_maxpacks < $query_strlen) {
  617. DupUtil::log("**ERROR** Query size limit [length={$query_strlen}] [sql=" . substr($sql_result_file_data[$counter], 75) . "...]");
  618. $dbquery_errs++;
  619. }
  620. elseif ($query_strlen > 0) {
  621. @mysqli_free_result(@mysqli_query($dbh, ($sql_result_file_data[$counter])));
  622. $err = mysqli_error($dbh);
  623. //Check to make sure the connection is alive
  624. if (! empty($err)){
  625. if (!mysqli_ping ($dbh)) {
  626. mysqli_close($dbh);
  627. $dbh = mysqli_connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname']);
  628. }
  629. DupUtil::log("**ERROR** database error write '{$err}' - [sql=" . substr($sql_result_file_data[$counter], 0, 75) . "...]");
  630. $dbquery_errs++;
  631. //Buffer data to browser to keep connection open
  632. } else {
  633. if ($fcgi_buffer_count++ > $fcgi_buffer_pool) {
  634. $fcgi_buffer_count = 0;
  635. DupUtil::fcgi_flush();
  636. }
  637. $dbquery_rows++;
  638. }
  639. }
  640. $counter++;
  641. }
  642. @mysqli_commit($dbh);
  643. @mysqli_autocommit($dbh, true);
  644. DupUtil::log("ERRORS FOUND:\t{$dbquery_errs}");
  645. DupUtil::log("DROP TABLE:\t{$drop_log}");
  646. DupUtil::log("QUERIES RAN:\t{$dbquery_rows}\n");
  647. $dbtable_count = 0;
  648. if ($result = mysqli_query($dbh, "SHOW TABLES")) {
  649. while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) {
  650. $table_rows = DupUtil::table_row_count($dbh, $row[0]);
  651. DupUtil::log("{$row[0]}: ({$table_rows})");
  652. $dbtable_count++;
  653. }
  654. @mysqli_free_result($result);
  655. }
  656. if ($dbtable_count == 0) {
  657. DupUtil::log("NOTICE: You may have to manually run the installer-data.sql to validate data input. Also check to make sure your installer file is correct and the
  658. table prefix '{$GLOBALS['FW_TABLEPREFIX']}' is correct for this particular version of WordPress. \n");
  659. }
  660. //DATA CLEANUP: Perform Transient Cache Cleanup
  661. //Remove all duplicator entries and record this one since this is a new install.
  662. $dbdelete_count = 0;
  663. @mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}duplicator`");
  664. $dbdelete_count1 = @mysqli_affected_rows($dbh) or 0;
  665. @mysqli_query($dbh, "DELETE FROM `{$GLOBALS['FW_TABLEPREFIX']}options` WHERE `option_name` LIKE ('_transient%') OR `option_name` LIKE ('_site_transient%')");
  666. $dbdelete_count2 = @mysqli_affected_rows($dbh) or 0;
  667. $dbdelete_count = (abs($dbdelete_count1) + abs($dbdelete_count2));
  668. DupUtil::log("Removed '{$dbdelete_count}' cache/transient rows");
  669. @mysqli_close($dbh);
  670. $profile_end = DupUtil::get_microtime();
  671. DupUtil::log("\nSECTION RUNTIME: " . DupUtil::elapsed_time($profile_end, $profile_start));
  672. $ajax1_end = DupUtil::get_microtime();
  673. $ajax1_sum = DupUtil::elapsed_time($ajax1_end, $ajax1_start);
  674. DupUtil::log("\n{$GLOBALS['SEPERATOR1']}");
  675. DupUtil::log('STEP1 COMPLETE @ ' . @date('h:i:s') . " - TOTAL RUNTIME: {$ajax1_sum}");
  676. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  677. $JSON['pass'] = 1;
  678. $JSON['table_count'] = $dbtable_count;
  679. $JSON['table_rows'] = ($dbquery_rows - ($dbtable_count + $dbdelete_count + $dbquery_errs));
  680. $JSON['query_errs'] = $dbquery_errs;
  681. echo json_encode($JSON);
  682. die('');
  683. ?> <?php break;
  684. case "2" :?> <?php
  685. /** ******************************************************
  686. * CLASS::DUPDBTEXTSWAP
  687. * Walks every table in db that then walks every row and column replacing searches with replaces
  688. * large tables are split into 50k row blocks to save on memory. */
  689. class DupDBTextSwap {
  690. /**
  691. * LOG ERRORS
  692. */
  693. static public function log_errors($report) {
  694. if ( ! empty($report['errsql']) ) {
  695. DupUtil::log("====================================");
  696. DupUtil::log("DATA-REPLACE ERRORS (MySQL)");
  697. foreach( $report['errsql'] as $error ) {DupUtil::log($error);}
  698. DupUtil::log("");
  699. }
  700. if ( ! empty($report['errser']) ) {
  701. DupUtil::log("====================================");
  702. DupUtil::log("DATA-REPLACE ERRORS (Serialization):");
  703. foreach( $report['errser'] as $error ) {DupUtil::log($error);}
  704. DupUtil::log("");
  705. }
  706. if ( ! empty($report['errkey']) ) {
  707. DupUtil::log("====================================");
  708. DupUtil::log("DATA-REPLACE ERRORS (Key):");
  709. DupUtil::log('Use SQL: SELECT @row := @row + 1 as row, t.* FROM some_table t, (SELECT @row := 0) r');
  710. foreach( $report['errkey'] as $error ) {DupUtil::log($error);}
  711. DupUtil::log("");
  712. }
  713. }
  714. /**
  715. * LOG STATS
  716. */
  717. static public function log_stats($report) {
  718. if ( ! empty( $report ) && is_array( $report ) ) {
  719. $stats = sprintf("SEARCH1:\t'%s' \nREPLACE1:\t'%s' \n", $_POST['url_old'], $_POST['url_new']);
  720. $stats .= sprintf("SEARCH2:\t'%s' \nREPLACE2:\t'%s' \n", $_POST['path_old'], $_POST['path_new']);
  721. $stats .= sprintf("SCANNED:\tTables:%d | Rows:%d | Cells:%d \n", $report['scan_tables'], $report['scan_rows'], $report['scan_cells']);
  722. $stats .= sprintf("UPDATED:\tTables:%d | Rows:%d |Cells:%d \n", $report['updt_tables'], $report['updt_rows'], $report['updt_cells']);
  723. $stats .= sprintf("ERRORS:\t\t%d \nRUNTIME:\t%f sec", $report['err_all'], $report['time'] );
  724. DupUtil::log($stats);
  725. }
  726. }
  727. /**
  728. * LOAD
  729. * Begins the processing for replace logic
  730. * @param mysql $conn The db connection object
  731. * @param array $list Key value pair of 'search' and 'replace' arrays
  732. * @param array $tables The tables we want to look at.
  733. * @return array Collection of information gathered during the run.
  734. */
  735. static public function load($conn, $list=array(), $tables=array(), $cols=array()) {
  736. $exclude_cols = $cols;
  737. $report = array('scan_tables'=>0, 'scan_rows'=>0, 'scan_cells'=>0,
  738. 'updt_tables'=>0, 'updt_rows'=>0, 'updt_cells'=>0,
  739. 'errsql'=>array(), 'errser'=>array(), 'errkey'=>array(),
  740. 'errsql_sum'=>0, 'errser_sum'=>0, 'errkey_sum'=>0,
  741. 'time'=>'', 'err_all'=>0);
  742. $profile_start = DupUtil::get_microtime();
  743. if ( is_array( $tables ) && ! empty( $tables ) ) {
  744. foreach ($tables as $table) {
  745. $report['scan_tables']++;
  746. $columns = array( );
  747. // Get a list of columns in this table
  748. $fields = mysqli_query($conn, 'DESCRIBE ' . $table);
  749. while ($column = mysqli_fetch_array( $fields )) {
  750. $columns[ $column[ 'Field' ] ] = $column[ 'Key' ] == 'PRI' ? true : false;
  751. }
  752. // Count the number of rows we have in the table if large we'll split into blocks, This is a mod from Simon Wheatley
  753. $row_count = mysqli_query($conn, 'SELECT COUNT(*) FROM ' . $table);
  754. $rows_result = mysqli_fetch_array( $row_count );
  755. @mysqli_free_result($row_count);
  756. $row_count = $rows_result[ 0 ];
  757. if ( $row_count == 0 )
  758. continue;
  759. $page_size = 25000;
  760. $pages = ceil($row_count / $page_size);
  761. for ($page = 0; $page < $pages; $page++) {
  762. $current_row = 0;
  763. $start = $page * $page_size;
  764. $end = $start + $page_size;
  765. // Grab the content of the table
  766. $data = mysqli_query($conn, sprintf( 'SELECT * FROM %s LIMIT %d, %d', $table, $start, $end ) );
  767. if (! $data)
  768. $report['errsql'][] = mysqli_error($conn);
  769. //Loops every row
  770. while ($row = mysqli_fetch_array($data)) {
  771. $report['scan_rows']++;
  772. $current_row++;
  773. $upd_col = array();
  774. $upd_sql = array();
  775. $where_sql = array();
  776. $upd = false;
  777. $serial_err = 0;
  778. //Loops every cell
  779. foreach( $columns as $column => $primary_key ) {
  780. if (in_array( $column, $exclude_cols ) ) {
  781. continue;
  782. }
  783. $report['scan_cells']++;
  784. $edited_data = $data_to_fix = $row[$column];
  785. $base64coverted = false;
  786. //Only replacing string values
  787. if (! is_numeric($row[$column])) {
  788. //Base 64 detection
  789. if (base64_decode($row[$column], true)) {
  790. $decoded = base64_decode($row[$column], true);
  791. if(self::is_serialized($decoded)) {
  792. $edited_data = $decoded;
  793. $base64coverted = true;
  794. }
  795. }
  796. //Replace logic - level 1: simple check on basic serilized strings
  797. foreach($list as $item) {
  798. $edited_data = self::recursive_unserialize_replace($item['search'], $item['replace'], $edited_data);
  799. }
  800. //Replace logic - level 2: repair larger/complex serilized strings
  801. $serial_check = self::fix_serial_string($edited_data);
  802. if ($serial_check['fixed']) {
  803. $edited_data = $serial_check['data'];
  804. }
  805. elseif ($serial_check['tried'] && ! $serial_check['fixed']) {
  806. $serial_err++;
  807. }
  808. }
  809. //Change was made
  810. if ( $edited_data != $data_to_fix || $serial_err > 0) {
  811. $report['updt_cells']++;
  812. //Base 64 encode
  813. if ($base64coverted) {
  814. $edited_data = base64_encode($edited_data);
  815. }
  816. $upd_col[] = $column;
  817. $upd_sql[] = $column . ' = "' . mysqli_real_escape_string($conn, $edited_data) . '"';
  818. $upd = true;
  819. }
  820. if ($primary_key) {
  821. $where_sql[] = $column . ' = "' . mysqli_real_escape_string($conn, $data_to_fix) . '"';
  822. }
  823. }
  824. //PERFORM ROW UPDATE
  825. if ($upd && ! empty($where_sql)) {
  826. $sql = "UPDATE `{$table}` SET " . implode( ', ', $upd_sql ) . ' WHERE ' . implode( ' AND ', array_filter( $where_sql ) );
  827. $result = mysqli_query($conn, $sql) or $report['errsql'][] = mysqli_error($conn);
  828. if ($result) {
  829. if ($serial_err > 0) {
  830. $report['errser'][] = "SELECT " . implode( ', ', $upd_col ) ." FROM `{$table}` WHERE " . implode(' AND ', array_filter( $where_sql )) . ';';
  831. }
  832. $report['updt_rows']++;
  833. }
  834. } elseif ($upd) {
  835. $report['errkey'][] = sprintf("Row [%s] on Table [%s] requires a manual update.", $current_row, $table);
  836. }
  837. DupUtil::fcgi_flush();
  838. }
  839. @mysqli_free_result($data);
  840. }
  841. if ($upd) {
  842. $report['updt_tables']++;
  843. }
  844. }
  845. }
  846. $profile_end = DupUtil::get_microtime();
  847. $report['time'] = DupUtil::elapsed_time($profile_end, $profile_start);
  848. $report['errsql_sum'] = empty($report['errsql']) ? 0 : count($report['errsql']);
  849. $report['errser_sum'] = empty($report['errser']) ? 0 : count($report['errser']);
  850. $report['errkey_sum'] = empty($report['errkey']) ? 0 : count($report['errkey']);
  851. $report['err_all'] = $report['errsql_sum'] + $report['errser_sum'] + $report['errkey_sum'];
  852. return $report;
  853. }
  854. /**
  855. * Take a serialised array and unserialise it replacing elements and
  856. * unserialising any subordinate arrays and performing the replace.
  857. * @param string $from String we're looking to replace.
  858. * @param string $to What we want it to be replaced with
  859. * @param array $data Used to pass any subordinate arrays back to in.
  860. * @param bool $serialised Does the array passed via $data need serialising.
  861. * @return array The original array with all elements replaced as needed.
  862. */
  863. static private function recursive_unserialize_replace($from = '', $to = '', $data = '', $serialised = false) {
  864. // some unseriliased data cannot be re-serialised eg. SimpleXMLElements
  865. try {
  866. if (is_string($data) && ($unserialized = @unserialize( $data )) !== false) {
  867. $data = self::recursive_unserialize_replace($from, $to, $unserialized, true);
  868. }
  869. elseif (is_array($data)) {
  870. $_tmp = array();
  871. foreach ($data as $key => $value) {
  872. $_tmp[$key] = self::recursive_unserialize_replace($from, $to, $value, false);
  873. }
  874. $data = $_tmp;
  875. unset($_tmp);
  876. }
  877. elseif (is_object($data)) {
  878. $dataClass = get_class($data);
  879. $_tmp = new $dataClass();
  880. foreach ($data as $key => $value) {
  881. $_tmp->$key = self::recursive_unserialize_replace($from, $to, $value, false);
  882. }
  883. $data = $_tmp;
  884. unset($_tmp);
  885. }
  886. else {
  887. if (is_string($data)) {
  888. $data = str_replace($from, $to, $data);
  889. }
  890. }
  891. if ($serialised)
  892. return serialize($data);
  893. } catch(Exception $error) {
  894. DupUtil::log("\nRECURSIVE UNSERIALIZE ERROR: With string\n". $error, 2);
  895. }
  896. return $data;
  897. }
  898. /**
  899. * IS_SERIALIZED
  900. * Test if a string in properly serialized */
  901. static public function is_serialized($data) {
  902. $test = @unserialize(($data));
  903. return ($test !== false || $test === 'b:0;') ? true : false;
  904. }
  905. /**
  906. * FIX_STRING
  907. * Fixes the string length of a string object that has been serialized but the length is broken
  908. * @param string $data The string ojbect to recalculate the size on.
  909. * @return
  910. */
  911. static private function fix_serial_string($data) {
  912. $result = array('data'=>$data, 'fixed'=>false, 'tried'=>false);
  913. if (preg_match("/s:[0-9]+:/", $data)) {
  914. if (! self::is_serialized($data) ) {
  915. $regex = '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|d:|i:|o:|N;))!s';
  916. $serial_string = preg_match( '/^s:[0-9]+:"(.*$)/s', trim($data), $matches);
  917. //Nested serial string
  918. if ($serial_string) {
  919. $inner = preg_replace_callback($regex, 'DupDBTextSwap::fix_string_callback', rtrim($matches[1], '";'));
  920. $serialized_fixed = 's:' . strlen($inner) . ':"' . $inner . '";' ;
  921. } else {
  922. $serialized_fixed = preg_replace_callback($regex, 'DupDBTextSwap::fix_string_callback', $data);
  923. }
  924. if (self::is_serialized($serialized_fixed) ) {
  925. $result['data'] = $serialized_fixed;
  926. $result['fixed'] = true;
  927. }
  928. $result['tried'] = true;
  929. }
  930. }
  931. return $result;
  932. }
  933. static private function fix_string_callback($matches) {
  934. return 's:' . strlen(($matches[2]));
  935. }
  936. }
  937. //====================================================================================================
  938. //DATABASE UPDATES
  939. //====================================================================================================
  940. $ajax2_start = DupUtil::get_microtime();
  941. //MYSQL CONNECTION
  942. $dbh = @mysqli_connect($_POST['dbhost'], $_POST['dbuser'], $_POST['dbpass'], $_POST['dbname']);
  943. $charset_server = @mysqli_character_set_name($dbh);
  944. @mysqli_query($dbh, "SET wait_timeout = {$GLOBALS['DB_MAX_TIME']}");
  945. DupUtil::mysql_set_charset($dbh, $_POST['dbcharset'], $_POST['dbcollate']);
  946. //POST PARAMS
  947. $_POST['blogname'] = mysqli_real_escape_string($dbh, $_POST['blogname']);
  948. $_POST['postguid'] = isset($_POST['postguid']) && $_POST['postguid'] == 1 ? 1 : 0;
  949. $_POST['path_old'] = isset($_POST['path_old']) ? trim($_POST['path_old']) : null;
  950. $_POST['path_new'] = isset($_POST['path_new']) ? trim($_POST['path_new']) : null;
  951. $_POST['siteurl'] = isset($_POST['siteurl']) ? rtrim(trim($_POST['siteurl']), '/') : null;
  952. $_POST['tables'] = isset($_POST['tables']) && is_array($_POST['tables']) ? array_map('stripcslashes', $_POST['tables']) : array();
  953. $_POST['url_old'] = isset($_POST['url_old']) ? trim($_POST['url_old']) : null;
  954. $_POST['url_new'] = isset($_POST['url_new']) ? rtrim(trim($_POST['url_new']), '/') : null;
  955. //LOGGING
  956. $POST_LOG = $_POST;
  957. unset($POST_LOG['tables']);
  958. unset($POST_LOG['plugins']);
  959. unset($POST_LOG['dbpass']);
  960. ksort($POST_LOG);
  961. //GLOBAL DB-REPLACE
  962. DupUtil::log("\n\n\n{$GLOBALS['SEPERATOR1']}");
  963. DupUtil::log('DUPLICATOR INSTALL-LOG');
  964. DupUtil::log('STEP2 START @ ' . @date('h:i:s') );
  965. DupUtil::log('NOTICE: NOTICE: Do not post to public sites or forums');
  966. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  967. DupUtil::log("CHARSET SERVER:\t{$charset_server}");
  968. DupUtil::log("CHARSET CLIENT:\t" . @mysqli_character_set_name($dbh));
  969. DupUtil::log("--------------------------------------");
  970. DupUtil::log("POST DATA");
  971. DupUtil::log("--------------------------------------");
  972. DupUtil::log(print_r($POST_LOG, true));
  973. DupUtil::log("--------------------------------------");
  974. DupUtil::log("SCANNED TABLES");
  975. DupUtil::log("--------------------------------------");
  976. $msg = (isset($_POST['tables']) && count($_POST['tables'] > 0)) ? print_r($_POST['tables'], true) : 'No tables selected to update';
  977. DupUtil::log($msg);
  978. DupUtil::log("--------------------------------------");
  979. DupUtil::log("KEEP PLUGINS ACTIVE");
  980. DupUtil::log("--------------------------------------");
  981. $msg = (isset($_POST['plugins']) && count($_POST['plugins'] > 0)) ? print_r($_POST['plugins'], true) : 'No plugins selected for activation';
  982. DupUtil::log($msg);
  983. //UPDATE SETTINGS
  984. $serial_plugin_list = (isset($_POST['plugins']) && count($_POST['plugins'] > 0)) ? @serialize($_POST['plugins']) : '';
  985. mysqli_query($dbh, "UPDATE `{$GLOBALS['FW_TABLEPREFIX']}options` SET option_value = '{$_POST['blogname']}' WHERE option_name = 'blogname' ");
  986. mysqli_query($dbh, "UPDATE `{$GLOBALS['FW_TABLEPREFIX']}options` SET option_value = '{$_POST['url_new']}' WHERE option_name = 'home' ");
  987. mysqli_query($dbh, "UPDATE `{$GLOBALS['FW_TABLEPREFIX']}options` SET option_value = '{$_POST['siteurl']}' WHERE option_name = 'siteurl' ");
  988. mysqli_query($dbh, "UPDATE `{$GLOBALS['FW_TABLEPREFIX']}options` SET option_value = '{$serial_plugin_list}' WHERE option_name = 'active_plugins' ");
  989. DupUtil::log("--------------------------------------");
  990. DupUtil::log("GLOBAL DB-REPLACE");
  991. DupUtil::log("--------------------------------------");
  992. array_push($GLOBALS['REPLACE_LIST'],
  993. array('search' =>$_POST['url_old'], 'replace'=>$_POST['url_new']),
  994. array('search' =>$_POST['path_old'], 'replace'=>$_POST['path_new']),
  995. array('search' =>rtrim(DupUtil::unset_safe_path($_POST['path_old']), '\\'), 'replace'=>rtrim($_POST['path_new'], '/'))
  996. );
  997. @mysqli_autocommit($dbh, false);
  998. $report = DupDBTextSwap::load( $dbh, $GLOBALS['REPLACE_LIST'], $_POST['tables'], $GLOBALS['TABLES_SKIP_COLS']);
  999. @mysqli_commit($dbh);
  1000. @mysqli_autocommit($dbh, true);
  1001. //BUILD JSON RESPONSE
  1002. $JSON = array();
  1003. $JSON['step1'] = json_decode(urldecode($_POST['json']));
  1004. $JSON['step2'] = $report;
  1005. $JSON['step2']['warn_all'] = 0;
  1006. $JSON['step2']['warnlist'] = array();
  1007. DupDBTextSwap::log_stats($report);
  1008. DupDBTextSwap::log_errors($report);
  1009. //Reset the postguid data
  1010. if ($_POST['postguid']) {
  1011. mysqli_query($dbh, "UPDATE `{$GLOBALS['FW_TABLEPREFIX']}posts` SET guid = REPLACE(guid, '{$_POST['url_new']}', '{$_POST['url_old']}')");
  1012. $update_guid = @mysqli_affected_rows($dbh) or 0;
  1013. DupUtil::log("Reverted '{$update_guid}' post guid columns back to '{$_POST['url_old']}'");
  1014. }
  1015. //====================================================================================================
  1016. //FINAL CLEANUP
  1017. //====================================================================================================
  1018. DupUtil::log("\n{$GLOBALS['SEPERATOR1']}");
  1019. DupUtil::log('START FINAL CLEANUP: ' . @date('h:i:s') );
  1020. DupUtil::log("{$GLOBALS['SEPERATOR1']}");
  1021. $patterns = array("/'WP_HOME',\s*'.*?'/",
  1022. "/'WP_SITEURL',\s*'.*?'/");
  1023. $replace = array("'WP_HOME', " . '\''.$_POST['url_new'].'\'',
  1024. "'WP_SITEURL', " . '\''.$_POST['url_new'].'\'');
  1025. $config_file = @file_get_contents('wp-config.php', true);
  1026. $config_file = preg_replace($patterns, $replace, $config_file);
  1027. file_put_contents('wp-config.php', $config_file);
  1028. //Create Snapshots directory
  1029. if(!file_exists(DUPLICATOR_SSDIR_NAME)) {
  1030. mkdir(DUPLICATOR_SSDIR_NAME, 0755);
  1031. }
  1032. $fp = fopen(DUPLICATOR_SSDIR_NAME . '/index.php', 'w');
  1033. fclose($fp);
  1034. //WEB CONFIG FILE
  1035. $currdata = parse_url($_POST['url_old']);
  1036. $newdata = parse_url($_POST['url_new']);
  1037. $currpath = DupUtil::add_slash(isset($currdata['path']) ? $currdata['path'] : "");
  1038. $newpath = DupUtil::add_slash(isset($newdata['path']) ? $newdata['path'] : "");
  1039. if ($currpath != $newpath) {
  1040. DupUtil::log("HTACCESS CHANGES:");
  1041. @copy('.htaccess', '.htaccess.orig');
  1042. @copy('web.config', 'web.config.orig');
  1043. @unlink('.htaccess');
  1044. @unlink('web.config');
  1045. DupUtil::log("created backup of original .htaccess to htaccess.orig and web.config to web…

Large files files are truncated, but you can click here to view the full file