PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.21
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.21
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / central / commands.php

commands.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.21, at central/commands.php

367 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
4
5 /**
6 * - A container for all the RPC commands implemented. Commands map exactly onto method names (and hence this class should not implement anything else, beyond the constructor, and private methods)
7 * - Return format is array('response' => (string - a code), 'data' => (mixed));
8 *
9 * RPC commands are not allowed to begin with an underscore. So, any private methods can be prefixed with an underscore.
10 */
11 abstract class UpdraftCentral_Commands {
12
13 protected $rc;
14
15 protected $ud;
16
17 protected $installed_data;
18
19 /**
20 * Class constructor
21 *
22 * @param string $rc
23 */
24 public function __construct($rc) {
25 $this->rc = $rc;
26 global $updraftplus;
27 $this->ud = $updraftplus;
28 $this->installed_data = array();
29 }
30
31 /**
32 * Include a file or files from wp-admin/includes
33 */
34 final protected function _admin_include() {
35 $files = func_get_args();
36 foreach ($files as $file) {
37 include_once(ABSPATH.'/wp-admin/includes/'.$file);
38 }
39 }
40
41 /**
42 * Include a file or files from wp-includes
43 */
44 final protected function _frontend_include() {
45 $files = func_get_args();
46 foreach ($files as $file) {
47 include_once(ABSPATH.WPINC.'/'.$file);
48 }
49 }
50
51 /**
52 * Return a response in the expected format
53 *
54 * @param Mixed $data
55 * @param String $code
56 *
57 * @return Array
58 */
59 final protected function _response($data = null, $code = 'rpcok') {
60 return array(
61 'response' => $code,
62 'data' => $data
63 );
64 }
65
66 /**
67 * Return an error in the expected format
68 *
69 * @param String $code
70 * @param Mixed $data
71 *
72 * @return Array
73 */
74 final protected function _generic_error_response($code = 'central_unspecified', $data = null) {
75 return $this->_response(
76 array(
77 'code' => $code,
78 'data' => $data
79 ),
80 'rpcerror'
81 );
82 }
83
84 /**
85 * Checks whether a backup and a security credentials is required for the given request
86 *
87 * @param array $dir The directory location to check
88 * @return array
89 */
90 final protected function _get_backup_credentials_settings($dir) {
91
92 // Do we need to ask the user for filesystem credentials? when installing and/or deleting items in the given directory
93 $filesystem_method = get_filesystem_method(array(), $dir);
94
95 ob_start();
96 $filesystem_credentials_are_stored = request_filesystem_credentials(site_url(), $filesystem_method);
97 ob_end_clean();
98 $request_filesystem_credentials = ('direct' != $filesystem_method && !$filesystem_credentials_are_stored);
99
100 // Do we need to execute a backup process before installing/managing items
101 $automatic_backups = (class_exists('UpdraftPlus_Options') && class_exists('UpdraftPlus_Addon_Autobackup') && UpdraftPlus_Options::get_updraft_option('updraft_autobackup_default', true)) ? true : false;
102
103 return array(
104 'request_filesystem_credentials' => $request_filesystem_credentials,
105 'automatic_backups' => $automatic_backups
106 );
107 }
108
109 /**
110 * Retrieves the information of the currently installed item (e.g. plugin or theme) through filter
111 *
112 * @param bool $response Indicates whether the installation was a success or failure
113 * @param array $args Extra argument for the hook
114 * @param array $data Contains paths used and other relevant information regarding the file
115 * @return array
116 */
117 final public function get_install_data($response, $args, $data) {
118
119 if ($response) {
120 switch ($args['type']) {
121 case 'plugin':
122 $plugin_data = get_plugins('/'.$data['destination_name']);
123 if (!empty($plugin_data)) {
124 $info = reset($plugin_data);
125 $key = key($plugin_data);
126
127 $info['slug'] = $data['destination_name'].'/'.$key;
128 $this->installed_data = $info;
129 }
130 break;
131 case 'theme':
132 $theme = wp_get_theme($data['destination_name']);
133 if ($theme->exists()) {
134 // Minimalistic info here, if you need to add additional information
135 // you can add them here. For now, the "Name" and "slug" fields will suffice
136 // in the succeeding process.
137 $this->installed_data = array(
138 'Name' => $theme->get('Name'),
139 'slug' => $data['destination_name'],
140 'template' => $theme->get_template()
141 );
142 }
143 break;
144 default:
145 break;
146 }
147 }
148
149 return $response;
150 }
151
152 /**
153 * Installs and activates either a plugin or theme through zip file upload
154 *
155 * @param array $params Parameter array containing information pertaining the currently uploaded item
156 * @param string $type Indicates whether this current process is intended for a 'plugin' or a 'theme' item
157 * @return array
158 */
159 final protected function process_chunk_upload($params, $type) {
160 global $updraftcentral_host_plugin, $updraftcentral_main;
161
162 if (!in_array($type, array('plugin', 'theme'))) {
163 return $this->_generic_error_response('upload_type_not_supported');
164 }
165
166 $permission_error = false;
167 if ('plugin' === $type) {
168 if (!current_user_can('install_plugins') || !current_user_can('activate_plugins')) $permission_error = true;
169 } else {
170 if (!current_user_can('install_themes') || !current_user_can('switch_themes')) $permission_error = true;
171 }
172
173 if ($permission_error) {
174 return $this->_generic_error_response($type.'_insufficient_permission');
175 }
176
177 // Pull any available and writable directory where we can store
178 // our data/file temporarily before running the installation process.
179 $upload_dir = untrailingslashit(get_temp_dir());
180 if (!is_writable($upload_dir)) {
181 $upload_dir = WP_CONTENT_DIR.'/upgrade';
182
183 if (!is_dir($upload_dir)) {
184 $wp_dir = wp_upload_dir();
185 if (!empty($wp_dir['basedir'])) $upload_dir = $wp_dir['basedir'];
186 }
187 }
188
189 // If we haven't found any writable directory to temporarily store our file then
190 // we bail and send an error back to the caller.
191 if (!is_dir($upload_dir) || !is_writable($upload_dir)) {
192 return $this->_generic_error_response('upload_dir_not_available');
193 }
194
195 // Preloads the submitted credentials to the global $_POST variable
196 if (!empty($params) && isset($params['filesystem_credentials'])) {
197 parse_str($params['filesystem_credentials'], $filesystem_credentials);
198 if (is_array($filesystem_credentials)) {
199 foreach ($filesystem_credentials as $key => $value) {
200 // Put them into $_POST, which is where request_filesystem_credentials() checks for them.
201 $_POST[$key] = $value;
202 }
203 }
204 }
205
206 // Save uploaded file
207 $filename = basename($params['filename']).md5(get_home_url());
208 $is_chunked = false;
209
210 if (isset($params['chunks']) && 1 < (int) $params['chunks']) {
211 $filename .= '.part';
212 $is_chunked = true;
213 }
214
215 if (!$is_chunked || ($is_chunked && isset($params['chunk']) && 0 === (int) $params['chunk'])) {
216 // if it's not a chunk upload or if it's a chunk upload operation and the current chunk variable is zero, then it means a new upload operation has just begun therefore we should remove previous left-over file (if any and due to error during the previous upload of the same file), because it can lead to a corrupt/invalid zip file (we use file_put_contents a few lines below with FILE_APPEND attribute)
217 if (file_exists($upload_dir.'/'.$filename) && !unlink($upload_dir.'/'.$filename)) return $this->_generic_error_response('unable_to_delete_existing_file');
218 }
219
220 if (empty($params['data'])) {
221 return $this->_generic_error_response('data_empty_or_invalid');
222 }
223
224 $result = file_put_contents($upload_dir.'/'.$filename, base64_decode($params['data']), FILE_APPEND | LOCK_EX);
225
226 if (false === $result) {
227 return $this->_generic_error_response('unable_to_write_content');
228 }
229
230 // Set $install_now to true for single upload and for the last chunk of a multi-chunks upload process
231 $install_now = true;
232
233 if ($is_chunked) {
234 if ($params['chunk'] == (int) $params['chunks'] - 1) {
235 // If this is the last chunk of the request, then we're going to restore the
236 // original filename of the file (without the '.part') since our upload is now complete.
237 $orig_filename = basename($filename, '.part');
238 $success = rename($upload_dir.'/'.$filename, $upload_dir.'/'.$orig_filename);
239
240 // If renaming the file was successful then restore the original name and override the $filename variable.
241 // Overriding the $filename variable makes it easy for us to use the same variable for both
242 // non-chunked and chunked zip file for the installation process.
243 if ($success) {
244 $filename = $orig_filename;
245 } else {
246 return $this->_generic_error_response('unable_to_rename_file');
247 }
248 } else {
249 // Bypass installation for now since we're waiting for the last chunk to arrive
250 // to complete the uploading of the zip file.
251 $install_now = false;
252 }
253 }
254
255 // Everything is already good (upload completed), thus, we proceed with the installation
256 if ($install_now) {
257
258 // We have successfully uploaded the zip file in this location with its original filename intact.
259 $zip_filepath = $upload_dir.'/'.$filename;
260
261 // Making sure that the file does actually exists, since we've just run through
262 // a renaming process above.
263 if (file_exists($zip_filepath)) {
264 add_filter('upgrader_post_install', array($this, 'get_install_data'), 10, 3);
265
266 // WP < 3.7
267 if (!class_exists('Automatic_Upgrader_Skin')) include_once(UPDRAFTCENTRAL_CLIENT_DIR.'/classes/class-automatic-upgrader-skin.php');
268 require_once(UPDRAFTCENTRAL_CLIENT_DIR.'/classes/class-updraftcentral-wp-upgrader.php');
269
270 $skin = new Automatic_Upgrader_Skin();
271 $upgrader = ('plugin' === $type) ? new UpdraftCentral_Plugin_Upgrader($skin) : new UpdraftCentral_Theme_Upgrader($skin);
272
273 $install_result = $upgrader->install($zip_filepath);
274 remove_filter('upgrader_post_install', array($this, 'get_install_data'), 10, 3);
275
276 // Remove zip file on success and on error (cleanup)
277 if ($install_result || is_null($install_result) || is_wp_error($install_result)) {
278 @unlink($zip_filepath);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise if the file doesn't exist.
279 }
280
281 if (false === $install_result || is_wp_error($install_result)) {
282 $message = $updraftcentral_host_plugin->retrieve_show_message('unable_to_connect');
283 if (is_wp_error($install_result)) $message = $install_result->get_error_message();
284
285 return $this->_generic_error_response($type.'_install_failed', array('message' => $message));
286 } else {
287 // Pull installed data
288 $data = $this->installed_data;
289
290 // For WP 3.4 the intended filter hook isn't working or not available
291 // so we're going to pull the data manually.
292 if ($install_result && empty($data)) {
293 $result = $this->get_install_data($install_result, array('type' => $type), $skin->result);
294 if ($result) {
295 // Getting the installed data one more time after manually calling
296 // the "get_install_data" function.
297 $data = $this->installed_data;
298 }
299 }
300
301 if (!empty($data)) {
302 // Activate item if set
303 $is_active = ('plugin' === $type) ? is_plugin_active($data['slug']) : ((wp_get_theme()->get('Name') === $data['Name']) ? true : false);
304
305 if ((bool) $params['activate'] && !$is_active) {
306 if ('plugin' === $type) {
307 if (is_multisite()) {
308 $activate = activate_plugin($data['slug'], '', true);
309 } else {
310 $activate = activate_plugin($data['slug']);
311 }
312 } else {
313 // In order to make it compatible with older versions of switch_theme which takes two
314 // arguments we're going to pass two arguments instead of one. Latest versions have backward
315 // compatibility so it's safe to do it this way.
316 switch_theme($data['template'], $data['slug']);
317 $activate = (wp_get_theme()->get_stylesheet() === $data['slug']) ? true : false;
318 }
319
320 if (false === $activate || is_wp_error($activate)) {
321 $wp_version = $updraftcentral_main->get_wordpress_version();
322
323 $message = is_wp_error($activate) ? array('message' => $activate->get_error_message()) : array('message' => sprintf($updraftcentral_host_plugin->retrieve_show_message('unable_to_activate'), $type, $type, $wp_version));
324 return $this->_generic_error_response('unable_to_activate_'.$type, $message);
325 }
326 }
327
328 return $this->_response(
329 array(
330 'installed' => true,
331 'installed_data' => $data,
332 )
333 );
334 }
335
336 if (is_wp_error($skin->result)) {
337 $code = $skin->result->get_error_code();
338 $message = $skin->result->get_error_message();
339
340 $error_data = $skin->result->get_error_data($code);
341 if (!empty($error_data)) {
342 if (is_array($error_data)) $error_data = json_encode($error_data);
343
344 $message .= ' '.$error_data;
345 }
346
347 return $this->_generic_error_response($code, $message);
348 } else {
349 return $this->_response(
350 array(
351 'installed' => false,
352 'message' => sprintf($updraftcentral_host_plugin->retrieve_show_message('unable_to_install'), $type, $type, $type, $type, 'wp-content/'.$type.'s'),
353 )
354 );
355 }
356 }
357 }
358 } else {
359 // Returning response to a chunk requests while still processing and
360 // completing the file upload process. If we don't return a positive response
361 // for every chunk requests then the caller will assumed an error has occurred
362 // and will eventually stop the upload process.
363 return $this->_response(array('in_progress' => true));
364 }
365 }
366 }
367