PluginProbe
ManageWP Worker / trunk
ManageWP Worker vtrunk
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
← All changes | init.php +681 -1098 3.9.20 → trunk View file →
@@ -1,1184 +1,767 @@
1 1 <?php
2 -/*
2 +/*
3 3 Plugin Name: ManageWP - Worker
4 -Plugin URI: http://managewp.com/
5 -Description: Manage all your blogs from one dashboard. Visit <a href="http://managewp.com">ManageWP.com</a> to sign up.
6 -Author: Prelovac Media
7 -Version: 3.9.20
8 -Author URI: http://www.prelovac.com
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
9 12 */
10 13
11 -/*************************************************************
12 - *
13 - * init.php
14 - *
15 - * Initialize the communication with master
16 - *
17 - *
18 - * Copyright (c) 2011 Prelovac Media
19 - * www.prelovac.com
20 - **************************************************************/
21 -if(basename($_SERVER['SCRIPT_FILENAME']) == "init.php"):
14 +/*
15 + * This file is part of the ManageWP Worker plugin.
16 + *
17 + * (c) ManageWP LLC <[email protected]>
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)) {
22 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('[email protected]', $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');
23 140 endif;
24 -if(!defined('MMB_WORKER_VERSION'))
25 - define('MMB_WORKER_VERSION', '3.9.20');
26 141
27 -if ( !defined('MMB_XFRAME_COOKIE')){
28 - $siteurl = function_exists( 'get_site_option' ) ? get_site_option( 'siteurl' ) : get_option( 'siteurl' );
29 - define('MMB_XFRAME_COOKIE', $xframe = 'wordpress_'.md5($siteurl).'_xframe');
30 -}
31 -global $wpdb, $mmb_plugin_dir, $mmb_plugin_url, $wp_version, $mmb_filters, $_mmb_item_filter;
32 -if (version_compare(PHP_VERSION, '5.0.0', '<')) // min version 5 supported
33 - exit("<p>ManageWP Worker plugin requires PHP 5 or higher.</p>");
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 + {
34 149
150 + private $container;
35 151
36 -$mmb_wp_version = $wp_version;
37 -$mmb_plugin_dir = WP_PLUGIN_DIR . '/' . basename(dirname(__FILE__));
38 -$mmb_plugin_url = WP_PLUGIN_URL . '/' . basename(dirname(__FILE__));
152 + private $responseSent = false;
39 153
40 -require_once("$mmb_plugin_dir/helper.class.php");
41 -require_once("$mmb_plugin_dir/core.class.php");
42 -require_once("$mmb_plugin_dir/post.class.php");
43 -require_once("$mmb_plugin_dir/comment.class.php");
44 -require_once("$mmb_plugin_dir/stats.class.php");
45 -require_once("$mmb_plugin_dir/backup.class.php");
46 -require_once("$mmb_plugin_dir/installer.class.php");
47 -require_once("$mmb_plugin_dir/link.class.php");
48 -require_once("$mmb_plugin_dir/user.class.php");
49 -require_once("$mmb_plugin_dir/api.php");
154 + function __construct(MWP_ServiceContainer_Interface $container)
155 + {
156 + $this->container = $container;
157 + }
50 158
51 -require_once("$mmb_plugin_dir/plugins/search/search.php");
52 -require_once("$mmb_plugin_dir/plugins/cleanup/cleanup.php");
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();
53 175
54 -require_once("$mmb_plugin_dir/widget.class.php");
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 + }
55 194
56 -if(!function_exists( 'json_decode' ) && !function_exists( 'json_encode' )){
57 - global $mmb_plugin_dir;
58 - require_once ($mmb_plugin_dir.'/lib/json/JSON.php' );
59 -
60 - function json_decode($json_object, $assoc = false) {
61 - $json = $assoc == true ? new Services_JSON(SERVICES_JSON_LOOSE_TYPE) : new Services_JSON();
62 - return $json->decode($json_object);
63 - }
64 -
65 - function json_encode($object_data) {
66 - $json = new Services_JSON();
67 - return $json->encode($object_data);
68 - }
69 -}
195 + /**
196 + * @return callable
197 + */
198 + public function getCallback()
199 + {
200 + return array($this, 'callback');
201 + }
202 + }
203 +endif;
70 204
71 -if( !function_exists ( 'mmb_parse_data' )) {
72 - function mmb_parse_data( $data = array() ){
73 - if( empty($data) )
74 - return $data;
75 -
76 - $data = (array) $data;
77 - if( isset($data['params']) )
78 - $data['params'] = mmb_filter_params( $data['params'] );
79 -
80 - $postkeys = array('action', 'params', 'id', 'signature', 'setting' );
81 -
82 - if( !empty($data) ){
83 - foreach($data as $key => $items){
84 - if( !in_array($key, $postkeys) )
85 - unset($data[$key]);
86 - }
87 - }
88 - return $data;
89 - }
90 -}
205 +if (!function_exists('mwp_container')):
206 + /**
207 + * @return MWP_ServiceContainer_Interface
208 + */
209 + function mwp_container()
210 + {
211 + static $container;
91 212
92 -if( !function_exists ( 'mmb_filter_params' )) {
93 - function mmb_filter_params( $array = array() ){
94 -
95 - $filter = array( 'current_user', 'wpdb' );
96 - $return = array();
97 - foreach ($array as $key => $val) {
98 - if( !is_int($key) && in_array($key, $filter) )
99 - continue;
100 -
101 - if( is_array( $val ) ) {
102 - $return[$key] = mmb_filter_params( $val );
103 - } else {
104 - $return[$key] = $val;
105 - }
106 - }
107 -
108 - return $return;
109 - }
110 -}
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 + }
111 224
112 -if( !function_exists ( 'mmb_parse_request' )) {
113 - function mmb_parse_request(){
114 -
115 - if (!isset($HTTP_RAW_POST_DATA)) {
116 - $HTTP_RAW_POST_DATA = file_get_contents('php://input');
117 - }
118 - ob_start();
119 -
120 - global $current_user, $mmb_core, $new_actions, $wp_db_version, $wpmu_version, $_wp_using_ext_object_cache, $_mmb_options;
121 - if(substr($HTTP_RAW_POST_DATA, 0, 7) == "action="){
122 - $HTTP_RAW_POST_DATA = str_replace("action=", "", $HTTP_RAW_POST_DATA);
123 - }
124 - $data = base64_decode($HTTP_RAW_POST_DATA);
125 - if ($data){
126 - $data = mmb_parse_data( unserialize( $data ) );
127 - $num = @extract( $data );
128 - }
129 - if (isset($action)) {
130 - $_wp_using_ext_object_cache = false;
131 - @set_time_limit(600);
132 -
133 - if (!$mmb_core->check_if_user_exists($params['username']))
134 - mmb_response('Username <b>' . $params['username'] . '</b> does not have administrator capabilities. Enter the correct username in the site options.', false);
135 -
136 - if ($action == 'add_site') {
137 - mmb_add_site($params);
138 - mmb_response('You should never see this.', false);
139 - }
225 + return $container;
226 + }
227 +endif;
140 228
141 - $auth = $mmb_core->authenticate_message($action . $id, $signature, $id);
142 - if ($auth === true) {
143 -
144 - if(isset($params['username']) && !is_user_logged_in()){
145 - $user = function_exists('get_user_by') ? get_user_by('login', $params['username']) : get_userdatabylogin( $params['username'] );
146 - wp_set_current_user($user->ID);
147 - }
148 -
149 - /* in case database upgrade required, do database backup and perform upgrade ( wordpress wp_upgrade() function ) */
150 - if( strlen(trim($wp_db_version)) && !defined('ACX_PLUGIN_DIR') ){
151 - if ( get_option('db_version') != $wp_db_version ) {
152 - /* in multisite network, please update database manualy */
153 - if (empty($wpmu_version) || (function_exists('is_multisite') && !is_multisite())){
154 - if( ! function_exists('wp_upgrade'))
155 - include_once(ABSPATH.'wp-admin/includes/upgrade.php');
156 -
157 - ob_clean();
158 - @wp_upgrade();
159 - @do_action('after_db_upgrade');
160 - ob_end_clean();
161 - }
162 - }
163 - }
164 -
165 - if(isset($params['secure'])){
166 - if($decrypted = $mmb_core->_secure_data($params['secure'])){
167 - $decrypted = maybe_unserialize($decrypted);
168 - if(is_array($decrypted)){
169 - foreach($decrypted as $key => $val){
170 - if(!is_numeric($key))
171 - $params[$key] = $val;
172 - }
173 - unset($params['secure']);
174 - } else $params['secure'] = $decrypted;
175 - }
176 - }
177 -
178 - if( isset($data['setting']) ){
179 - $mmb_core->save_options( $data['setting'] );
180 - }
181 -
182 - if( !$mmb_core->register_action_params( $action, $params ) ){
183 - global $_mmb_plugin_actions;
184 - $_mmb_plugin_actions[$action] = $params;
185 - }
186 -
187 -
188 - } else {
189 - mmb_response($auth['error'], false);
190 - }
191 - } else {
192 - MMB_Stats::set_hit_count();
193 - }
194 - ob_end_clean();
195 - }
196 -}
197 -/* Main response function */
198 -if( !function_exists ( 'mmb_response' )) {
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;
199 237
200 - function mmb_response($response = false, $success = true)
201 - {
202 - $return = array();
203 -
204 - if ((is_array($response) && empty($response)) || (!is_array($response) && strlen($response) == 0))
205 - $return['error'] = 'Empty response.';
206 - else if ($success)
207 - $return['success'] = $response;
208 - else
209 - $return['error'] = $response;
210 -
211 - if( !headers_sent() ){
212 - header('HTTP/1.0 200 OK');
213 - header('Content-Type: text/plain');
214 - }
215 - exit("<MWPHEADER>" . base64_encode(serialize($return))."<ENDMWPHEADER>");
216 - }
217 -}
238 + private static $errorLog = array();
218 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 + }
219 249
250 + $responseJson = json_decode($response['body'], true);
220 251
221 -if( !function_exists ( 'mmb_add_site' )) {
222 - function mmb_add_site($params) {
223 - global $mmb_core;
224 - $num = extract($params);
225 -
226 - if ($num) {
227 - if (!get_option('_action_message_id') && !get_option('_worker_public_key')) {
228 - $public_key = base64_decode($public_key);
229 -
230 - if (function_exists('openssl_verify')) {
231 - $verify = openssl_verify($action . $id, base64_decode($signature), $public_key);
232 - if ($verify == 1) {
233 - $mmb_core->set_master_public_key($public_key);
234 - $mmb_core->set_worker_message_id($id);
235 - $mmb_core->get_stats_instance();
236 - if(is_array($notifications) && !empty($notifications)){
237 - $mmb_core->stats_instance->set_notifications($notifications);
238 - }
239 - if(is_array($brand) && !empty($brand)){
240 - update_option('mwp_worker_brand',$brand);
241 - }
242 -
243 - if( isset( $add_settigns ) && !empty( $add_settigns ) )
244 - apply_filters( 'mwp_website_add', $add_settigns );
245 -
246 - mmb_response($mmb_core->stats_instance->get_initial_stats(), true);
247 - } else if ($verify == 0) {
248 -
249 - //mmb_response('Site could not be added. OpenSSL verification error: "'.openssl_error_string().'". Contact your hosting support to check the OpenSSL configuration.', false);
250 -
251 - } else {
252 - mmb_response('Command not successful. Please try again.', false);
253 - }
254 - }
255 -
256 - if (!get_option('_worker_nossl_key')) {
257 - srand();
258 -
259 - $random_key = md5(base64_encode($public_key) . rand(0, getrandmax()));
260 -
261 - $mmb_core->set_random_signature($random_key);
262 - $mmb_core->set_worker_message_id($id);
263 - $mmb_core->set_master_public_key($public_key);
264 - $mmb_core->get_stats_instance();
265 - if(is_array($notifications) && !empty($notifications)){
266 - $mmb_core->stats_instance->set_notifications($notifications);
267 - }
268 -
269 - if(is_array($brand) && !empty($brand)){
270 - update_option('mwp_worker_brand',$brand);
271 - }
272 -
273 - mmb_response($mmb_core->stats_instance->get_initial_stats(), true);
274 - } else
275 - mmb_response('Please deactivate & activate ManageWP Worker plugin on your site, then re-add the site to your dashboard.', false);
276 -
277 - } else {
278 - mmb_response('Please deactivate & activate ManageWP Worker plugin on your site and re-add the site to your dashboard.', false);
279 - }
280 - } else {
281 - mmb_response('Invalid parameters received. Please try again.', false);
282 - }
283 - }
284 -}
252 + if (empty($responseJson) || !is_array($responseJson)) {
253 + throw new Exception('Error while parsing checksum.json.');
254 + }
285 255
286 -if( !function_exists ( 'mmb_remove_site' )) {
287 - function mmb_remove_site($params)
288 - {
289 - extract($params);
290 - global $mmb_core;
291 - $mmb_core->uninstall( $deactivate );
292 -
293 - include_once(ABSPATH . 'wp-admin/includes/plugin.php');
294 - $plugin_slug = basename(dirname(__FILE__)) . '/' . basename(__FILE__);
295 -
296 - if ($deactivate) {
297 - deactivate_plugins($plugin_slug, true);
298 - }
299 -
300 - if (!is_plugin_active($plugin_slug))
301 - mmb_response(array(
302 - 'deactivated' => 'Site removed successfully. <br /><br />ManageWP Worker plugin successfully deactivated.'
303 - ), true);
304 - else
305 - mmb_response(array(
306 - 'removed_data' => 'Site removed successfully. <br /><br /><b>ManageWP Worker plugin was not deactivated.</b>'
307 - ), true);
308 -
309 - }
310 -}
311 -if( !function_exists ( 'mmb_stats_get' )) {
312 - function mmb_stats_get($params)
313 - {
314 - global $mmb_core;
315 - $mmb_core->get_stats_instance();
316 - mmb_response($mmb_core->stats_instance->get($params), true);
317 - }
318 -}
256 + return $responseJson;
257 + }
319 258
320 -if( !function_exists ( 'mmb_worker_header' )) {
321 - function mmb_worker_header()
322 - { global $mmb_core, $current_user;
323 -
324 - if(!headers_sent()){
325 - if(isset($current_user->ID))
326 - $expiration = time() + apply_filters('auth_cookie_expiration', 10800, $current_user->ID, false);
327 - else
328 - $expiration = time() + 10800;
329 -
330 - setcookie(MMB_XFRAME_COOKIE, md5(MMB_XFRAME_COOKIE), $expiration, COOKIEPATH, COOKIE_DOMAIN, false, true);
331 - $_COOKIE[MMB_XFRAME_COOKIE] = md5(MMB_XFRAME_COOKIE);
332 - }
333 - }
334 -}
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");
335 263
336 -if( !function_exists ( 'mmb_pre_init_stats' )) {
337 - function mmb_pre_init_stats( $params )
338 - {
339 - global $mmb_core;
340 - $mmb_core->get_stats_instance();
341 - return $mmb_core->stats_instance->pre_init_stats($params);
342 - }
343 -}
344 264
345 -if( !function_exists ( 'mwp_datasend' )) {
346 - function mwp_datasend( $params = array() )
347 - {
348 - global $mmb_core, $_mmb_item_filter, $_mmb_options;
349 - if( isset($_mmb_options['datacron']) ){
350 -
351 - $_mmb_remoteurl = get_option('home');
352 - $_mmb_remoteown = isset($_mmb_options['dataown']) && !empty($_mmb_options['dataown']) ? $_mmb_options['dataown'] : false;
353 -
354 - if( empty($_mmb_remoteown) )
355 - return;
356 -
357 - $_mmb_item_filter['pre_init_stats'] = array( 'core_update', 'hit_counter', 'comments', 'backups', 'posts', 'drafts', 'scheduled' );
358 - $_mmb_item_filter['get'] = array( 'updates', 'errors' );
359 - $mmb_core->get_stats_instance();
360 -
361 - $filter = array(
362 - 'refresh' => '',
363 - 'item_filter' => array(
364 - 'get_stats' => array(
365 - array('updates', array('plugins' => true, 'themes' => true, 'premium' => true )),
366 - array('core_update', array('core' => true )),
367 - array('posts', array('numberposts' => 5 )),
368 - array('drafts', array('numberposts' => 5 )),
369 - array('scheduled', array('numberposts' => 5 )),
370 - array('hit_counter'),
371 - array('comments', array('numberposts' => 5 )),
372 - array('backups'),
373 - 'plugins' => array('cleanup' => array(
374 - 'overhead' => array(),
375 - 'revisions' => array( 'num_to_keep' => 'r_5'),
376 - 'spam' => array(),
377 - )
378 - ),
379 - ),
380 - )
381 - );
382 -
383 - $pre_init_data = $mmb_core->stats_instance->pre_init_stats($filter);
384 - $init_data = $mmb_core->stats_instance->get($filter);
385 -
386 - $data = array_merge($init_data, $pre_init_data);
387 - $hash = $mmb_core->get_secure_hash();
388 -
389 - $datasend['datasend'] = $mmb_core->encrypt_data($data);
390 - $datasend['sitehome'] = base64_encode($_mmb_remoteown.'[]'.$_mmb_remoteurl);
391 - $datasend['sitehash'] = md5($hash.$_mmb_remoteown.$_mmb_remoteurl);
392 -
393 - if ( !class_exists('WP_Http') )
394 - include_once(ABSPATH . WPINC . '/class-http.php');
395 -
396 - $remote = array();
397 - $remote['body'] = $datasend;
398 - $result = wp_remote_post($_mmb_options['datacron'], $remote);
399 - }
400 - }
401 -}
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 + }
402 268
403 -//post
404 -if( !function_exists ( 'mmb_post_create' )) {
405 - function mmb_post_create($params)
406 - {
407 - global $mmb_core;
408 - $mmb_core->get_post_instance();
409 - $return = $mmb_core->post_instance->create($params);
410 - if (is_int($return))
411 - mmb_response($return, true);
412 - else{
413 - if(isset($return['error'])){
414 - mmb_response($return['error'], false);
415 - } else {
416 - mmb_response($return, false);
417 - }
418 - }
419 - }
420 -}
269 + register_shutdown_function(array($this, 'releaseLock'));
421 270
422 -if( !function_exists ( 'mmb_change_post_status' )) {
423 - function mmb_change_post_status($params)
424 - {
425 - global $mmb_core;
426 - $mmb_core->get_post_instance();
427 - $return = $mmb_core->post_instance->change_status($params);
428 - //mmb_response($return, true);
271 + update_option('mwp_incremental_recover_lock', time());
429 272
430 - }
431 -}
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));
432 276
433 -//comments
434 -if( !function_exists ( 'mmb_change_comment_status' )) {
435 - function mmb_change_comment_status($params)
436 - {
437 - global $mmb_core;
438 - $mmb_core->get_comment_instance();
439 - $return = $mmb_core->comment_instance->change_status($params);
440 - //mmb_response($return, true);
441 - if ($return){
442 - $mmb_core->get_stats_instance();
443 - mmb_response($mmb_core->stats_instance->get_comments_stats($params), true);
444 - }else
445 - mmb_response('Comment not updated', false);
446 - }
277 + try {
278 + $files = $this->recoverFiles($dirName, $filesAndChecksums, $version);
279 + } catch (Exception $e) {
280 + $this->releaseLock();
281 + throw $e;
282 + }
447 283
448 -}
449 -if( !function_exists ( 'mmb_comment_stats_get' )) {
450 - function mmb_comment_stats_get($params)
451 - {
452 - global $mmb_core;
453 - $mmb_core->get_stats_instance();
454 - mmb_response($mmb_core->stats_instance->get_comments_stats($params), true);
455 - }
456 -}
284 + $this->releaseLock();
457 285
458 -if( !function_exists ( 'mmb_backup_now' )) {
459 -//backup
460 - function mmb_backup_now($params)
461 - {
462 - global $mmb_core;
463 -
464 - $mmb_core->get_backup_instance();
465 - $return = $mmb_core->backup_instance->backup($params);
466 -
467 - if (is_array($return) && array_key_exists('error', $return))
468 - mmb_response($return['error'], false);
469 - else {
470 - mmb_response($return, true);
471 - }
472 - }
473 -}
286 + return $files;
287 + }
474 288
475 -if( !function_exists ( 'mmb_run_task_now' )) {
476 - function mmb_run_task_now($params)
477 - {
478 - global $mmb_core;
479 - $mmb_core->get_backup_instance();
480 - $return = $mmb_core->backup_instance->task_now($params['task_name']);
481 - if (is_array($return) && array_key_exists('error', $return))
482 - mmb_response($return['error'], false);
483 - else {
484 - mmb_response($return, true);
485 - }
486 - }
487 -}
289 + public function releaseLock()
290 + {
291 + delete_option('mwp_incremental_recover_lock');
292 + }
488 293
489 -if( !function_exists ( 'mmb_email_backup' )) {
490 - function mmb_email_backup($params)
491 - {
492 - global $mmb_core;
493 - $mmb_core->get_backup_instance();
494 - $return = $mmb_core->backup_instance->email_backup($params);
495 -
496 - if (is_array($return) && array_key_exists('error', $return))
497 - mmb_response($return['error'], false);
498 - else {
499 - mmb_response($return, true);
500 - }
501 - }
502 -}
294 + public static function selfUpdate()
295 + {
296 + if (get_option('mwp_recovering')) {
297 + return false;
298 + }
503 299
504 -if( !function_exists ( 'mmb_check_backup_compat' )) {
505 - function mmb_check_backup_compat($params)
506 - {
507 - global $mmb_core;
508 - $mmb_core->get_backup_instance();
509 - $return = $mmb_core->backup_instance->check_backup_compat($params);
510 -
511 - if (is_array($return) && array_key_exists('error', $return))
512 - mmb_response($return['error'], false);
513 - else {
514 - mmb_response($return, true);
515 - }
516 - }
517 -}
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));
518 314
519 -if( !function_exists ( 'mmb_get_backup_req' )) {
520 - function mmb_get_backup_req( $params )
521 - {
522 - global $mmb_core;
523 - $mmb_core->get_stats_instance();
524 - $return = $mmb_core->stats_instance->get_backup_req($params);
525 -
526 - mmb_response($return, true);
527 - }
528 -}
315 + return false;
316 + }
529 317
530 -if( !function_exists ( 'mmb_scheduled_backup' )) {
531 - function mmb_scheduled_backup($params)
532 - {
533 - global $mmb_core;
534 - $mmb_core->get_backup_instance();
535 - $return = $mmb_core->backup_instance->set_backup_task($params);
536 - mmb_response($return, $return);
537 - }
538 -}
318 + return true;
319 + }
539 320
540 -if( !function_exists ( 'mmm_delete_backup' )) {
541 - function mmm_delete_backup($params)
542 - {
543 - global $mmb_core;
544 - $mmb_core->get_backup_instance();
545 - $return = $mmb_core->backup_instance->delete_backup($params);
546 - mmb_response($return, $return);
547 - }
548 -}
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 + }
549 331
550 -if( !function_exists ( 'mmb_optimize_tables' )) {
551 - function mmb_optimize_tables($params)
552 - {
553 - global $mmb_core;
554 - $mmb_core->get_backup_instance();
555 - $return = $mmb_core->backup_instance->optimize_tables();
556 - if ($return)
557 - mmb_response($return, true);
558 - else
559 - mmb_response(false, false);
560 - }
561 -}
562 -if( !function_exists ( 'mmb_restore_now' )) {
563 - function mmb_restore_now($params)
564 - {
565 - global $mmb_core;
566 - $mmb_core->get_backup_instance();
567 - $return = $mmb_core->backup_instance->restore($params);
568 - if (is_array($return) && array_key_exists('error', $return))
569 - mmb_response($return['error'], false);
570 - else
571 - mmb_response($return, true);
572 -
573 - }
574 -}
332 + $ignoreDelete = array(
333 + 'log.html' => 1,
334 + 'worker.json' => 1,
335 + 'init.php' => 1, // safe-guard
336 + 'functions.php' => 1, // safe-guard
337 + );
575 338
576 -if( !function_exists ( 'mmb_remote_backup_now' )) {
577 - function mmb_remote_backup_now($params)
578 - {
579 - global $mmb_core;
580 - $backup_instance = $mmb_core->get_backup_instance();
581 - $return = $mmb_core->backup_instance->remote_backup_now($params);
582 - if (is_array($return) && array_key_exists('error', $return))
583 - mmb_response($return['error'], false);
584 - else
585 - mmb_response($return, true);
586 - }
587 -}
339 + $files = array_keys(iterator_to_array(new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD)));
588 340
341 + foreach ($files as $file) {
342 + $file = preg_replace('/^'.preg_quote($base, '/').'/', '', $file, 1, $count);
589 343
590 -if( !function_exists ( 'mmb_clean_orphan_backups' )) {
591 - function mmb_clean_orphan_backups()
592 - {
593 - global $mmb_core;
594 - $backup_instance = $mmb_core->get_backup_instance();
595 - $return = $mmb_core->backup_instance->cleanup();
596 - if(is_array($return))
597 - mmb_response($return, true);
598 - else
599 - mmb_response($return, false);
600 - }
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('[email protected]', 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 + }
601 529 }
602 530
603 -if( !function_exists ( 'mmb_update_worker_plugin' )) {
604 - function mmb_update_worker_plugin($params)
605 - {
606 - global $mmb_core;
607 - mmb_response($mmb_core->update_worker_plugin($params), true);
608 - }
609 -}
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");
610 536
611 -if( !function_exists ( 'mmb_wp_checkversion' )) {
612 - function mmb_wp_checkversion($params)
613 - {
614 - include_once(ABSPATH . 'wp-includes/version.php');
615 - global $mmb_wp_version, $mmb_core;
616 - mmb_response($mmb_wp_version, true);
617 - }
618 -}
619 -if( !function_exists ( 'mmb_search_posts_by_term' )) {
620 - function mmb_search_posts_by_term($params)
621 - {
622 - global $mmb_core;
623 - $mmb_core->get_search_instance();
624 -
625 - $search_type = trim($params['search_type']);
626 - $search_term = strtolower(trim($params['search_term']));
537 + if (empty($recoveringTime)) {
538 + return true;
539 + }
627 540
628 - switch ($search_type){
629 - case 'page_post':
630 - $return = $mmb_core->search_instance->search_posts_by_term($params);
631 - if($return){
632 - $return = serialize($return);
633 - mmb_response($return, true);
634 - }else{
635 - mmb_response('No posts found', false);
636 - }
637 - break;
638 -
639 - case 'plugin':
640 - $plugins = get_option('active_plugins');
641 -
642 - $have_plugin = false;
643 - foreach ($plugins as $plugin) {
644 - if(strpos($plugin, $search_term)>-1){
645 - $have_plugin = true;
646 - }
647 - }
648 - if($have_plugin){
649 - mmb_response(serialize($plugin), true);
650 - }else{
651 - mmb_response(false, false);
652 - }
653 - break;
654 - case 'theme':
655 - $theme = strtolower(get_option('template'));
656 - if(strpos($theme, $search_term)>-1){
657 - mmb_response($theme, true);
658 - }else{
659 - mmb_response(false, false);
660 - }
661 - break;
662 - default: mmb_response(false, false);
663 - }
664 - $return = $mmb_core->search_instance->search_posts_by_term($params);
665 -
666 -
667 -
668 - if ($return_if_true) {
669 - mmb_response($return_value, true);
670 - } else {
671 - mmb_response($return_if_false, false);
672 - }
673 - }
674 -}
541 + delete_transient('mwp_recovery_key');
542 + $recoveryKit = new MwpRecoveryKit();
543 + try {
544 + $recoveredFiles = $recoveryKit->recover($GLOBALS['MMB_WORKER_VERSION']);
675 545
676 -if( !function_exists ( 'mmb_install_addon' )) {
677 - function mmb_install_addon($params)
678 - {
679 - global $mmb_core;
680 - $mmb_core->get_installer_instance();
681 - $return = $mmb_core->installer_instance->install_remote_file($params);
682 - mmb_response($return, true);
683 -
684 - }
685 -}
546 + // Recovery complete.
547 + update_option('mwp_recovering', '');
548 + mail('[email protected]', 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 + }
686 553
687 -if( !function_exists ( 'mmb_do_upgrade' )) {
688 - function mmb_do_upgrade($params)
689 - {
690 - global $mmb_core, $mmb_upgrading;
691 - $mmb_core->get_installer_instance();
692 - $return = $mmb_core->installer_instance->do_upgrade($params);
693 - mmb_response($return, true);
694 -
695 - }
696 -}
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 + }
697 558
698 -if( !function_exists ('mmb_get_links')) {
699 - function mmb_get_links($params)
700 - {
701 - global $mmb_core;
702 - $mmb_core->get_link_instance();
703 - $return = $mmb_core->link_instance->get_links($params);
704 - if (is_array($return) && array_key_exists('error', $return))
705 - mmb_response($return['error'], false);
706 - else {
707 - mmb_response($return, true);
708 - }
709 - }
710 -}
559 + return false;
560 + }
711 561
712 -if( !function_exists ( 'mmb_add_link' )) {
713 - function mmb_add_link($params)
714 - {
715 - global $mmb_core;
716 - $mmb_core->get_link_instance();
717 - $return = $mmb_core->link_instance->add_link($params);
718 - if (is_array($return) && array_key_exists('error', $return))
719 -
720 - mmb_response($return['error'], false);
721 - else {
722 - mmb_response($return, true);
723 - }
724 -
725 - }
726 -}
562 + return true;
563 + }
564 +endif;
727 565
728 -if( !function_exists ('mmb_delete_link')) {
729 - function mmb_delete_link($params)
730 - {
731 - global $mmb_core;
732 - $mmb_core->get_link_instance();
733 -
734 - $return = $mmb_core->link_instance->delete_link($params);
735 - if (is_array($return) && array_key_exists('error', $return))
736 - mmb_response($return['error'], false);
737 - else {
738 - mmb_response($return, true);
739 - }
740 - }
741 -}
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;
742 572
743 -if( !function_exists ('mmb_delete_links')) {
744 - function mmb_delete_links($params)
745 - {
746 - global $mmb_core;
747 - $mmb_core->get_link_instance();
748 -
749 - $return = $mmb_core->link_instance->delete_links($params);
750 - if (is_array($return) && array_key_exists('error', $return))
751 - mmb_response($return['error'], false);
752 - else {
753 - mmb_response($return, true);
754 - }
755 - }
756 -}
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');
757 581
758 -if( !function_exists ('mmb_get_comments')) {
759 - function mmb_get_comments($params)
760 - {
761 - global $mmb_core;
762 - $mmb_core->get_comment_instance();
763 - $return = $mmb_core->comment_instance->get_comments($params);
764 - if (is_array($return) && array_key_exists('error', $return))
765 - mmb_response($return['error'], false);
766 - else {
767 - mmb_response($return, true);
768 - }
769 - }
770 -}
582 + $GLOBALS['MMB_WORKER_VERSION'] = '4.9.38';
583 + $GLOBALS['MMB_WORKER_REVISION'] = '2026-08-21 00:00:00';
771 584
772 -if( !function_exists ('mmb_action_comment')) {
773 - function mmb_action_comment($params)
774 - {
775 - global $mmb_core;
776 - $mmb_core->get_comment_instance();
777 -
778 - $return = $mmb_core->comment_instance->action_comment($params);
779 - if (is_array($return) && array_key_exists('error', $return))
780 - mmb_response($return['error'], false);
781 - else {
782 - mmb_response($return, true);
783 - }
784 - }
785 -}
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 + }
786 590
787 -if( !function_exists ('mmb_bulk_action_comments')) {
788 - function mmb_bulk_action_comments($params)
789 - {
790 - global $mmb_core;
791 - $mmb_core->get_comment_instance();
792 -
793 - $return = $mmb_core->comment_instance->bulk_action_comments($params);
794 - if (is_array($return) && array_key_exists('error', $return))
795 - mmb_response($return['error'], false);
796 - else {
797 - mmb_response($return, true);
798 - }
799 - }
800 -}
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 + }
801 598
802 -if( !function_exists ('mmb_reply_comment')) {
803 - function mmb_reply_comment($params)
804 - {
805 - global $mmb_core;
806 - $mmb_core->get_comment_instance();
807 -
808 - $return = $mmb_core->comment_instance->reply_comment($params);
809 - if (is_array($return) && array_key_exists('error', $return))
810 - mmb_response($return['error'], false);
811 - else {
812 - mmb_response($return, true);
813 - }
814 - }
815 -}
599 + global $wpdb;
816 600
817 -if( !function_exists ( 'mmb_add_user' )) {
818 - function mmb_add_user($params)
819 - {
820 - global $mmb_core;
821 - $mmb_core->get_user_instance();
822 - $return = $mmb_core->user_instance->add_user($params);
823 - if (is_array($return) && array_key_exists('error', $return))
824 -
825 - mmb_response($return['error'], false);
826 - else {
827 - mmb_response($return, true);
828 - }
829 -
830 - }
831 -}
601 + $tries = 0;
602 + $lastResult = true;
832 603
833 -if( !function_exists ('mmb_get_users')) {
834 - function mmb_get_users($params)
835 - {
836 - global $mmb_core;
837 - $mmb_core->get_user_instance();
838 - $return = $mmb_core->user_instance->get_users($params);
839 - if (is_array($return) && array_key_exists('error', $return))
840 - mmb_response($return['error'], false);
841 - else {
842 - mmb_response($return, true);
843 - }
844 - }
845 -}
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 + }
846 608
847 -if( !function_exists ('mmb_edit_users')) {
848 - function mmb_edit_users($params)
849 - {
850 - global $mmb_core;
851 - $mmb_core->get_user_instance();
852 - $return = $mmb_core->user_instance->edit_users($params);
853 - mmb_response($return, true);
854 - }
855 -}
609 + if (!$lastResult) {
610 + echo "\nMWP_RETRY_ME: 1\n";
611 + }
856 612
857 -if( !function_exists ('mmb_get_posts')) {
858 - function mmb_get_posts($params)
859 - {
860 - global $mmb_core;
861 - $mmb_core->get_post_instance();
862 -
863 - $return = $mmb_core->post_instance->get_posts($params);
864 - if (is_array($return) && array_key_exists('error', $return))
865 - mmb_response($return['error'], false);
866 - else {
867 - mmb_response($return, true);
868 - }
869 - }
870 -}
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 + }
871 626
872 -if( !function_exists ('mmb_delete_post')) {
873 - function mmb_delete_post($params)
874 - {
875 - global $mmb_core;
876 - $mmb_core->get_post_instance();
877 -
878 - $return = $mmb_core->post_instance->delete_post($params);
879 - if (is_array($return) && array_key_exists('error', $return))
880 - mmb_response($return['error'], false);
881 - else {
882 - mmb_response($return, true);
883 - }
884 - }
885 -}
627 + if ($recoveringTime = get_option('mwp_recovering')) {
628 + if (isset($_SERVER['HTTP_MWP_ACTION'])) {
629 + $tries = 0;
630 + $lastResult = false;
886 631
887 -if( !function_exists ('mmb_delete_posts')) {
888 - function mmb_delete_posts($params)
889 - {
890 - global $mmb_core;
891 - $mmb_core->get_post_instance();
892 -
893 - $return = $mmb_core->post_instance->delete_posts($params);
894 - if (is_array($return) && array_key_exists('error', $return))
895 - mmb_response($return['error'], false);
896 - else {
897 - mmb_response($return, true);
898 - }
899 - }
900 -}
632 + while ($tries < 60 && !($lastResult = mwp_try_recovery())) {
633 + sleep(1);
634 + ++$tries;
635 + }
901 636
902 -if( !function_exists ('mmb_edit_posts')) {
903 - function mmb_edit_posts($params)
904 - {
905 - global $mmb_core;
906 - $mmb_core->get_posts_instance();
907 - $return = $mmb_core->posts_instance->edit_posts($params);
908 - mmb_response($return, true);
909 - }
910 -}
637 + if ($lastResult) {
638 + echo "\nMWP_RETRY_ME: 1\n";
639 + }
911 640
912 -if( !function_exists ('mmb_get_pages')) {
913 - function mmb_get_pages($params)
914 - {
915 - global $mmb_core;
916 - $mmb_core->get_post_instance();
917 -
918 - $return = $mmb_core->post_instance->get_pages($params);
919 - if (is_array($return) && array_key_exists('error', $return))
920 - mmb_response($return['error'], false);
921 - else {
922 - mmb_response($return, true);
923 - }
924 - }
925 -}
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";
926 651
927 -if( !function_exists ('mmb_delete_page')) {
928 - function mmb_delete_page($params)
929 - {
930 - global $mmb_core;
931 - $mmb_core->get_post_instance();
932 -
933 - $return = $mmb_core->post_instance->delete_page($params);
934 - if (is_array($return) && array_key_exists('error', $return))
935 - mmb_response($return['error'], false);
936 - else {
937 - mmb_response($return, true);
938 - }
939 - }
940 -}
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.
941 658
942 -if( !function_exists ( 'mmb_iframe_plugins_fix' )) {
943 - function mmb_iframe_plugins_fix($update_actions)
944 - {
945 - foreach($update_actions as $key => $action)
946 - {
947 - $update_actions[$key] = str_replace('target="_parent"','',$action);
948 - }
949 -
950 - return $update_actions;
951 -
952 - }
953 -}
954 -if( !function_exists ( 'mmb_execute_php_code' )) {
955 - function mmb_execute_php_code($params)
956 - {
957 - ob_start();
958 - eval($params['code']);
959 - $return = ob_get_flush();
960 - mmb_response(print_r($return, true), true);
961 - }
962 -}
659 + $headers = array();
660 + if (isset($_SERVER['HTTP_AUTHORIZATION'])) {
661 + $headers['AUTHORIZATION'] = $_SERVER['HTTP_AUTHORIZATION'];
662 + }
963 663
964 -if( !function_exists ( 'mmb_set_notifications' )) {
965 - function mmb_set_notifications($params)
966 - {
967 - global $mmb_core;
968 - $mmb_core->get_stats_instance();
969 - $return = $mmb_core->stats_instance->set_notifications($params);
970 - if (is_array($return) && array_key_exists('error', $return))
971 - mmb_response($return['error'], false);
972 - else {
973 - mmb_response($return, true);
974 - }
975 -
976 - }
977 -}
664 + // fork only once, so we do not make too many parallel requests to the website
665 + $lockTime = get_option('mwp_incremental_recover_lock');
978 666
979 -if( !function_exists ( 'mmb_set_alerts' )) {
980 - function mmb_set_alerts($params)
981 - {
982 - global $mmb_core;
983 - $mmb_core->get_stats_instance();
984 - $return = $mmb_core->stats_instance->set_alerts($params);
985 - mmb_response(true, true);
986 - }
987 -
988 -}
989 -if( !function_exists ('mmb_get_dbname')) {
990 - function mmb_get_dbname($params)
991 - {
992 - global $mmb_core;
993 - $mmb_core->get_stats_instance();
994 -
995 - $return = $mmb_core->stats_instance->get_active_db();
996 - if (is_array($return) && array_key_exists('error', $return))
997 - mmb_response($return['error'], false);
998 - else {
999 - mmb_response($return, true);
1000 - }
1001 - }
1002 -}
667 + if ($lockTime && time() - $lockTime < 1200) { // lock for 20 minutes
668 + return;
669 + }
1003 670
1004 -if( !function_exists('mmb_more_reccurences') ){
1005 - //Backup Tasks
1006 - add_filter('cron_schedules', 'mmb_more_reccurences');
1007 - function mmb_more_reccurences($schedules) {
1008 - $schedules['halfminute'] = array('interval' => 30, 'display' => 'Once in a half minute');
1009 - $schedules['minutely'] = array('interval' => 60, 'display' => 'Once in a minute');
1010 - $schedules['fiveminutes'] = array('interval' => 300, 'display' => 'Once every five minutes');
1011 - $schedules['tenminutes'] = array('interval' => 600, 'display' => 'Once every ten minutes');
1012 - $schedules['sixhours'] = array('interval' => 21600, 'display' => 'Every six hours');
1013 - $schedules['fourhours'] = array('interval' => 14400, 'display' => 'Every four hours');
1014 - $schedules['threehours'] = array('interval' => 10800, 'display' => 'Every three hours');
1015 -
1016 - return $schedules;
1017 - }
1018 -}
1019 -
1020 - add_action('mwp_backup_tasks', 'mwp_check_backup_tasks');
1021 -
1022 -if( !function_exists('mwp_check_backup_tasks') ){
1023 - function mwp_check_backup_tasks() {
1024 - global $mmb_core, $_wp_using_ext_object_cache;
1025 - $_wp_using_ext_object_cache = false;
1026 -
1027 - $mmb_core->get_backup_instance();
1028 - $mmb_core->backup_instance->check_backup_tasks();
1029 - }
1030 -}
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 + }
1031 683
1032 -// if (!wp_next_scheduled('mwp_notifications')) {
1033 - // wp_schedule_event( time(), 'twicedaily', 'mwp_notifications' );
1034 -// }
1035 -// add_action('mwp_notifications', 'mwp_check_notifications');
1036 -
684 + mwp_try_recovery();
685 + }
1037 686
1038 -if (!wp_next_scheduled('mwp_datasend')) {
1039 - wp_schedule_event( time(), 'threehours', 'mwp_datasend' );
1040 -}
1041 -add_action('mwp_datasend', 'mwp_datasend');
1042 -
1043 -if( !function_exists('mwp_check_notifications') ){
1044 - function mwp_check_notifications() {
1045 - global $mmb_core, $_wp_using_ext_object_cache;
1046 - $_wp_using_ext_object_cache = false;
1047 -
1048 - $mmb_core->get_stats_instance();
1049 - $mmb_core->stats_instance->check_notifications();
1050 - }
1051 -}
687 + return;
688 + }
689 + }
1052 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 + }
1053 697
1054 -if( !function_exists('mmb_get_plugins_themes') ){
1055 - function mmb_get_plugins_themes($params) {
1056 - global $mmb_core;
1057 - $mmb_core->get_installer_instance();
1058 - $return = $mmb_core->installer_instance->get($params);
1059 - mmb_response($return, true);
1060 - }
1061 -}
698 + $GLOBALS['mmb_plugin_dir'] = WP_PLUGIN_DIR.'/'.basename(dirname(__FILE__));
699 + $GLOBALS['_mmb_item_filter'] = array();
700 + $core = mwp_core();
1062 701
1063 -if( !function_exists('mmb_edit_plugins_themes') ){
1064 - function mmb_edit_plugins_themes($params) {
1065 - global $mmb_core;
1066 - $mmb_core->get_installer_instance();
1067 - $return = $mmb_core->installer_instance->edit($params);
1068 - mmb_response($return, true);
1069 - }
1070 -}
702 + $siteUrl = function_exists('get_site_option') ? get_site_option('siteurl') : get_option('siteurl');
703 + define('MMB_XFRAME_COOKIE', 'wordpress_'.md5($siteUrl).'_xframe');
1071 704
1072 -if( !function_exists('mmb_worker_brand')){
1073 - function mmb_worker_brand($params) {
1074 - update_option("mwp_worker_brand",$params['brand']);
1075 - mmb_response(true, true);
1076 - }
1077 -}
705 + define('MWP_BACKUP_DIR', WP_CONTENT_DIR.'/managewp/backups');
706 + define('MWP_DB_DIR', MWP_BACKUP_DIR.'/mwp_db');
1078 707
1079 -if( !function_exists('mmb_maintenance_mode')){
1080 - function mmb_maintenance_mode( $params ) {
1081 - global $wp_object_cache;
1082 -
1083 - $default = get_option('mwp_maintenace_mode');
1084 - $params = empty($default) ? $params : array_merge($default, $params);
1085 - update_option("mwp_maintenace_mode", $params);
1086 -
1087 - if(!empty($wp_object_cache))
1088 - @$wp_object_cache->flush();
1089 - mmb_response(true, true);
1090 - }
1091 -}
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');
1092 715
1093 -if( !function_exists('mmb_plugin_actions') ){
1094 - function mmb_plugin_actions() {
1095 - global $mmb_actions, $mmb_core;
1096 -
1097 - if(!empty($mmb_actions)){
1098 - global $_mmb_plugin_actions;
1099 - if(!empty($_mmb_plugin_actions)){
1100 - $failed = array();
1101 - foreach($_mmb_plugin_actions as $action => $params){
1102 - if(isset($mmb_actions[$action]))
1103 - call_user_func($mmb_actions[$action], $params);
1104 - else
1105 - $failed[] = $action;
1106 - }
1107 - if(!empty($failed)){
1108 - $f = implode(', ', $failed);
1109 - $s = count($f) > 1 ? 'Actions "' . $f . '" do' : 'Action "' . $f . '" does';
1110 - mmb_response($s.' not exist. Please update your Worker plugin.', false);
1111 - }
1112 -
1113 - }
1114 - }
1115 -
1116 - global $pagenow, $current_user, $mmode;
1117 - if( !is_admin() && !in_array($pagenow, array( 'wp-login.php' ))){
1118 - $mmode = get_option('mwp_maintenace_mode');
1119 - if( !empty($mmode) ){
1120 - if(isset($mmode['active']) && $mmode['active'] == true){
1121 - if(isset($current_user->data) && !empty($current_user->data) && isset($mmode['hidecaps']) && !empty($mmode['hidecaps'])){
1122 - $usercaps = array();
1123 - if(isset($current_user->caps) && !empty($current_user->caps)){
1124 - $usercaps = $current_user->caps;
1125 - }
1126 - foreach($mmode['hidecaps'] as $cap => $hide){
1127 - if(!$hide)
1128 - continue;
1129 -
1130 - foreach($usercaps as $ucap => $val){
1131 - if($ucap == $cap){
1132 - ob_end_clean();
1133 - ob_end_flush();
1134 - die($mmode['template']);
1135 - }
1136 - }
1137 - }
1138 - } else
1139 - die($mmode['template']);
1140 - }
1141 - }
1142 - }
1143 -
1144 - if (file_exists(dirname(__FILE__) . '/log')) {
1145 - unlink(dirname(__FILE__) . '/log');
1146 - }
1147 - }
1148 -}
716 + add_filter('cron_schedules', 'mwp_link_monitor_cron_recurrence_interval');
1149 717
1150 -$mmb_core = new MMB_Core();
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');
1151 721
1152 -if(isset($_GET['auto_login']))
1153 - $mmb_core->automatic_login();
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 + }
1154 730
1155 -if (function_exists('register_activation_hook'))
1156 - register_activation_hook( __FILE__ , array( $mmb_core, 'install' ));
731 + register_deactivation_hook(__FILE__, array($core, 'deactivate'));
732 + register_uninstall_hook(dirname(__FILE__).'/functions.php', 'mwp_uninstall');
1157 733
1158 -if (function_exists('register_deactivation_hook'))
1159 - register_deactivation_hook(__FILE__, array( $mmb_core, 'uninstall' ));
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 + }
1160 739
1161 -if (function_exists('add_action'))
1162 - add_action('init', 'mmb_plugin_actions', 99999);
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();
1163 746
1164 -if (function_exists('add_filter'))
1165 - add_filter('install_plugin_complete_actions','mmb_iframe_plugins_fix');
747 + $request = MWP_Worker_Request::createFromGlobals();
748 + $container = mwp_container();
749 + $responder = new MwpWorkerResponder($container);
1166 750
1167 -if(!function_exists('mwb_edit_redirect_override')){
1168 - function mwb_edit_redirect_override($location = false, $comment_id = false){
1169 - if(isset($_COOKIE[MMB_XFRAME_COOKIE])){
1170 - $location = get_site_url().'/wp-admin/edit-comments.php';
1171 - }
1172 - return $location;
1173 - }
1174 -}
1175 -if (function_exists('add_filter'))
1176 - add_filter('comment_edit_redirect', 'mwb_edit_redirect_override');
751 + $kernel = new MWP_Worker_Kernel($container);
752 + $kernel->handleRequest($request, $responder->getCallback(), true);
1177 753
1178 -if( isset($_COOKIE[MMB_XFRAME_COOKIE]) ){
1179 - remove_action( 'admin_init', 'send_frame_options_header');
1180 - remove_action( 'login_init', 'send_frame_options_header');
1181 -}
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 + }
1182 759
760 + if (!defined('MWP_SKIP_BOOTSTRAP') || !MWP_SKIP_BOOTSTRAP) {
761 + if (!get_option('mwp_recovering')) {
762 + require_once dirname(__FILE__).'/functions.php';
763 + }
1183 764
1184 -?>
765 + mwp_init();
766 + }
767 +endif;