PluginProbe
ManageWP Worker / 4.9.38
ManageWP Worker v4.9.38
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.38, at init.php

768 lines 30.1 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.38
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 * Note: Type hint removed from $response parameter to fix PHP 8.4+ deprecation warning
166 * about implicitly nullable parameters while maintaining backward compatibility with PHP 5.5+.
167 * The nullable type syntax (?Type) is not supported in PHP 5.5-7.0.
168 */
169 function callback($e = null, $response = null)
170 {
171 if ($response !== null && $response instanceof MWP_Http_ResponseInterface) {
172 $responseEvent = new MWP_Event_MasterResponse($response);
173 $this->container->getEventDispatcher()->dispatch(MWP_Event_Events::MASTER_RESPONSE, $responseEvent);
174 $lastResponse = $responseEvent->getResponse();
175
176 if ($lastResponse !== null) {
177 if (!$this->responseSent) {
178 // This looks pretty ugly, but the "execute PHP" function handles fatal errors and wraps them
179 // in a valid action response. That fatal error may also be handled by the global fatal error
180 // handler, which also wraps the error in a response. We keep the state in this class, so we
181 // don't send a worker response twice, first time as an action response, second time as a
182 // global response.
183 // If this is to be removed, simply remove fatal error handling from the "execute PHP" action.
184 $lastResponse->send();
185 $this->responseSent = true;
186 }
187 exit;
188 }
189 } elseif ($e !== null) {
190 // Exception is thrown and the response is empty. This should never happen, so don't try to hide it.
191 throw $e;
192 }
193 }
194
195 /**
196 * @return callable
197 */
198 public function getCallback()
199 {
200 return array($this, 'callback');
201 }
202 }
203 endif;
204
205 if (!function_exists('mwp_container')):
206 /**
207 * @return MWP_ServiceContainer_Interface
208 */
209 function mwp_container()
210 {
211 static $container;
212
213 if ($container === null) {
214 $parameters = (array)get_option('mwp_container_parameters', array()) + (array)get_option('mwp_container_site_parameters', array());
215 $requestId = isset($_GET['mwprid']) && is_string($_GET['mwprid']) ? $_GET['mwprid'] : null;
216 $container = new MWP_ServiceContainer_Production(array(
217 'worker_realpath' => __FILE__,
218 'worker_basename' => 'worker/init.php',
219 'worker_version' => $GLOBALS['MMB_WORKER_VERSION'],
220 'worker_revision' => $GLOBALS['MMB_WORKER_REVISION'],
221 'request_id' => $requestId,
222 ) + $parameters);
223 }
224
225 return $container;
226 }
227 endif;
228
229 if (!class_exists('MwpRecoveryKit', false)):
230 /**
231 * This class must be isolated from the rest of the ManageWP Worker library, because
232 * we're counting that we have only this file and WordPress bootstrapped.
233 */
234 class MwpRecoveryKit
235 {
236 const MAX_LOGGED_ERRORS = 5;
237
238 private static $errorLog = array();
239
240 private static function requestJson($url)
241 {
242 $response = wp_remote_get($url, array('timeout' => 60));
243 if ($response instanceof WP_Error) {
244 throw new Exception('Unable to download checksum.json: '.$response->get_error_message());
245 }
246 if ($response['response']['code'] !== 200) {
247 throw new Exception('Unable to download checksum.json: invalid status code ('.$response['response']['code'].')');
248 }
249
250 $responseJson = json_decode($response['body'], true);
251
252 if (empty($responseJson) || !is_array($responseJson)) {
253 throw new Exception('Error while parsing checksum.json.');
254 }
255
256 return $responseJson;
257 }
258
259 public function recover($version)
260 {
261 global $wpdb;
262 $lockTime = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'mwp_incremental_recover_lock' LIMIT 1");
263
264
265 if ($lockTime && time() - (int)$lockTime < 1200) { // lock for 20 minutes
266 throw new Exception('Another incremental update or recovery process is already active', 1337);
267 }
268
269 register_shutdown_function(array($this, 'releaseLock'));
270
271 update_option('mwp_incremental_recover_lock', time());
272
273 ignore_user_abort(true);
274 $dirName = realpath(dirname(__FILE__));
275 $filesAndChecksums = $this->requestJson(sprintf('https://s3-us-west-2.amazonaws.com/mwp-orion-public/worker/raw/%s/checksum.json', $version));
276
277 try {
278 $files = $this->recoverFiles($dirName, $filesAndChecksums, $version);
279 } catch (Exception $e) {
280 $this->releaseLock();
281 throw $e;
282 }
283
284 $this->releaseLock();
285
286 return $files;
287 }
288
289 public function releaseLock()
290 {
291 delete_option('mwp_incremental_recover_lock');
292 }
293
294 public static function selfUpdate()
295 {
296 if (get_option('mwp_recovering')) {
297 return false;
298 }
299
300 try {
301 $response = self::requestJson('https://s3-us-west-2.amazonaws.com/mwp-orion-public/worker/latest.json');
302 $response += array('version' => '0.0.0', 'schedule' => 86400, 'autoUpdate' => false, 'checksum' => array());
303 wp_clear_scheduled_hook('mwp_auto_update');
304 wp_schedule_single_event(current_time('timestamp') + $response['schedule'], 'mwp_auto_update');
305 if (!$response['autoUpdate']) {
306 return false;
307 }
308 if (version_compare($response['version'], $GLOBALS['MMB_WORKER_VERSION'], '<')) {
309 return false;
310 }
311 self::recoverFiles(dirname(__FILE__), $response['checksum'], $response['version']);
312 } catch (Exception $e) {
313 mwp_logger()->error("Self-update failed.", array('exception' => $e));
314
315 return false;
316 }
317
318 return true;
319 }
320
321 private static function clearUnknownFiles($filesAndChecksums, $fs)
322 {
323 /** @var WP_Filesystem_Base $fs */
324 $base = dirname(__FILE__);
325 if (version_compare(phpversion(), '5.3', '<')) {
326 $directory = new RecursiveDirectoryIterator($base);
327 } else {
328 /** @handled constant */
329 $directory = new RecursiveDirectoryIterator($base, RecursiveDirectoryIterator::SKIP_DOTS);
330 }
331
332 $ignoreDelete = array(
333 'log.html' => 1,
334 'worker.json' => 1,
335 'init.php' => 1, // safe-guard
336 'functions.php' => 1, // safe-guard
337 );
338
339 $files = array_keys(iterator_to_array(new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD)));
340
341 foreach ($files as $file) {
342 $file = preg_replace('/^'.preg_quote($base, '/').'/', '', $file, 1, $count);
343
344 if (!$count) {
345 continue;
346 }
347
348 $file = strtr($file, '\\', '/');
349 $file = ltrim($file, '/');
350
351 if (isset($filesAndChecksums[$file]) || isset($ignoreDelete[$file])) {
352 continue;
353 }
354
355 $fs->delete($fs->find_folder(WP_PLUGIN_DIR).'worker/'.$file, false, 'f');
356 }
357 }
358
359 public static function recoverFiles($dirName, array $filesAndChecksums, $version)
360 {
361 set_error_handler(array(__CLASS__, 'logError'));
362 require_once ABSPATH.'wp-admin/includes/file.php';
363 require_once ABSPATH.'wp-admin/includes/template.php';
364
365 $options = array();
366
367 $fsMethod = get_filesystem_method();
368 if ($fsMethod !== 'direct') {
369 ob_start();
370 $options = request_filesystem_credentials('');
371 ob_end_clean();
372 }
373
374 /** @var WP_Filesystem_Base $fs */
375 WP_Filesystem($options);
376 $fs = $GLOBALS['wp_filesystem'];
377
378 if (!$fs->connect()) {
379 $lastError = error_get_last();
380 $errorMessage = $lastError ? $lastError['message'] : '(no error logged)';
381 throw new Exception('Unable to connect to the file system: '.$errorMessage);
382 }
383
384 $cachedFilesAndChecksums = $filesAndChecksums;
385
386 // First create directories and remove them from the array.
387 // Must be done before shuffling because of nesting.
388 foreach ($filesAndChecksums as $relativePath => $checksum) {
389 if ($checksum !== '') {
390 continue;
391 }
392 unset ($filesAndChecksums[$relativePath]);
393 $absolutePath = $dirName.'/'.$relativePath;
394 // Directories are ordered first.
395 if (!is_dir($absolutePath)) {
396 $fs->mkdir($fs->find_folder(WP_PLUGIN_DIR).'worker/'.$relativePath);
397 }
398 }
399
400 // Check and recreate files. Shuffle them so multiple running instances have a smaller collision.
401 $recoveredFiles = array();
402 $filesAndChecksums = self::shuffleAssoc($filesAndChecksums);
403 $retryCount = 0;
404 $retryUpTo = 5;
405 $lastError = null;
406 while ($checksum = current($filesAndChecksums)) {
407 if ($retryCount >= $retryUpTo) {
408 restore_error_handler();
409 throw new Exception($lastError);
410 }
411 $relativePath = key($filesAndChecksums);
412 $absolutePath = $dirName.'/'.$relativePath;
413 if (file_exists($absolutePath) && md5_file($absolutePath) === $checksum) {
414 next($filesAndChecksums);
415 continue;
416 }
417 $fileUrl = sprintf('https://s3-us-west-2.amazonaws.com/mwp-orion-public/worker/raw/%s/%s', $version, $relativePath);
418 $response = wp_remote_get($fileUrl, array('timeout' => 60));
419 if ($response instanceof WP_Error) {
420 $lastError = 'Unable to download file '.$fileUrl.': '.$response->get_error_message();
421 $retryCount++;
422 continue;
423 }
424 if ($response['response']['code'] !== 200) {
425 $lastError = 'Unable to download file '.$fileUrl.': invalid status code ('.$response['response']['code'].')';
426 $retryCount++;
427 continue;
428 }
429 $saved = $fs->put_contents($fs->find_folder(WP_PLUGIN_DIR).'worker/'.$relativePath, $response['body']);
430
431 if (!$saved) {
432 if (is_callable(array($fs, '__destruct'))) {
433 $fs->__destruct();
434 }
435 $fs->connect();
436 $lastError = 'File saving failed.';
437 if (count(self::$errorLog)) {
438 $lastError .= sprintf(" Last %d logged errors:%s", min(self::MAX_LOGGED_ERRORS, count(self::$errorLog)), "\n - ".implode("\n - ", self::$errorLog));
439 }
440 $retryCount++;
441 continue;
442 }
443
444 $lastError = null;
445 $retryCount = 0;
446 $recoveredFiles[] = $relativePath;
447 next($filesAndChecksums);
448 }
449
450 self::clearUnknownFiles($cachedFilesAndChecksums, $fs);
451
452 if (function_exists('opcache_reset')) {
453 @opcache_reset();
454 }
455
456 restore_error_handler();
457
458 return $recoveredFiles;
459 }
460
461 public static function logError($code, $message, $file = 'Unknown', $line = 0)
462 {
463 self::$errorLog[] = sprintf('Error [%d]: %s in %s on line %d', $code, $message, $file, $line);
464
465 if (count(self::$errorLog) > self::MAX_LOGGED_ERRORS) {
466 array_shift(self::$errorLog);
467 }
468 }
469
470 private static function shuffleAssoc($array)
471 {
472 $keys = array_keys($array);
473 shuffle($keys);
474 $shuffled = array();
475 foreach ($keys as $key) {
476 $shuffled[$key] = $array[$key];
477 }
478
479 return $shuffled;
480 }
481
482 public function selfDeactivate($reason)
483 {
484 if (isset($_SERVER['MWP2_VERSION_ID'])) {
485 return;
486 }
487
488 $activePlugins = get_option('active_plugins');
489 $workerIndex = array_search(plugin_basename(__FILE__), is_array($activePlugins) ? $activePlugins : array());
490 if ($workerIndex === false) {
491 // Plugin is not yet enabled, possibly in activation context.
492 return;
493 }
494 unset($activePlugins[$workerIndex]);
495 // Reset indexes.
496 $activePlugins = array_values($activePlugins);
497
498 delete_option('mwp_recovering');
499 update_option('active_plugins', $activePlugins);
500
501 $lastErrorMessage = '';
502 if ($lastError = error_get_last()) {
503 $lastErrorMessage = "\n\nLast error: ".$lastError['message'];
504 }
505 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));
506 }
507 }
508 endif;
509
510 if (!function_exists('mwp_activation_hook')) {
511 function mwp_activation_hook()
512 {
513 update_option('mwp_incremental_update_active', '');
514
515 if (get_option('mwp_recovering')) {
516 update_option('mwp_recovering', '');
517 // Run the checksum one last time.
518 $recoveryKit = new MwpRecoveryKit();
519 try {
520 $recoveryKit->recover($GLOBALS['MMB_WORKER_VERSION']);
521 } catch (Exception $e) {
522 // Deactivating the plugin in activation hook wouldn't work, prevent the activation by triggering an error.
523 trigger_error($e->getMessage(), E_USER_ERROR);
524 }
525 }
526
527 mwp_core()->install();
528 }
529 }
530
531 if (!function_exists('mwp_try_recovery')):
532 function mwp_try_recovery()
533 {
534 global $wpdb;
535 $recoveringTime = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'mwp_recovering' LIMIT 1");
536
537 if (empty($recoveringTime)) {
538 return true;
539 }
540
541 delete_transient('mwp_recovery_key');
542 $recoveryKit = new MwpRecoveryKit();
543 try {
544 $recoveredFiles = $recoveryKit->recover($GLOBALS['MMB_WORKER_VERSION']);
545
546 // Recovery complete.
547 update_option('mwp_recovering', '');
548 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');
549 } catch (Exception $e) {
550 if ($e->getCode() === 1337) {
551 return false;
552 }
553
554 if (time() - $recoveringTime > 3600) {
555 // If the recovery process does not complete after an hour, deactivate the Worker for safety
556 $recoveryKit->selfDeactivate($e->getMessage());
557 }
558
559 return false;
560 }
561
562 return true;
563 }
564 endif;
565
566 if (!function_exists('add_worker_update_info')):
567 function add_worker_update_info()
568 {
569 echo ' The plugin is going to update itself automatically in the next few days.';
570 }
571 endif;
572
573 if (!function_exists('mwp_init')):
574 function mwp_init()
575 {
576 // When the plugin deactivates due to a corrupt installation, (de)activation hooks
577 // will never get executed, so the 'mwp_recovering' option will never be deleted,
578 // making the plugin always force the recovery mode , which may always fail for any
579 // reason (eg. the site can't ping itself). Handle that case early.
580 register_activation_hook(__FILE__, 'mwp_activation_hook');
581
582 $GLOBALS['MMB_WORKER_VERSION'] = '4.9.38';
583 $GLOBALS['MMB_WORKER_REVISION'] = '2026-08-21 00:00:00';
584
585 // Ensure PHP version compatibility.
586 if (version_compare(PHP_VERSION, '5.2', '<')) {
587 trigger_error("ManageWP Worker plugin requires PHP 5.2 or higher.", E_USER_ERROR);
588 exit;
589 }
590
591 if ($incrementalUpdateTime = get_option('mwp_incremental_update_active')) {
592 if (time() - $incrementalUpdateTime > 600) { // lock for a maximum of 10 minutes for incremental update
593 update_option('mwp_incremental_update_active', '');
594 } else {
595 if (!isset($_SERVER['HTTP_MWP_ACTION'])) {
596 return;
597 }
598
599 global $wpdb;
600
601 $tries = 0;
602 $lastResult = true;
603
604 while ($tries < 60 && ($lastResult = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'mwp_incremental_update_active' LIMIT 1"))) {
605 sleep(1);
606 ++$tries;
607 }
608
609 if (!$lastResult) {
610 echo "\nMWP_RETRY_ME: 1\n";
611 }
612
613 echo "\n", json_encode(array('error' => 'Worker is currently updating; please retry this action in a few seconds.', 'exception' => array(
614 'class' => 'Exception',
615 'message' => 'Worker is currently updating; please retry this action in a few seconds.',
616 'code' => 10037,
617 'file' => __FILE__,
618 'line' => __LINE__,
619 'traceString' => '',
620 'context' => array(),
621 'type' => 'WORKER_UPDATING',
622 ))), "\n";
623 exit;
624 }
625 }
626
627 if ($recoveringTime = get_option('mwp_recovering')) {
628 if (isset($_SERVER['HTTP_MWP_ACTION'])) {
629 $tries = 0;
630 $lastResult = false;
631
632 while ($tries < 60 && !($lastResult = mwp_try_recovery())) {
633 sleep(1);
634 ++$tries;
635 }
636
637 if ($lastResult) {
638 echo "\nMWP_RETRY_ME: 1\n";
639 }
640
641 echo "\n", json_encode(array('error' => 'Worker is currently recovering; please retry this action in a few seconds.', 'exception' => array(
642 'class' => 'Exception',
643 'message' => 'Worker is currently recovering; please retry this action in a few seconds.',
644 'code' => 10036,
645 'file' => __FILE__,
646 'line' => __LINE__,
647 'traceString' => '',
648 'context' => array(),
649 'type' => 'WORKER_RECOVERING',
650 ))), "\n";
651
652 exit;
653 } else {
654 $recoveryKey = get_transient('mwp_recovery_key');
655 if (!$passedRecoveryKey = filter_input(INPUT_POST, 'mwp_recovery_key')) {
656 $recoveryKey = md5(uniqid('', true));
657 set_transient('mwp_recovery_key', $recoveryKey, time() + 604800); // 1 week.
658
659 $headers = array();
660 if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
661 $headers['AUTHORIZATION'] = $_SERVER['HTTP_AUTHORIZATION'];
662 }
663
664 // fork only once, so we do not make too many parallel requests to the website
665 $lockTime = get_option('mwp_incremental_recover_lock');
666
667 if ($lockTime && time() - $lockTime < 1200) { // lock for 20 minutes
668 return;
669 }
670
671 wp_remote_post(get_bloginfo('wpurl'), array(
672 'reject_unsafe_urls' => false,
673 'headers' => $headers,
674 'body' => array(
675 'mwp_recovery_key' => $recoveryKey,
676 ),
677 'timeout' => 0.01,
678 ));
679 } else {
680 if ($recoveryKey !== $passedRecoveryKey) {
681 return;
682 }
683
684 mwp_try_recovery();
685 }
686
687 return;
688 }
689 }
690
691 if (version_compare(PHP_VERSION, '5.3', '<')) {
692 spl_autoload_register('mwp_autoload');
693 } else {
694 // The prepend parameter was added in PHP 5.3.0
695 spl_autoload_register('mwp_autoload', true, true);
696 }
697
698 $GLOBALS['mmb_plugin_dir'] = WP_PLUGIN_DIR.'/'.basename(dirname(__FILE__));
699 $GLOBALS['_mmb_item_filter'] = array();
700 $core = mwp_core();
701
702 $siteUrl = function_exists('get_site_option') ? get_site_option('siteurl') : get_option('siteurl');
703 define('MMB_XFRAME_COOKIE', 'wordpress_'.md5($siteUrl).'_xframe');
704
705 define('MWP_BACKUP_DIR', WP_CONTENT_DIR.'/managewp/backups');
706 define('MWP_DB_DIR', MWP_BACKUP_DIR.'/mwp_db');
707
708 add_filter('deprecated_function_trigger_error', '__return_false');
709 add_action('mwp_update_public_keys', 'mwp_refresh_live_public_keys');
710 add_action('init', 'mmb_plugin_actions', 99999);
711 add_filter('install_plugin_complete_actions', 'mmb_iframe_plugins_fix');
712 add_filter('comment_edit_redirect', 'mwb_edit_redirect_override');
713 add_action('mwp_auto_update', 'MwpRecoveryKit::selfUpdate');
714 add_action('in_plugin_update_message-'.plugin_basename(__FILE__), 'add_worker_update_info');
715
716 add_filter('cron_schedules', 'mwp_link_monitor_cron_recurrence_interval');
717
718 if (mwp_context()->optionGet('mwp_link_monitor_enabled')) {
719 add_action('save_post', 'mwp_add_post_to_link_monitor_check');
720 add_action('delete_post', 'mwp_add_post_to_link_monitor_check');
721
722 if (wp_next_scheduled('mwp_check_for_post_update')) {
723 wp_clear_scheduled_hook('mwp_check_for_post_update');
724 }
725 }
726 // Public key updating cron.
727 if (!wp_next_scheduled('mwp_update_public_keys')) {
728 wp_schedule_event(time(), 'daily', 'mwp_update_public_keys');
729 }
730
731 register_deactivation_hook(__FILE__, array($core, 'deactivate'));
732 register_uninstall_hook(dirname(__FILE__).'/functions.php', 'mwp_uninstall');
733
734 // Don't send the "X-Frame-Options: SAMEORIGIN" header if we're logging in inside an iframe.
735 if (isset($_COOKIE[MMB_XFRAME_COOKIE])) {
736 remove_action('admin_init', 'send_frame_options_header');
737 remove_action('login_init', 'send_frame_options_header');
738 }
739
740 // Remove legacy scheduler.
741 if (wp_next_scheduled('mwp_backup_tasks')) {
742 wp_clear_scheduled_hook('mwp_backup_tasks');
743 }
744 mwp_provision_keys();
745 mwp_set_plugin_priority();
746
747 $request = MWP_Worker_Request::createFromGlobals();
748 $container = mwp_container();
749 $responder = new MwpWorkerResponder($container);
750
751 $kernel = new MWP_Worker_Kernel($container);
752 $kernel->handleRequest($request, $responder->getCallback(), true);
753
754 $mwpMM = get_option('mwp_maintenace_mode');
755 if (!empty($mwpMM) && isset($mwpMM['active']) && $mwpMM['active']) {
756 add_action('admin_notices', 'site_in_mwp_maintenance_mode');
757 }
758 }
759
760 if (!defined('MWP_SKIP_BOOTSTRAP') || !MWP_SKIP_BOOTSTRAP) {
761 if (!get_option('mwp_recovering')) {
762 require_once dirname(__FILE__).'/functions.php';
763 }
764
765 mwp_init();
766 }
767 endif;
768