PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/backupbuddy/_repairbuddy.php

https://bitbucket.org/cblakebarber/circle_bastiat
PHP | 541 lines | 330 code | 80 blank | 131 comment | 102 complexity | f3624d95f3db56cd3cb5cab60f085eff MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, AGPL-1.0, GPL-2.0
  1. <?php
  2. /**
  3. *
  4. * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  5. *
  6. * WARNING: THERE ARE ABSOLUTELY NO EDITABLE PORTIONS OF THIS SCRIPT.
  7. * ALL OPTIONS ARE CONFIGURABLE VIA THE WEB INTERFACE.
  8. * YOU CAN EXTEND THE FUNCTIONALITY BY WRITING A MODULE
  9. * SEE /repairbuddy/modules/ FOR EXAMPLES ON FUNCTIONAL MODULES
  10. *
  11. * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  12. *
  13. * Script Name: RepairBuddy.php for use with BackupBuddy backups.
  14. * Plugin URI: http://pluginbuddy.com/backupbuddy/
  15. * Description: Backup - Restore - Migrate. Backs up files, settings, and content for a complete snapshot of your site. Allows migration to a new host or URL.
  16. * Version: 0.0.1 - See repairbuddy/history.txt
  17. * Author: Dustin Bolton and Ronald Huereca
  18. * Author URI: http://pluginbuddy.com/
  19. *
  20. * Usage:
  21. *
  22. * 1. Upload this script to the server you would like to repair/troubleshoot.
  23. * 2. Upload your backup ZIP file created with BackupBuddy.
  24. * 3. Navigate to the web address of this script. Ex: http://yoursite.com/repairbuddy.php
  25. * 4. Follow the on screen instructions.
  26. *
  27. */
  28. //EXTRACT REPAIRBUDDY
  29. // Unpack files into directory.
  30. /**
  31. * mkdir_recursive()
  32. *
  33. * Recursively creates the directories needed to generate a full directory path.
  34. *
  35. * $path string Full absolute path to generate.
  36. * @return null
  37. *
  38. */
  39. function mkdir_recursive( $path ) {
  40. if ( empty( $path ) ) { // prevent infinite loop on bad path
  41. return;
  42. }
  43. is_dir( dirname( $path ) ) || mkdir_recursive( dirname( $path ) );
  44. return is_dir( $path ) || mkdir( $path );
  45. }
  46. /**
  47. * unpack_packbuddy()
  48. *
  49. * Unpacks required files encoded in importbuddy.php into stand-alone files.
  50. *
  51. * @return null
  52. */
  53. function unpack_repairbuddy( $pb_abspath = '' ) {
  54. if ( !is_writable( $pb_abspath ) ) {
  55. echo 'Error #224834. This directory is not write enabled. Please verify write permissions to continue.';
  56. die();
  57. } else {
  58. $unpack_file = '';
  59. $handle = @fopen( $pb_abspath . 'repairbuddy.php', 'r' );
  60. if ( $handle ) {
  61. while ( ( $buffer = fgets( $handle ) ) !== false ) {
  62. if ( substr( $buffer, 0, 11 ) == '###PACKDATA' ) {
  63. $packdata_commands = explode( ',', trim( $buffer ) );
  64. array_shift( $packdata_commands );
  65. if ( $packdata_commands[0] == 'BEGIN' ) {
  66. // Start packed data.
  67. } elseif ( $packdata_commands[0] == 'FILE_START' ) {
  68. $unpack_file = $packdata_commands[2];
  69. } elseif ( $packdata_commands[0] == 'FILE_END' ) {
  70. $unpack_file = '';
  71. } elseif ( $packdata_commands[0] == 'END' ) {
  72. return;
  73. }
  74. } else {
  75. if ( $unpack_file != '' ) {
  76. if ( !is_dir( dirname( $pb_abspath . $unpack_file ) ) ) {
  77. mkdir_recursive( dirname( $pb_abspath . $unpack_file ) );
  78. }
  79. file_put_contents( $pb_abspath . $unpack_file, trim( base64_decode( $buffer ) ) );
  80. }
  81. }
  82. }
  83. if ( !feof( $handle ) ) {
  84. echo "Error: unexpected fgets() fail\n";
  85. }
  86. fclose( $handle );
  87. }
  88. }
  89. } //end unpack_repairbuddy
  90. $pb_abspath = dirname( __FILE__ ) . '/';
  91. if ( !file_exists( $pb_abspath . 'repairbuddy' ) ) {
  92. unpack_repairbuddy( $pb_abspath );
  93. if ( !file_exists( $pb_abspath . 'repairbuddy' ) ) {
  94. die( 'Unable to unpack RepairBuddy. Error #24349489.' );
  95. }
  96. }
  97. require_once( 'repairbuddy/_load.php' );
  98. class pluginbuddy_repairbuddy {
  99. var $_version = '1.0.0';
  100. var $_bbversion = '2.2.25';
  101. var $_selfdestruct = '#SELFDESTRUCT#';
  102. var $debug = false;
  103. var $_timestamp = 'M j, Y, H:i:s'; // PHP timestamp format.
  104. var $_bootstrap_wordpress = false;
  105. var $_defaults = array(
  106. 'repair_password' => '#PASSWORD#', // MD5 hash of the import password. Prevents unauthorized access. Default: #PASSWORD#
  107. 'password' => '', // MD5 hash of password given.
  108. );
  109. var $_modules = array();
  110. var $_options = array();
  111. var $_database_connected = false;
  112. var $_wpconfig_loaded = false;
  113. /**
  114. * pluginbuddy_importbuddy()
  115. *
  116. * Default constructor.
  117. *
  118. */
  119. function __construct() {
  120. // SELF DESTRUCT IF APPLICABLE!
  121. if ( $this->_selfdestruct != ' #SELFDESTRUCT#' ) {
  122. if ( $this->_selfdestruct > time() ) {
  123. echo '<html><body><h3>RepairBuddy is self-destructing . . .</h3>This copy of RepairBuddy has been set to self destruct & expire and the expiration time has passed.</body></html>';
  124. $this->wipe_repairbuddy();
  125. }
  126. }
  127. // Prevent access to importbuddy.php if it is still in plugin directory.
  128. if ( file_exists( dirname( __FILE__ ) . '/backupbuddy.php' ) ) {
  129. echo 'This file can ONLY be accessed on the destination server that you wish to use the script on.<br>';
  130. echo 'Upload the importer in the root web directory on the destination server and try again.<br><br>';
  131. echo 'If you need assistance visit <a href="http://pluginbuddy.com">http://pluginbuddy.com</a>';
  132. die();
  133. }
  134. // Start logging time for steps that report how long they took.
  135. $this->time_start = microtime( true );
  136. // Set up PHP error levels.
  137. if ( ( $this->debug === true ) || ( isset( $this->_options[ 'show_php_warnings' ] ) &&$this->_options['show_php_warnings'] === true ) ) {
  138. error_reporting( E_ERROR | E_WARNING | E_PARSE | E_NOTICE ); // HIGH
  139. $this->log( 'PHP error reporting set HIGH.' );
  140. } else {
  141. error_reporting( E_ALL ^ E_NOTICE ); // LOW
  142. }
  143. // Detect max execution time for database steps so they can pause when needed for additional PHP processes.
  144. $this->detected_max_execution_time = str_ireplace( 's', '', ini_get( 'max_execution_time' ) );
  145. if ( is_numeric( $this->detected_max_execution_time ) === false ) {
  146. $detected_max_execution_time = 30;
  147. }
  148. // Handle authentication (if needed).
  149. $this->has_access = false; // default
  150. if ( $this->_defaults['repair_password'] == '#PASSWORD#' ) {
  151. //$this->has_access = true;
  152. die( 'Error #454545. A password is required for this script to function.' );
  153. } else {
  154. if ( md5( $this->_options['password'] ) == $this->_defaults['repair_password'] ) {
  155. $this->has_access = true;
  156. }
  157. if ( isset( $_POST['password'] ) || isset( $_GET['v'] ) ) {
  158. if ( md5( $_POST['password'] ) == $this->_defaults['repair_password'] ) {
  159. $this->_options['password'] = $_POST['password'];
  160. $this->has_access = true;
  161. }
  162. if ( isset( $_GET['v'] ) && ( $_GET['v'] == ( 'xv' . md5( $this->_defaults['repair_password'] . 'repairbuddy' . $_GET['page'] ) ) ) ) {
  163. $this->has_access = true;
  164. }
  165. } elseif ( isset( $_POST[ 'hash' ] ) && isset( $_POST[ 'page' ] ) ) {
  166. if ( $_POST[ 'hash' ] == ( 'xv' . md5( $this->_defaults[ 'repair_password' ] . 'repairbuddy' . $_POST[ 'page' ] ) ) ) {
  167. $this->has_access = true;
  168. }
  169. }
  170. }
  171. //Initialize The database
  172. if ( $this->_wpconfig_loaded = ( defined( 'PB_WP_CONFIG' ) ) ) {
  173. $this->_database_connected = defined( 'PB_DB_LOADED' );
  174. }
  175. pb_add_action( 'repairbuddy_init', array( &$this, 'init' ) );
  176. } //end constructor
  177. function has_db_access() {
  178. return $this->_database_connected;
  179. } //end has_db_access
  180. function has_access() {
  181. return $this->has_access;
  182. } //end has_db_access
  183. function ajax_url( ) {
  184. $path = 'repairbuddy/ajax.php';
  185. $plugin == __FILE__;
  186. $plugin_dir = rtrim( dirname( $plugin ), '/' );
  187. //die( $plugin_dir );
  188. $plugin_path = rtrim( str_replace( ABSPATH, '', $plugin_dir ), '/' );
  189. $root_path = 'http://' . $_SERVER[ 'HTTP_HOST' ] . str_replace( $plugin_path, '', $_SERVER[ 'REQUEST_URI' ] );
  190. $filename = basename( $_SERVER[ 'REQUEST_URI' ] );
  191. $full_url = "http://" . $_SERVER['HTTP_HOST'] .$_SERVER['REQUEST_URI'];
  192. $full_url = rtrim( str_replace( $filename, '', $full_url ), '/' ) . '/' . $plugin_path;
  193. if ( !empty( $path ) && is_string( $path) ) {
  194. $full_url .= ltrim( $path, '/' );
  195. }
  196. ?>
  197. <script type='text/javascript'>
  198. var pb_ajaxurl = '<?php echo $full_url; ?>';
  199. </script>
  200. <?php
  201. } //end ajax_url
  202. function init() {
  203. pb_do_action( 'init' );
  204. // LOAD PAGE TEMPLATE.
  205. if ( defined( "PB_DOING_AJAX" ) ) return;
  206. require_once( 'repairbuddy/_template.php' );
  207. }
  208. //Returns a Module title, false on failure
  209. function get_module_title( $slug = '' ) {
  210. $page_slug = isset( $_GET[ 'page' ] ) ? $_GET[ 'page' ] : false;
  211. if ( !empty( $slug ) ) $page_slug = $slug;
  212. foreach ( $this->_modules as $priority => $modules ) {
  213. foreach ( $modules as $module ) {
  214. if ( $module[ 'slug' ] == $page_slug ) {
  215. return $module[ 'title' ];
  216. }
  217. }
  218. }
  219. return false;
  220. } //end get_module_name
  221. /**
  222. * register_module()
  223. *
  224. * Registers a new module. Typically this is called from the module's init.php within the module directory.
  225. * Modules must be registered here to show on the main page.
  226. *
  227. * @param $module_slug string Module slug. Alphanumeric + underscores + dashes permitted.
  228. * @param $module_title string Informative short title. 1-3 words.
  229. * @param $module_description string Short descriptive sentence explaining the module.
  230. * @param $module_default_page string Base name of the default page to load when clicking the module. pagename.php in the pages directory within the module.
  231. * @param $bootstrap_wordpress boolean True: Load WordPress backend via wp-load.php.
  232. * @param $is_minimode string True: Display the module at the bottom of the page as a small button. False: Large button up top.
  233. * @param $is_subtle string True: Display the button as less prominent than other buttons. Currently only in use for minimode.
  234. * @return null
  235. */
  236. function register_module( $args = array() ) {
  237. $defaults = array(
  238. 'slug' => '',
  239. 'title' => '',
  240. 'description' => '',
  241. 'page' => '',
  242. 'bootstrap_wordpress' => false,
  243. 'mini_mode' => '',
  244. 'is_subtle' => '',
  245. 'priority' => 10,
  246. );
  247. $defaults = array_merge( $defaults, $args );
  248. $this->_modules[ intval( $defaults[ 'priority' ] ) ][] = $defaults;
  249. } //end register_module
  250. /**
  251. * alert()
  252. *
  253. * Displays a message to the user.
  254. *
  255. * $message string Message you want to display to the user.
  256. * $error boolean OPTIONAL! true indicates this alert is an error and displays as red. Default: false
  257. * $error_code int OPTIONAL! Error code number to use in linking in the wiki for easy reference.
  258. */
  259. function alert( $message_title, $message_details = '', $error_code = '' ) {
  260. ?>
  261. <div class="alert">
  262. <img src="repairbuddy/images/alert.png" style="float: left;" height="55">
  263. <div style="margin-left: 65px;">
  264. <b><?php echo $message_title; ?></b><br><br>
  265. <?php echo $message_details; ?>
  266. <?php
  267. if ( ( $error_code != '' ) && ( $error_code != '9021' ) ) {
  268. echo '<p><a href="http://ithemes.com/codex/page/BackupBuddy:_Error_Codes#' . $error_code . '" target="_new"><i>BackupBuddy Error Code ' . $error_code . ' - Click for more details.</i></a></p>';
  269. $this->log( 'Error #' . $error_code . ': ' . $message_title, 'error' );
  270. }
  271. ?>
  272. </div>
  273. </div>
  274. <?php
  275. }
  276. function output_status( $message, $is_error = false ) {
  277. $class = $is_error ? 'error' : 'updated';
  278. ?>
  279. <div class='<?php echo $class; ?>'><p><strong><?php echo $message; ?></strong></p></div>
  280. <?php
  281. } //end status
  282. /**
  283. * log()
  284. *
  285. * Logs to a text file depending on settings.
  286. * 0 = none, 1 = errors only, 2 = errors + warnings, 3 = debugging (all kinds of actions)
  287. *
  288. * $text string Text to log.
  289. * $log_type string Valid options: error, warning, all (default so may be omitted).
  290. *
  291. */
  292. function log( $text, $log_type = 'all' ) {
  293. $write = false;
  294. if ( $this->_options['log_level'] == 0 ) { // No logging.
  295. return;
  296. } elseif ( $this->_options['log_level'] == 1 ) { // Errors only.
  297. if ( $log_type == 'error' ) {
  298. $write = true;
  299. }
  300. } elseif ( $this->_options['log_level'] == 2 ) { // Errors and warnings only.
  301. if ( ( $log_type == 'error' ) || ( $log_type == 'warning' ) ) {
  302. $write = true;
  303. }
  304. } elseif ( $this->_options['log_level'] == 3 ) { // Log all; Errors, warnings, actions, notes, etc.
  305. $write = true;
  306. }
  307. if ( is_writable( ABSPATH ) ) {
  308. $fh = fopen( ABSPATH . 'importbuddy.txt', 'a');
  309. if ( $fh !== false ) {
  310. fwrite( $fh, '[' . date( $this->_timestamp, time() ) . '-' . $log_type . '] ' . $text . "\n" );
  311. fclose( $fh );
  312. } else {
  313. // Don't use alert here since it could recursively look writing to the log.
  314. echo 'Warning: Unable to write to log file. Verify write permissions to this directory.' ;
  315. }
  316. }
  317. }
  318. /**
  319. * tip()
  320. *
  321. * Displays a message to the user when they hover over the question mark. Gracefully falls back to normal tooltip.
  322. * HTML is supposed within tooltips.
  323. *
  324. * $message string Actual message to show to user.
  325. * $title string Title of message to show to user. This is displayed at top of tip in bigger letters. Default is blank. (optional)
  326. * $echo_tip boolean Whether to echo the tip (default; true), or return the tip (false). (optional)
  327. */
  328. function tip( $message, $title = '', $echo_tip = true ) {
  329. $tip = ' <a class="pluginbuddy_tip" title="' . $title . ' - ' . $message . '"><img src="repairbuddy/images/pluginbuddy_tip.png"></a>';
  330. if ( $echo_tip === true ) {
  331. echo $tip;
  332. } else {
  333. return $tip;
  334. }
  335. }
  336. function page_link( $module_slug, $page, $force_wordpress_bootstrap = 'false' ) {
  337. if ( $this->has_access != true ) {
  338. return '?';
  339. }
  340. if ( $this->_modules[$module_slug]['bootsrap_wordpress'] == 'true' ) {
  341. $bootstrap = 'true';
  342. } else {
  343. if ( $force_wordpress_bootstrap == true ) {
  344. $bootstrap = 'true';
  345. } else {
  346. $bootstrap = 'false';
  347. }
  348. }
  349. return '?module=' . $module_slug . '&page=' . $page . '&v=xv' . md5( $this->_defaults['repair_password'] . 'repairbuddy' . $page ) . '&bootstrap=' . $bootstrap;
  350. }
  351. /**
  352. * status_box()
  353. *
  354. * Displays a textarea for placing status text into.
  355. *
  356. * @param $default_text string First line of text to display.
  357. * @return string HTML for textarea.
  358. */
  359. function status_box( $default_text = '' ) {
  360. return '<textarea style="width: 100%; height: 120px;" id="importbuddy_status">' . $default_text . '</textarea>';
  361. }
  362. /**
  363. * status()
  364. *
  365. * Write a status line into an existing textarea created with the status_box() function.
  366. *
  367. * @param $type string message, details, error, or warning. Currently not in use.
  368. * @param $message string Message to append to the status box.
  369. * @return null
  370. */
  371. function status( $type, $message ) {
  372. $message = htmlentities( addslashes( $message ) );
  373. $status = date( $this->_timestamp, time() ) . ': ' . $message;
  374. echo '<script type="text/javascript">jQuery( "#importbuddy_status" ).append( "\n' . $status . '"); textareaelem = document.getElementById( "importbuddy_status" ); textareaelem.scrollTop = textareaelem.scrollHeight; </script>';
  375. flush();
  376. if ( $type == 'error' ) {
  377. $this->log( $message, 'error' );
  378. } elseif ( $type == 'warning' ) {
  379. $this->log( $message, 'warning' );
  380. } else {
  381. $this->log( '[' . $type . ']' . $message, 'all' );
  382. }
  383. }
  384. function format_size( $size ) {
  385. $sizes = array( ' Bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB');
  386. if ( $size == 0 ) {
  387. return( 'empty' );
  388. } else {
  389. return ( round( $size / pow( 1024, ( $i = floor( log( $size, 1024 ) ) ) ), $i > 1 ? 2 : 0) . $sizes[$i] );
  390. }
  391. }
  392. function wipe_repairbuddy() {
  393. $this->remove_file( ABSPATH . 'repairbuddy/', 'RepairBuddy Directory', true );
  394. $this->remove_file( ABSPATH . 'repairbuddy.txt', 'RepairBuddy Log File', true );
  395. $this->remove_file( ABSPATH . 'repairbuddy.php', 'RepairBuddy.php main file.', true );
  396. }
  397. function remove_file( $file, $description, $error_on_missing = false ) {
  398. $this->status( 'message', 'Deleting `' . $description . '`...' );
  399. @chmod( $file, 0755 ); // High permissions to delete.
  400. if ( is_dir( $file ) ) { // directory.
  401. $this->remove_dir( $file );
  402. if ( file_exists( $file ) ) {
  403. $this->status( 'error', 'Unable to delete directory: `' . $description . '`. You should manually delete it.' );
  404. } else {
  405. $this->status( 'message', 'Deleted.' );
  406. }
  407. } else { // file
  408. if ( file_exists( $file ) ) {
  409. if ( @unlink( $file ) != 1 ) {
  410. $this->status( 'error', 'Unable to delete file: `' . $description . '`. You should manually delete it.' );
  411. } else {
  412. $this->status( 'message', 'Deleted.' );
  413. }
  414. }
  415. }
  416. }
  417. /**
  418. * remove_dir()
  419. *
  420. * ?
  421. *
  422. * @return ?
  423. */
  424. function remove_dir( $dir ) {
  425. if ( !file_exists( $dir ) ) {
  426. return true;
  427. }
  428. if ( !is_dir( $dir ) || is_link( $dir ) ) {
  429. return unlink($dir);
  430. }
  431. foreach ( scandir( $dir ) as $item ) {
  432. if ( $item == '.' || $item == '..' ) {
  433. continue;
  434. }
  435. if ( !$this->remove_dir( $dir . "/" . $item ) ) {
  436. chmod( $dir . "/" . $item, 0777 );
  437. if ( !$this->remove_dir( $dir . "/" . $item ) ) {
  438. return false;
  439. }
  440. }
  441. }
  442. return rmdir($dir);
  443. }
  444. } // end class.
  445. define( 'pluginbuddy_importbuddy', true ); // Tell Server Info page to not load some sections.
  446. global $pluginbuddy_repairbuddy;
  447. $pluginbuddy_repairbuddy = new pluginbuddy_repairbuddy();
  448. pb_do_action( 'repairbuddy_init' );
  449. function pb_register_module( $args = array() ) {
  450. global $pluginbuddy_repairbuddy;
  451. $pluginbuddy_repairbuddy->register_module( $args );
  452. } //end pb_register_module
  453. function pb_has_db_access() {
  454. global $pluginbuddy_repairbuddy;
  455. return $pluginbuddy_repairbuddy->has_db_access();
  456. } //end pb_has_database_access
  457. function pb_has_access() {
  458. global $pluginbuddy_repairbuddy;
  459. return $pluginbuddy_repairbuddy->has_access();
  460. }
  461. ?>