| @@ -53,68 +53,31 @@ | ||
| 53 | 53 | if (empty($slug)) { |
| 54 | 54 | return new WP_Error('empty_arg', __('Argument should not be empty.', 'betterdocs')); |
| 55 | 55 | } |
| 56 | 56 | |
| 57 | - // Use core's plugins_api() instead of a hand-rolled request. The old code | |
| 58 | - // POSTed to plaintext http://api.wordpress.org and passed the response | |
| 59 | - // body straight to unserialize(), so anyone able to intercept that | |
| 60 | - // connection could inject a PHP-object-injection payload or a malicious | |
| 61 | - // download_link. plugins_api() talks to api.wordpress.org over HTTPS and | |
| 62 | - // returns a decoded object — no plaintext transport, no unserialize(). | |
| 63 | - if (!function_exists('plugins_api')) { | |
| 64 | - include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; | |
| 65 | - } | |
| 57 | + $response = wp_remote_post( | |
| 58 | + 'http://api.wordpress.org/plugins/info/1.0/', | |
| 59 | + [ | |
| 60 | + 'body' => [ | |
| 61 | + 'action' => 'plugin_information', | |
| 62 | + 'request' => serialize((object) [ | |
| 63 | + 'slug' => $slug, | |
| 64 | + 'fields' => [ | |
| 65 | + 'version' => false, | |
| 66 | + ], | |
| 67 | + ]), | |
| 68 | + ], | |
| 69 | + ] | |
| 70 | + ); | |
| 66 | 71 | |
| 67 | - $response = plugins_api('plugin_information', [ | |
| 68 | - 'slug' => $slug, | |
| 69 | - 'fields' => [ | |
| 70 | - 'version' => true, | |
| 71 | - ], | |
| 72 | - ]); | |
| 73 | - | |
| 74 | - if (is_wp_error($response) || !is_object($response)) { | |
| 75 | - return is_wp_error($response) ? $response : new WP_Error('plugins_api_failed', __('Could not retrieve plugin information.', 'betterdocs')); | |
| 72 | + if (is_wp_error($response)) { | |
| 73 | + return $response; | |
| 76 | 74 | } |
| 77 | 75 | |
| 78 | - // Bind the package to the requested slug and to an https WordPress.org | |
| 79 | - // host before anything installs it. | |
| 80 | - if (isset($response->slug) && $response->slug !== $slug) { | |
| 81 | - return new WP_Error('slug_mismatch', __('Plugin information did not match the requested plugin.', 'betterdocs')); | |
| 82 | - } | |
| 83 | - | |
| 84 | - if (isset($response->download_link) && !$this->is_allowed_package_url($response->download_link)) { | |
| 85 | - return new WP_Error('bad_package_host', __('Plugin download URL is not an approved WordPress.org address.', 'betterdocs')); | |
| 86 | - } | |
| 87 | - | |
| 88 | - return $response; | |
| 76 | + return unserialize(wp_remote_retrieve_body($response)); | |
| 89 | 77 | } |
| 90 | 78 | |
| 91 | 79 | /** |
| 92 | - * Whether a package URL is safe to hand to the upgrader: https on a | |
| 93 | - * WordPress.org host. Prevents a tampered response from redirecting the | |
| 94 | - * install to an attacker-controlled archive. | |
| 95 | - * | |
| 96 | - * @param string $url | |
| 97 | - * @return bool | |
| 98 | - */ | |
| 99 | - protected function is_allowed_package_url($url) | |
| 100 | - { | |
| 101 | - if (!is_string($url) || $url === '') { | |
| 102 | - return false; | |
| 103 | - } | |
| 104 | - | |
| 105 | - $parts = wp_parse_url($url); | |
| 106 | - | |
| 107 | - if (empty($parts['scheme']) || strtolower($parts['scheme']) !== 'https' || empty($parts['host'])) { | |
| 108 | - return false; | |
| 109 | - } | |
| 110 | - | |
| 111 | - $host = strtolower($parts['host']); | |
| 112 | - | |
| 113 | - return in_array($host, ['downloads.wordpress.org', 'wordpress.org', 'www.wordpress.org'], true); | |
| 114 | - } | |
| 115 | - | |
| 116 | - /** | |
| 117 | 80 | * install_plugin |
| 118 | 81 | * |
| 119 | 82 | * @param mixed $slug |
| 120 | 83 | * @param bool $active |
| @@ -166,9 +129,9 @@ | ||
| 166 | 129 | * @return mixed bool|WP_Error |
| 167 | 130 | */ |
| 168 | 131 | public function upgrade_plugin($basename = '') |
| 169 | 132 | { |
| 170 | - if (empty($basename)) { | |
| 133 | + if (empty($slug)) { | |
| 171 | 134 | return new WP_Error('empty_arg', __('Argument should not be empty.', 'betterdocs')); |
| 172 | 135 | } |
| 173 | 136 | |
| 174 | 137 | include_once ABSPATH . 'wp-admin/includes/file.php'; |
| @@ -188,13 +151,12 @@ | ||
| 188 | 151 | if(!current_user_can( 'install_plugins' )) { |
| 189 | 152 | wp_send_json_error(__('you are not allowed to do this action', 'betterdocs')); |
| 190 | 153 | } |
| 191 | 154 | |
| 192 | - $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : ''; | |
| 155 | + $slug = isset( $_POST['slug'] ) ? sanitize_text_field( $_POST['slug'] ) : ''; | |
| 193 | 156 | $result = $this->install_plugin( $slug ); |
| 194 | 157 | |
| 195 | - $promotype = isset( $_POST['promotype'] ) ? sanitize_text_field( wp_unslash( $_POST['promotype'] ) ) : ''; | |
| 196 | - if ( 'eb-banner' === $promotype ) { | |
| 158 | + if( isset( $_POST['promotype'] ) && 'eb-banner' === $_POST['promotype'] ) { | |
| 197 | 159 | wp_remote_get( 'https://essential-addons.com/essential-blocks-install-gutenberg' ); |
| 198 | 160 | } |
| 199 | 161 | |
| 200 | 162 | if ( is_wp_error( $result ) ) { |
| @@ -211,9 +173,9 @@ | ||
| 211 | 173 | if(!current_user_can( 'update_plugins' )) { |
| 212 | 174 | wp_send_json_error(__('you are not allowed to do this action', 'betterdocs')); |
| 213 | 175 | } |
| 214 | 176 | |
| 215 | - $basename = isset( $_POST['basename'] ) ? sanitize_text_field( wp_unslash( $_POST['basename'] ) ) : ''; | |
| 177 | + $basename = isset( $_POST['basename'] ) ? sanitize_text_field( $_POST['basename'] ) : ''; | |
| 216 | 178 | $result = $this->upgrade_plugin( $basename ); |
| 217 | 179 | |
| 218 | 180 | if (is_wp_error($result)) { |
| 219 | 181 | wp_send_json_error($result->get_error_message()); |
| @@ -230,9 +192,9 @@ | ||
| 230 | 192 | if(!current_user_can( 'activate_plugins' )) { |
| 231 | 193 | wp_send_json_error(__('you are not allowed to do this action', 'betterdocs')); |
| 232 | 194 | } |
| 233 | 195 | |
| 234 | - $basename = isset( $_POST['basename'] ) ? sanitize_text_field( wp_unslash( $_POST['basename'] ) ) : ''; | |
| 196 | + $basename = isset( $_POST['basename'] ) ? sanitize_text_field( $_POST['basename'] ) : ''; | |
| 235 | 197 | $result = activate_plugin( $basename, '', false, true ); |
| 236 | 198 | |
| 237 | 199 | if ( is_wp_error( $result ) ) { |
| 238 | 200 | wp_send_json_error( $result->get_error_message() ); |
| @@ -251,9 +213,9 @@ | ||
| 251 | 213 | if ( ! current_user_can( 'activate_plugins' ) ) { |
| 252 | 214 | wp_send_json_error( __( 'you are not allowed to do this action', 'betterdocs' ) ); |
| 253 | 215 | } |
| 254 | 216 | |
| 255 | - $basename = isset( $_POST['basename'] ) ? sanitize_text_field( wp_unslash( $_POST['basename'] ) ) : ''; | |
| 217 | + $basename = isset( $_POST['basename'] ) ? sanitize_text_field( $_POST['basename'] ) : ''; | |
| 256 | 218 | deactivate_plugins( $basename, true ); |
| 257 | 219 | |
| 258 | 220 | wp_send_json_success( __( 'Plugin is deactivated successfully!', 'betterdocs' ) ); |
| 259 | 221 | } |
| @@ -260,10 +222,9 @@ | ||
| 260 | 222 | |
| 261 | 223 | public function ajax_auto_active_even_not_installed() { |
| 262 | 224 | check_ajax_referer( 'betterdocs-wpdeveloper-plugins', 'security' ); |
| 263 | 225 | |
| 264 | - $basename = isset( $_POST['basename'] ) ? sanitize_text_field( wp_unslash( $_POST['basename'] ) ) : ''; | |
| 265 | - if ( $this->get_local_plugin_data( $basename ) === false ) { | |
| 226 | + if ( $this->get_local_plugin_data( $_POST['basename'] ) === false ) { | |
| 266 | 227 | $this->ajax_install_plugin(); |
| 267 | 228 | } else { |
| 268 | 229 | $this->ajax_activate_plugin(); |
| 269 | 230 | } |