PluginProbe
ManageWP Worker / 4.9.29
ManageWP Worker v4.9.29
4.9.38 4.9.37 4.9.36 4.9.35 4.9.34 3.8.7 3.8.8 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.18 3.9.19 3.9.2 3.9.20 3.9.21 3.9.22 3.9.23 3.9.24 All 73 releases
worker / init.php

init.php in ManageWP Worker 4.9.29, at init.php

764 lines 29.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: ManageWP - Worker
4 Plugin URI: https://managewp.com
5 Description: We help you efficiently manage all your WordPress websites. <strong>Updates, backups, 1-click login, migrations, security</strong> and more, on one dashboard. This service comes in two versions: standalone <a href="https://managewp.com">ManageWP</a> service that focuses on website management, and <a href="https://godaddy.com/pro">GoDaddy Pro</a> that includes additional tools for hosting, client management, lead generation, and more.
6 Version: 4.9.29
7 Author: GoDaddy
8 Author URI: https://godaddy.com
9 License: GPL2
10 Text Domain: worker
11 Network: true
12 */
13
14 /*
15 * This file is part of the ManageWP Worker plugin.
16 *
17 * (c) ManageWP LLC <contact@managewp.com>
18 *
19 * For the full copyright and license information, please view the LICENSE
20 * file that was distributed with this source code.
21 */
22
23 if (!defined('ABSPATH') && (!defined('MWP_SKIP_BOOTSTRAP') || !MWP_SKIP_BOOTSTRAP)) {
24 exit;
25 }
26
27 if (!defined('MAX_PRIORITY_HOOK')) {
28 define('MAX_PRIORITY_HOOK', 2147483647);
29 }
30
31 if (version_compare(phpversion(), '8.0', '>=') && !function_exists('set_time_limit')){
32 function set_time_limit($seconds)
33 {
34 return false;
35 }
36 }
37
38 /**
39 * Handler for incomplete plugin installations.
40 */
41 if (!function_exists('mwp_fail_safe')):
42 /**
43 * Reserved memory for fatal error handling execution context.
44 */
45 $GLOBALS['mwp_reserved_memory'] = str_repeat(' ', 1024 * 20);
46 /**
47 * If we ever get only partially upgraded due to a server error or misconfiguration,
48 * attempt to disable the plugin.
49 */
50 function mwp_fail_safe()
51 {
52 $GLOBALS['mwp_reserved_memory'] = null;
53
54 $lastError = error_get_last();
55
56 $acceptedErrorTypes = array(
57 E_ERROR,
58 E_COMPILE_ERROR,
59 );
60
61 if (!$lastError || !in_array($lastError['type'], $acceptedErrorTypes)) {
62 return;
63 }
64
65 $activePlugins = get_option('active_plugins');
66 $workerIndex = array_search(plugin_basename(__FILE__), is_array($activePlugins) ? $activePlugins : array());
67 if ($workerIndex === false) {
68 // Plugin is not yet enabled, possibly in activation context.
69 return;
70 }
71
72 $errorSource = realpath($lastError['file']);
73 // We might be in eval() context.
74 if (!$errorSource) {
75 return;
76 }
77
78 // The only fatal error that we would get would be a 'Class 'X' not found in ...', so look out only for those messages.
79 if (!preg_match('/^(Uncaught Error: )?Class \'[^\']+\' not found/', $lastError['message']) &&
80 !preg_match('/^(Uncaught Error: )?Call to undefined method /', $lastError['message']) &&
81 !preg_match('/^require_once\(\): Failed opening required \'[^\']+\'/', $lastError['message'])
82 ) {
83 return;
84 }
85
86 // Only look for files that belong to this plugin.
87 $pluginBase = realpath(dirname(__FILE__));
88 if (stripos($errorSource, $pluginBase) !== 0) {
89 return;
90 }
91
92 // Signal ourselves that the installation is corrupt.
93 update_option('mwp_recovering', time());
94
95 $siteUrl = get_option('siteurl');
96 $path = (string)parse_url($siteUrl, PHP_URL_PATH);
97 $title = sprintf("ManageWP Worker corrupt on %s", $siteUrl);
98 $to = get_option('admin_email');
99 $brand = get_option('mwp_worker_brand');
100 if (!empty($brand['admin_email'])) {
101 $to = $brand['admin_email'];
102 }
103
104 $fullError = print_r($lastError, 1);
105 $serviceID = (string)get_option('mwp_service_key');
106 $body = sprintf("Corrupt ManageWP Worker v%s installation detected. Site URL in question is %s. User email is %s (service ID: %s). Attempting recovery process at %s. The error that caused this:\n\n<pre>%s</pre>", $GLOBALS['MMB_WORKER_VERSION'], $siteUrl, $to, $serviceID, date('Y-m-d H:i:s'), $fullError);
107 mail('recovery@managewp.com', $title, $body, "Content-Type: text/html");
108
109 // If we're inside a cron scope, don't attempt to hide this error.
110 if (defined('DOING_CRON') && DOING_CRON) {
111 return;
112 }
113
114 // If we're inside a normal request scope retry the request so user doesn't have to see an ugly error page.
115 if (!empty($_SERVER['REQUEST_URI'])) {
116 $siteUrl .= substr($_SERVER['REQUEST_URI'], strlen($path));
117 }
118 if (isset($_SERVER['HTTP_MWP_ACTION'])) {
119 echo "\nMWP_RETRY_ME: 1\n", json_encode(array('error' => 'Worker recover started', 'exception' => array(
120 'class' => 'Exception',
121 'message' => 'Worker recover started',
122 'code' => 10038,
123 'file' => __FILE__,
124 'line' => __LINE__,
125 'traceString' => '',
126 'context' => array(),
127 'type' => 'WORKER_RECOVER_STARTED',
128 ))), "\n";
129 exit;
130 } elseif (headers_sent()) {
131 // The headers are probably sent if the PHP configuration has the 'display_errors' directive enabled. In that case try a meta redirect.
132 printf('<meta http-equiv="refresh" content="0; url=%s">', htmlspecialchars($siteUrl, ENT_QUOTES));
133 } else {
134 header('Location: '.htmlspecialchars($siteUrl, ENT_QUOTES));
135 }
136 exit;
137 }
138
139 register_shutdown_function('mwp_fail_safe');
140 endif;
141
142 if (!class_exists('MwpWorkerResponder', false)):
143 /**
144 * We're not allowed to use lambda functions because this is PHP 5.2, so use a responder
145 * class that's able to access the service container.
146 */
147 class MwpWorkerResponder
148 {
149
150 private $container;
151
152 private $responseSent = false;
153
154 function __construct(MWP_ServiceContainer_Interface $container)
155 {
156 $this->container = $container;
157 }
158
159 /**
160 * @param Exception|Error $e
161 * @param MWP_Http_ResponseInterface|null $response
162 *
163 * @throws null
164 */
165 function callback($e = null, MWP_Http_ResponseInterface $response = null)
166 {
167 if ($response !== null) {
168 $responseEvent = new MWP_Event_MasterResponse($response);
169 $this->container->getEventDispatcher()->dispatch(MWP_Event_Events::MASTER_RESPONSE, $responseEvent);
170 $lastResponse = $responseEvent->getResponse();
171
172 if ($lastResponse !== null) {
173 if (!$this->responseSent) {
174 // This looks pretty ugly, but the "execute PHP" function handles fatal errors and wraps them
175 // in a valid action response. That fatal error may also be handled by the global fatal error
176 // handler, which also wraps the error in a response. We keep the state in this class, so we
177 // don't send a worker response twice, first time as an action response, second time as a
178 // global response.
179 // If this is to be removed, simply remove fatal error handling from the "execute PHP" action.
180 $lastResponse->send();
181 $this->responseSent = true;
182 }
183 exit;
184 }
185 } elseif ($e !== null) {
186 // Exception is thrown and the response is empty. This should never happen, so don't try to hide it.
187 throw $e;
188 }
189 }
190
191 /**
192 * @return callable
193 */
194 public function getCallback()
195 {
196 return array($this, 'callback');
197 }
198 }
199 endif;
200
201 if (!function_exists('mwp_container')):
202 /**
203 * @return MWP_ServiceContainer_Interface
204 */
205 function mwp_container()
206 {
207 static $container;
208
209 if ($container === null) {
210 $parameters = (array)get_option('mwp_container_parameters', array()) + (array)get_option('mwp_container_site_parameters', array());
211 $requestId = isset($_GET['mwprid']) && is_string($_GET['mwprid']) ? $_GET['mwprid'] : null;
212 $container = new MWP_ServiceContainer_Production(array(
213 'worker_realpath' => __FILE__,
214 'worker_basename' => 'worker/init.php',
215 'worker_version' => $GLOBALS['MMB_WORKER_VERSION'],
216 'worker_revision' => $GLOBALS['MMB_WORKER_REVISION'],
217 'request_id' => $requestId,
218 ) + $parameters);
219 }
220
221 return $container;
222 }
223 endif;
224
225 if (!class_exists('MwpRecoveryKit', false)):
226 /**
227 * This class must be isolated from the rest of the ManageWP Worker library, because
228 * we're counting that we have only this file and WordPress bootstrapped.
229 */
230 class MwpRecoveryKit
231 {
232 const MAX_LOGGED_ERRORS = 5;
233
234 private static $errorLog = array();
235
236 private static function requestJson($url)
237 {
238 $response = wp_remote_get($url, array('timeout' => 60));
239 if ($response instanceof WP_Error) {
240 throw new Exception('Unable to download checksum.json: '.$response->get_error_message());
241 }
242 if ($response['response']['code'] !== 200) {
243 throw new Exception('Unable to download checksum.json: invalid status code ('.$response['response']['code'].')');
244 }
245
246 $responseJson = json_decode($response['body'], true);
247
248 if (empty($responseJson) || !is_array($responseJson)) {
249 throw new Exception('Error while parsing checksum.json.');
250 }
251
252 return $responseJson;
253 }
254
255 public function recover($version)
256 {
257 global $wpdb;
258 $lockTime = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'mwp_incremental_recover_lock' LIMIT 1");
259
260
261 if ($lockTime && time() - (int)$lockTime < 1200) { // lock for 20 minutes
262 throw new Exception('Another incremental update or recovery process is already active', 1337);
263 }
264
265 register_shutdown_function(array($this, 'releaseLock'));
266
267 update_option('mwp_incremental_recover_lock', time());
268
269 ignore_user_abort(true);
270 $dirName = realpath(dirname(__FILE__));
271 $filesAndChecksums = $this->requestJson(sprintf('https://s3-us-west-2.amazonaws.com/mwp-orion-public/worker/raw/%s/checksum.json', $version));
272
273 try {
274 $files = $this->recoverFiles($dirName, $filesAndChecksums, $version);
275 } catch (Exception $e) {
276 $this->releaseLock();
277 throw $e;
278 }
279
280 $this->releaseLock();
281
282 return $files;
283 }
284
285 public function releaseLock()
286 {
287 delete_option('mwp_incremental_recover_lock');
288 }
289
290 public static function selfUpdate()
291 {
292 if (get_option('mwp_recovering')) {
293 return false;
294 }
295
296 try {
297 $response = self::requestJson('https://s3-us-west-2.amazonaws.com/mwp-orion-public/worker/latest.json');
298 $response += array('version' => '0.0.0', 'schedule' => 86400, 'autoUpdate' => false, 'checksum' => array());
299 wp_clear_scheduled_hook('mwp_auto_update');
300 wp_schedule_single_event(current_time('timestamp') + $response['schedule'], 'mwp_auto_update');
301 if (!$response['autoUpdate']) {
302 return false;
303 }
304 if (version_compare($response['version'], $GLOBALS['MMB_WORKER_VERSION'], '<')) {
305 return false;
306 }
307 self::recoverFiles(dirname(__FILE__), $response['checksum'], $response['version']);
308 } catch (Exception $e) {
309 mwp_logger()->error("Self-update failed.", array('exception' => $e));
310
311 return false;
312 }
313
314 return true;
315 }
316
317 private static function clearUnknownFiles($filesAndChecksums, $fs)
318 {
319 /** @var WP_Filesystem_Base $fs */
320 $base = dirname(__FILE__);
321 if (version_compare(phpversion(), '5.3', '<')) {
322 $directory = new RecursiveDirectoryIterator($base);
323 } else {
324 /** @handled constant */
325 $directory = new RecursiveDirectoryIterator($base, RecursiveDirectoryIterator::SKIP_DOTS);
326 }
327
328 $ignoreDelete = array(
329 'log.html' => 1,
330 'worker.json' => 1,
331 'init.php' => 1, // safe-guard
332 'functions.php' => 1, // safe-guard
333 );
334
335 $files = array_keys(iterator_to_array(new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD)));
336
337 foreach ($files as $file) {
338 $file = preg_replace('/^'.preg_quote($base, '/').'/', '', $file, 1, $count);
339
340 if (!$count) {
341 continue;
342 }
343
344 $file = strtr($file, '\\', '/');
345 $file = ltrim($file, '/');
346
347 if (isset($filesAndChecksums[$file]) || isset($ignoreDelete[$file])) {
348 continue;
349 }
350
351 $fs->delete($fs->find_folder(WP_PLUGIN_DIR).'worker/'.$file, false, 'f');
352 }
353 }
354
355 public static function recoverFiles($dirName, array $filesAndChecksums, $version)
356 {
357 set_error_handler(array(__CLASS__, 'logError'));
358 require_once ABSPATH.'wp-admin/includes/file.php';
359 require_once ABSPATH.'wp-admin/includes/template.php';
360
361 $options = array();
362
363 $fsMethod = get_filesystem_method();
364 if ($fsMethod !== 'direct') {
365 ob_start();
366 $options = request_filesystem_credentials('');
367 ob_end_clean();
368 }
369
370 /** @var WP_Filesystem_Base $fs */
371 WP_Filesystem($options);
372 $fs = $GLOBALS['wp_filesystem'];
373
374 if (!$fs->connect()) {
375 $lastError = error_get_last();
376 $errorMessage = $lastError ? $lastError['message'] : '(no error logged)';
377 throw new Exception('Unable to connect to the file system: '.$errorMessage);
378 }
379
380 $cachedFilesAndChecksums = $filesAndChecksums;
381
382 // First create directories and remove them from the array.
383 // Must be done before shuffling because of nesting.
384 foreach ($filesAndChecksums as $relativePath => $checksum) {
385 if ($checksum !== '') {
386 continue;
387 }
388 unset ($filesAndChecksums[$relativePath]);
389 $absolutePath = $dirName.'/'.$relativePath;
390 // Directories are ordered first.
391 if (!is_dir($absolutePath)) {
392 $fs->mkdir($fs->find_folder(WP_PLUGIN_DIR).'worker/'.$relativePath);
393 }
394 }
395
396 // Check and recreate files. Shuffle them so multiple running instances have a smaller collision.
397 $recoveredFiles = array();
398 $filesAndChecksums = self::shuffleAssoc($filesAndChecksums);
399 $retryCount = 0;
400 $retryUpTo = 5;
401 $lastError = null;
402 while ($checksum = current($filesAndChecksums)) {
403 if ($retryCount >= $retryUpTo) {
404 restore_error_handler();
405 throw new Exception($lastError);
406 }
407 $relativePath = key($filesAndChecksums);
408 $absolutePath = $dirName.'/'.$relativePath;
409 if (file_exists($absolutePath) && md5_file($absolutePath) === $checksum) {
410 next($filesAndChecksums);
411 continue;
412 }
413 $fileUrl = sprintf('https://s3-us-west-2.amazonaws.com/mwp-orion-public/worker/raw/%s/%s', $version, $relativePath);
414 $response = wp_remote_get($fileUrl, array('timeout' => 60));
415 if ($response instanceof WP_Error) {
416 $lastError = 'Unable to download file '.$fileUrl.': '.$response->get_error_message();
417 $retryCount++;
418 continue;
419 }
420 if ($response['response']['code'] !== 200) {
421 $lastError = 'Unable to download file '.$fileUrl.': invalid status code ('.$response['response']['code'].')';
422 $retryCount++;
423 continue;
424 }
425 $saved = $fs->put_contents($fs->find_folder(WP_PLUGIN_DIR).'worker/'.$relativePath, $response['body']);
426
427 if (!$saved) {
428 if (is_callable(array($fs, '__destruct'))) {
429 $fs->__destruct();
430 }
431 $fs->connect();
432 $lastError = 'File saving failed.';
433 if (count(self::$errorLog)) {
434 $lastError .= sprintf(" Last %d logged errors:%s", min(self::MAX_LOGGED_ERRORS, count(self::$errorLog)), "\n - ".implode("\n - ", self::$errorLog));
435 }
436 $retryCount++;
437 continue;
438 }
439
440 $lastError = null;
441 $retryCount = 0;
442 $recoveredFiles[] = $relativePath;
443 next($filesAndChecksums);
444 }
445
446 self::clearUnknownFiles($cachedFilesAndChecksums, $fs);
447
448 if (function_exists('opcache_reset')) {
449 @opcache_reset();
450 }
451
452 restore_error_handler();
453
454 return $recoveredFiles;
455 }
456
457 public static function logError($code, $message, $file = 'Unknown', $line = 0)
458 {
459 self::$errorLog[] = sprintf('Error [%d]: %s in %s on line %d', $code, $message, $file, $line);
460
461 if (count(self::$errorLog) > self::MAX_LOGGED_ERRORS) {
462 array_shift(self::$errorLog);
463 }
464 }
465
466 private static function shuffleAssoc($array)
467 {
468 $keys = array_keys($array);
469 shuffle($keys);
470 $shuffled = array();
471 foreach ($keys as $key) {
472 $shuffled[$key] = $array[$key];
473 }
474
475 return $shuffled;
476 }
477
478 public function selfDeactivate($reason)
479 {
480 if (isset($_SERVER['MWP2_VERSION_ID'])) {
481 return;
482 }
483
484 $activePlugins = get_option('active_plugins');
485 $workerIndex = array_search(plugin_basename(__FILE__), is_array($activePlugins) ? $activePlugins : array());
486 if ($workerIndex === false) {
487 // Plugin is not yet enabled, possibly in activation context.
488 return;
489 }
490 unset($activePlugins[$workerIndex]);
491 // Reset indexes.
492 $activePlugins = array_values($activePlugins);
493
494 delete_option('mwp_recovering');
495 update_option('active_plugins', $activePlugins);
496
497 $lastErrorMessage = '';
498 if ($lastError = error_get_last()) {
499 $lastErrorMessage = "\n\nLast error: ".$lastError['message'];
500 }
501 mail('recovery@managewp.com', sprintf("ManageWP Worker recovery aborted on %s", get_option('siteurl')), sprintf("ManageWP Worker v%s. Reason: %s%s", $GLOBALS['MMB_WORKER_VERSION'], $reason, $lastErrorMessage));
502 }
503 }
504 endif;
505
506 if (!function_exists('mwp_activation_hook')) {
507 function mwp_activation_hook()
508 {
509 update_option('mwp_incremental_update_active', '');
510
511 if (get_option('mwp_recovering')) {
512 update_option('mwp_recovering', '');
513 // Run the checksum one last time.
514 $recoveryKit = new MwpRecoveryKit();
515 try {
516 $recoveryKit->recover($GLOBALS['MMB_WORKER_VERSION']);
517 } catch (Exception $e) {
518 // Deactivating the plugin in activation hook wouldn't work, prevent the activation by triggering an error.
519 trigger_error($e->getMessage(), E_USER_ERROR);
520 }
521 }
522
523 mwp_core()->install();
524 }
525 }
526
527 if (!function_exists('mwp_try_recovery')):
528 function mwp_try_recovery()
529 {
530 global $wpdb;
531 $recoveringTime = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'mwp_recovering' LIMIT 1");
532
533 if (empty($recoveringTime)) {
534 return true;
535 }
536
537 delete_transient('mwp_recovery_key');
538 $recoveryKit = new MwpRecoveryKit();
539 try {
540 $recoveredFiles = $recoveryKit->recover($GLOBALS['MMB_WORKER_VERSION']);
541
542 // Recovery complete.
543 update_option('mwp_recovering', '');
544 mail('recovery@managewp.com', sprintf("ManageWP Worker recovered on %s", get_option('siteurl')), sprintf("%d files successfully recovered in this recovery fork of ManageWP Worker v%s. Filesystem method used was <code>%s</code>.\n\n<pre>%s</pre>", count($recoveredFiles), $GLOBALS['MMB_WORKER_VERSION'], get_filesystem_method(), implode("\n", $recoveredFiles)), 'Content-Type: text/html');
545 } catch (Exception $e) {
546 if ($e->getCode() === 1337) {
547 return false;
548 }
549
550 if (time() - $recoveringTime > 3600) {
551 // If the recovery process does not complete after an hour, deactivate the Worker for safety
552 $recoveryKit->selfDeactivate($e->getMessage());
553 }
554
555 return false;
556 }
557
558 return true;
559 }
560 endif;
561
562 if (!function_exists('add_worker_update_info')):
563 function add_worker_update_info()
564 {
565 echo ' The plugin is going to update itself automatically in the next few days.';
566 }
567 endif;
568
569 if (!function_exists('mwp_init')):
570 function mwp_init()
571 {
572 // When the plugin deactivates due to a corrupt installation, (de)activation hooks
573 // will never get executed, so the 'mwp_recovering' option will never be deleted,
574 // making the plugin always force the recovery mode , which may always fail for any
575 // reason (eg. the site can't ping itself). Handle that case early.
576 register_activation_hook(__FILE__, 'mwp_activation_hook');
577
578 $GLOBALS['MMB_WORKER_VERSION'] = '4.9.29';
579 $GLOBALS['MMB_WORKER_REVISION'] = '2026-01-15 00:00:00';
580
581 // Ensure PHP version compatibility.
582 if (version_compare(PHP_VERSION, '5.2', '<')) {
583 trigger_error("ManageWP Worker plugin requires PHP 5.2 or higher.", E_USER_ERROR);
584 exit;
585 }
586
587 if ($incrementalUpdateTime = get_option('mwp_incremental_update_active')) {
588 if (time() - $incrementalUpdateTime > 600) { // lock for a maximum of 10 minutes for incremental update
589 update_option('mwp_incremental_update_active', '');
590 } else {
591 if (!isset($_SERVER['HTTP_MWP_ACTION'])) {
592 return;
593 }
594
595 global $wpdb;
596
597 $tries = 0;
598 $lastResult = true;
599
600 while ($tries < 60 && ($lastResult = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'mwp_incremental_update_active' LIMIT 1"))) {
601 sleep(1);
602 ++$tries;
603 }
604
605 if (!$lastResult) {
606 echo "\nMWP_RETRY_ME: 1\n";
607 }
608
609 echo "\n", json_encode(array('error' => 'Worker is currently updating; please retry this action in a few seconds.', 'exception' => array(
610 'class' => 'Exception',
611 'message' => 'Worker is currently updating; please retry this action in a few seconds.',
612 'code' => 10037,
613 'file' => __FILE__,
614 'line' => __LINE__,
615 'traceString' => '',
616 'context' => array(),
617 'type' => 'WORKER_UPDATING',
618 ))), "\n";
619 exit;
620 }
621 }
622
623 if ($recoveringTime = get_option('mwp_recovering')) {
624 if (isset($_SERVER['HTTP_MWP_ACTION'])) {
625 $tries = 0;
626 $lastResult = false;
627
628 while ($tries < 60 && !($lastResult = mwp_try_recovery())) {
629 sleep(1);
630 ++$tries;
631 }
632
633 if ($lastResult) {
634 echo "\nMWP_RETRY_ME: 1\n";
635 }
636
637 echo "\n", json_encode(array('error' => 'Worker is currently recovering; please retry this action in a few seconds.', 'exception' => array(
638 'class' => 'Exception',
639 'message' => 'Worker is currently recovering; please retry this action in a few seconds.',
640 'code' => 10036,
641 'file' => __FILE__,
642 'line' => __LINE__,
643 'traceString' => '',
644 'context' => array(),
645 'type' => 'WORKER_RECOVERING',
646 ))), "\n";
647
648 exit;
649 } else {
650 $recoveryKey = get_transient('mwp_recovery_key');
651 if (!$passedRecoveryKey = filter_input(INPUT_POST, 'mwp_recovery_key')) {
652 $recoveryKey = md5(uniqid('', true));
653 set_transient('mwp_recovery_key', $recoveryKey, time() + 604800); // 1 week.
654
655 $headers = array();
656 if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
657 $headers['AUTHORIZATION'] = $_SERVER['HTTP_AUTHORIZATION'];
658 }
659
660 // fork only once, so we do not make too many parallel requests to the website
661 $lockTime = get_option('mwp_incremental_recover_lock');
662
663 if ($lockTime && time() - $lockTime < 1200) { // lock for 20 minutes
664 return;
665 }
666
667 wp_remote_post(get_bloginfo('wpurl'), array(
668 'reject_unsafe_urls' => false,
669 'headers' => $headers,
670 'body' => array(
671 'mwp_recovery_key' => $recoveryKey,
672 ),
673 'timeout' => 0.01,
674 ));
675 } else {
676 if ($recoveryKey !== $passedRecoveryKey) {
677 return;
678 }
679
680 mwp_try_recovery();
681 }
682
683 return;
684 }
685 }
686
687 if (version_compare(PHP_VERSION, '5.3', '<')) {
688 spl_autoload_register('mwp_autoload');
689 } else {
690 // The prepend parameter was added in PHP 5.3.0
691 spl_autoload_register('mwp_autoload', true, true);
692 }
693
694 $GLOBALS['mmb_plugin_dir'] = WP_PLUGIN_DIR.'/'.basename(dirname(__FILE__));
695 $GLOBALS['_mmb_item_filter'] = array();
696 $core = mwp_core();
697
698 $siteUrl = function_exists('get_site_option') ? get_site_option('siteurl') : get_option('siteurl');
699 define('MMB_XFRAME_COOKIE', 'wordpress_'.md5($siteUrl).'_xframe');
700
701 define('MWP_BACKUP_DIR', WP_CONTENT_DIR.'/managewp/backups');
702 define('MWP_DB_DIR', MWP_BACKUP_DIR.'/mwp_db');
703
704 add_filter('deprecated_function_trigger_error', '__return_false');
705 add_action('mwp_update_public_keys', 'mwp_refresh_live_public_keys');
706 add_action('init', 'mmb_plugin_actions', 99999);
707 add_filter('install_plugin_complete_actions', 'mmb_iframe_plugins_fix');
708 add_filter('comment_edit_redirect', 'mwb_edit_redirect_override');
709 add_action('mwp_auto_update', 'MwpRecoveryKit::selfUpdate');
710 add_action('in_plugin_update_message-'.plugin_basename(__FILE__), 'add_worker_update_info');
711
712 add_filter('cron_schedules', 'mwp_link_monitor_cron_recurrence_interval');
713
714 if (mwp_context()->optionGet('mwp_link_monitor_enabled')) {
715 add_action('save_post', 'mwp_add_post_to_link_monitor_check');
716 add_action('delete_post', 'mwp_add_post_to_link_monitor_check');
717
718 if (wp_next_scheduled('mwp_check_for_post_update')) {
719 wp_clear_scheduled_hook('mwp_check_for_post_update');
720 }
721 }
722 // Public key updating cron.
723 if (!wp_next_scheduled('mwp_update_public_keys')) {
724 wp_schedule_event(time(), 'daily', 'mwp_update_public_keys');
725 }
726
727 register_deactivation_hook(__FILE__, array($core, 'deactivate'));
728 register_uninstall_hook(dirname(__FILE__).'/functions.php', 'mwp_uninstall');
729
730 // Don't send the "X-Frame-Options: SAMEORIGIN" header if we're logging in inside an iframe.
731 if (isset($_COOKIE[MMB_XFRAME_COOKIE])) {
732 remove_action('admin_init', 'send_frame_options_header');
733 remove_action('login_init', 'send_frame_options_header');
734 }
735
736 // Remove legacy scheduler.
737 if (wp_next_scheduled('mwp_backup_tasks')) {
738 wp_clear_scheduled_hook('mwp_backup_tasks');
739 }
740 mwp_provision_keys();
741 mwp_set_plugin_priority();
742
743 $request = MWP_Worker_Request::createFromGlobals();
744 $container = mwp_container();
745 $responder = new MwpWorkerResponder($container);
746
747 $kernel = new MWP_Worker_Kernel($container);
748 $kernel->handleRequest($request, $responder->getCallback(), true);
749
750 $mwpMM = get_option('mwp_maintenace_mode');
751 if (!empty($mwpMM) && isset($mwpMM['active']) && $mwpMM['active']) {
752 add_action('admin_notices', 'site_in_mwp_maintenance_mode');
753 }
754 }
755
756 if (!defined('MWP_SKIP_BOOTSTRAP') || !MWP_SKIP_BOOTSTRAP) {
757 if (!get_option('mwp_recovering')) {
758 require_once dirname(__FILE__).'/functions.php';
759 }
760
761 mwp_init();
762 }
763 endif;
764