PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.3 6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 All 156 releases
← All changes | class/class-mainwp-api-manager-plugin-update.php +185 -157 4.6.0.1 → 6.2.2 View file →
@@ -10,9 +10,9 @@
10 10 namespace MainWP\Dashboard;
11 11
12 12 // Exit if accessed directly.
13 13 if ( ! defined( 'ABSPATH' ) ) {
14 - exit;
14 + exit;
15 15 }
16 16
17 17 /**
18 18 * Class MainWP_Api_Manager_Plugin_Update
@@ -23,195 +23,223 @@
23 23 * @author Todd Lahman LLC
24 24 * @copyright Copyright (c) Todd Lahman LLC
25 25 * @since 1.0.0
26 26 */
27 -class MainWP_Api_Manager_Plugin_Update {
27 +class MainWP_Api_Manager_Plugin_Update { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
28 28
29 - /**
30 - * Protected static variable to hold the instance.
31 - *
32 - * @var null Default value.
33 - */
34 - protected static $instance = null;
29 + /**
30 + * Protected static variable to hold the instance.
31 + *
32 + * @var null Default value.
33 + */
34 + protected static $instance = null;
35 35
36 - /**
37 - * Method instance()
38 - *
39 - * @static
40 - * @return class instance
41 - */
42 - public static function instance() {
43 - if ( is_null( self::$instance ) ) {
44 - self::$instance = new self();
45 - }
36 + /**
37 + * Method instance()
38 + *
39 + * @static
40 + * @return class instance
41 + */
42 + public static function instance() {
43 + if ( is_null( static::$instance ) ) {
44 + static::$instance = new self();
45 + }
46 46
47 - return self::$instance;
48 - }
47 + return static::$instance;
48 + }
49 49
50 - /**
51 - * MainWP_Api_Manager_Plugin_Update constructor.
52 - *
53 - * Run each time the class is called.
54 - */
55 - public function __construct() {
50 + /**
51 + * MainWP_Api_Manager_Plugin_Update constructor.
52 + *
53 + * Run each time the class is called.
54 + */
55 + public function __construct() {
56 + // API data.
57 + }
56 58
57 - // API data.
58 - }
59 + /**
60 + * Create upgrade request API URL.
61 + *
62 + * @param array $args Request arguments.
63 + *
64 + * @return string Build URL.
65 + *
66 + * @uses \MainWP\Dashboard\MainWP_Api_Manager::get_upgrade_url()
67 + */
68 + private function create_upgrade_api_url( $args ) {
69 + $upgrade_url = esc_url_raw( add_query_arg( 'mainwp-api', 'am-software-api', MainWP_Api_Manager::instance()->get_upgrade_url() ) );
59 70
71 + $query_url = '';
72 + foreach ( $args as $key => $value ) {
73 + $query_url .= $key . '=' . rawurlencode( $value ) . '&';
74 + }
75 + $query_url = rtrim( $query_url, '&' );
60 76
61 - /**
62 - * Create upgrade request API URL.
63 - *
64 - * @param array $args Request arguments.
65 - * @param bool $bulk_check Bulk check request.
66 - *
67 - * @return string Build URL.
68 - *
69 - * @uses \MainWP\Dashboard\MainWP_Api_Manager::get_upgrade_url()
70 - */
71 - private function create_upgrade_api_url( $args, $bulk_check = true ) {
72 - if ( $bulk_check ) {
73 - $upgrade_url = esc_url_raw( add_query_arg( 'mainwp-api', 'am-software-api', MainWP_Api_Manager::instance()->get_upgrade_url() ) );
74 - } else {
75 - $upgrade_url = esc_url_raw( add_query_arg( 'mainwp-api', 'am-software-api', MainWP_Api_Manager::instance()->get_upgrade_url() ) ); // old: wc-api/upgrade-api.
76 - }
77 + return $upgrade_url . '&' . $query_url;
78 + }
77 79
78 - $query_url = '';
79 - foreach ( $args as $key => $value ) {
80 - $query_url .= $key . '=' . rawurlencode( $value ) . '&';
81 - }
82 - $query_url = rtrim( $query_url, '&' );
80 + /**
81 + * Returns plugin information in an array.
82 + *
83 + * @param array $plugin Plugin to check.
84 + *
85 + * @return array Plugin information.
86 + */
87 + public function update_check( $plugin ) {
83 88
84 - return $upgrade_url . '&' . $query_url;
85 - }
89 + $args = array(
90 + 'request' => 'pluginupdatecheck',
91 + 'plugin_name' => $plugin['plugin_name'],
92 + 'version' => $plugin['software_version'],
93 + 'product_id' => $plugin['product_id'],
94 + 'api_key' => $plugin['api_key'],
95 + 'instance' => $plugin['instance'],
96 + 'software_version' => $plugin['software_version'],
97 + 'extra' => isset( $plugin['extra'] ) ? $plugin['extra'] : '',
98 + );
86 99
87 - /**
88 - * Returns plugin information in an array.
89 - *
90 - * @param array $plugin Plugin to check.
91 - *
92 - * @return array Plugin information.
93 - */
94 - public function update_check( $plugin ) {
100 + // Check for a plugin update.
101 + return $this->plugin_information( $args ); // pluginupdatecheck.
102 + }
95 103
96 - $args = array(
97 - 'request' => 'pluginupdatecheck',
98 - 'plugin_name' => $plugin['plugin_name'],
99 - 'version' => $plugin['software_version'],
100 - 'product_id' => $plugin['product_id'],
101 - 'api_key' => $plugin['api_key'],
102 - 'instance' => $plugin['instance'],
103 - 'software_version' => $plugin['software_version'],
104 - 'extra' => isset( $plugin['extra'] ) ? $plugin['extra'] : '',
105 - );
106 104
107 - // Check for a plugin update.
108 - return $this->plugin_information( $args ); // pluginupdatecheck.
109 - }
105 + /**
106 + * Check if bulkupdateapi is true|false & grab domain name adn extensions list.
107 + *
108 + * @param array $plugins List of plugins (extensions).
109 + *
110 + * @return array Plugin Information & bulkupdatecheck.
111 + */
112 + public function bulk_update_check( $plugins ) {
110 113
114 + $args = array(
115 + 'request' => 'bulkupdatecheck',
116 + 'extensions' => base64_encode( wp_json_encode( $plugins ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
117 + 'json' => true,
118 + );
111 119
112 - /**
113 - * Check if bulkupdateapi is true|false & grab domain name adn extensions list.
114 - *
115 - * @param array $plugins List of plugins (extensions).
116 - *
117 - * @return array Plugin Information & bulkupdatecheck.
118 - */
119 - public function bulk_update_check( $plugins ) {
120 + $mainwp_api_key = MainWP_Api_Manager_Key::instance()->get_decrypt_master_api_key();
120 121
121 - $args = array(
122 - 'request' => 'bulkupdatecheck',
123 - 'extensions' => base64_encode( wp_json_encode( $plugins ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
124 - 'json' => true,
125 - );
122 + if ( ! empty( $mainwp_api_key ) ) {
123 + $args['api_key'] = $mainwp_api_key;
124 + }
126 125
127 - $mainwp_api_key = MainWP_Api_Manager_Key::instance()->get_decrypt_master_api_key();
126 + return $this->plugin_information( $args, true ); // bulkupdatecheck.
127 + }
128 128
129 - if ( ! empty( $mainwp_api_key ) ) {
130 - $args['api_key'] = $mainwp_api_key;
131 - }
132 129
133 - return $this->plugin_information( $args, true ); // bulkupdatecheck.
134 - }
130 + /**
131 + * Check $args, if there is a response, an object exists & response is not false.
132 + *
133 + * @param array $args Request arguments.
134 + *
135 + * @return array|false $response Plugin information.
136 + */
137 + public function request( $args ) {
138 + $args['request'] = 'plugininformation';
135 139
140 + $response = $this->plugin_information( $args ); // plugininformation.
136 141
137 - /**
138 - * Check $args, if there is a response, an object exists & response is not false.
139 - *
140 - * @param array $args Request arguments.
141 - *
142 - * @return array|false $response Plugin information.
143 - */
144 - public function request( $args ) {
145 - $args['request'] = 'plugininformation';
142 + // If everything is okay return the response.
143 + if ( isset( $response ) && is_object( $response ) && false !== $response ) {
144 + return $response;
145 + }
146 + return false;
147 + }
146 148
147 - $response = $this->plugin_information( $args ); // plugininformation.
149 + /**
150 + * Sends and receives data to and from the server API.
151 + *
152 + * @access public
153 + *
154 + * @param array $args Request arguments.
155 + * @param bool $bulk_check Check if updating in bulk true|false.
156 + *
157 + * @return array|false Plugin information.
158 + * @since 1.0.0
159 + *
160 + * @uses \MainWP\Dashboard\MainWP_System_Utility::maybe_unserialyze()
161 + */
162 + public function plugin_information( $args, $bulk_check = false ) {
148 163
149 - // If everything is okay return the response.
150 - if ( isset( $response ) && is_object( $response ) && false !== $response ) {
151 - return $response;
152 - }
153 - }
164 + $args['object'] = MainWP_Api_Manager::instance()->get_domain();
154 165
155 - /**
156 - * Sends and receives data to and from the server API.
157 - *
158 - * @access public
159 - *
160 - * @param array $args Request arguments.
161 - * @param bool $bulk_check Check if updating in bulk true|false.
162 - *
163 - * @return array|false Plugin information.
164 - * @since 1.0.0
165 - *
166 - * @uses \MainWP\Dashboard\MainWP_System_Utility::maybe_unserialyze()
167 - */
168 - public function plugin_information( $args, $bulk_check = false ) {
166 + $target_url = $this->create_upgrade_api_url( $args );
167 + $default = array(
168 + 'timeout' => 150,
169 + 'sslverify' => 1,
170 + );
169 171
170 - $args['object'] = MainWP_Api_Manager::instance()->get_domain();
172 + $params = apply_filters( 'mainwp_plugin_information_sslverify', $default, $args );
171 173
172 - $target_url = $this->create_upgrade_api_url( $args, $bulk_check );
173 - $default = array(
174 - 'timeout' => 150,
175 - 'sslverify' => 1,
176 - );
174 + // MWP-1546 (Codex follow-up): redact api_key everywhere it appears
175 + // before handing data to the logger. The previous code only masked
176 + // the top-level api_key; the per-extension api_keys nested inside
177 + // the bulk-check `extensions` payload (and the api_key= param baked
178 + // into target_url itself) were both written to the log in plaintext.
179 + // For installs running the file logger that turned every cron
180 + // update-check tick into a persistence path for credentials.
181 + $log_args = $args;
182 + if ( isset( $log_args['api_key'] ) ) {
183 + $log_args['api_key'] = '***';
184 + }
177 185
178 - $params = apply_filters( 'mainwp_plugin_information_sslverify', $default, $args );
186 + if ( ! empty( $log_args['extensions'] ) ) {
187 + $log_exts = json_decode( base64_decode( $log_args['extensions'] ), true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- NOSONAR base64_decode used for http encoding compatible.
188 + if ( is_array( $log_exts ) ) {
189 + foreach ( $log_exts as $log_ext_key => $log_ext ) {
190 + if ( is_array( $log_ext ) && isset( $log_ext['api_key'] ) ) {
191 + $log_exts[ $log_ext_key ]['api_key'] = '***';
192 + }
193 + }
194 + } else {
195 + $log_exts = array();
196 + }
197 + $log_args['_decoded_extensions'] = $log_exts;
198 + unset( $log_args['extensions'] );
199 + }
179 200
180 - $request = wp_remote_get(
181 - $target_url,
182 - $params
183 - );
201 + // Strip api_key from the URL query string before logging.
202 + $log_target_url = preg_replace( '/(\?|&)api_key=[^&]*/', '$1api_key=***', $target_url );
184 203
185 - if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) {
186 - return false;
187 - }
204 + MainWP_Logger::instance()->log_events( 'extension-updates-check', sprintf( '[target_url=%s] :: [params=%s] :: [bulk_check=%s]', $log_target_url, print_r( $log_args, true ), $bulk_check ? 'true' : 'false' ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions -- print_r used for debugging.
188 205
189 - $response = wp_remote_retrieve_body( $request );
206 + $request = wp_remote_get(
207 + $target_url,
208 + $params
209 + );
190 210
191 - if ( isset( $args['json'] ) ) { // bulkupdatecheck: json.
192 - $response = json_decode( $response, true );
193 - } else { // pluginupdatecheck, plugininformation : serialize.
194 - $response = unserialize( $response ); // phpcs:ignore -- data from extensions, to compatible.
195 - }
211 + if ( is_wp_error( $request ) || wp_remote_retrieve_response_code( $request ) !== 200 ) {
212 + return false;
213 + }
196 214
197 - /**
198 - * For debugging errors from the API
199 - * For errors like: unserialize(): Error at offset 0 of 170 bytes
200 - * Comment out $response above first
201 - */
202 - if ( ! $bulk_check ) {
203 - if ( is_object( $response ) ) {
204 - if ( isset( $response->package ) ) {
205 - $response->package = apply_filters( 'mainwp_api_manager_upgrade_package_url', $response->package, $response );
206 - }
207 - return $response;
208 - }
209 - } elseif ( is_array( $response ) ) {
210 - return $response;
211 - }
215 + $response = wp_remote_retrieve_body( $request );
212 216
213 - return false;
214 - }
217 + MainWP_Logger::instance()->log_events( 'extension-updates-check', sprintf( '[response=%s]', $response ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions -- print_r used for debugging.
218 +
219 + if ( isset( $args['json'] ) ) { // bulkupdatecheck: json.
220 + $response = json_decode( $response, true );
221 + } else { // pluginupdatecheck, plugininformation : serialize.
222 + $response = unserialize( $response ); // phpcs:ignore -- data from extensions, to compatible.
223 + }
224 +
225 + /**
226 + * For debugging errors from the API
227 + * For errors like: unserialize(): Error at offset 0 of 170 bytes
228 + * Comment out $response above first
229 + */
230 + if ( ! $bulk_check ) {
231 + if ( is_object( $response ) ) {
232 + if ( isset( $response->package ) ) {
233 + $response->package = apply_filters( 'mainwp_api_manager_upgrade_package_url', $response->package, $response );
234 + }
235 + return $response;
236 + }
237 + } elseif ( is_array( $response ) ) {
238 + return $response;
239 + }
240 +
241 + return false;
242 + }
215 243 }
216 244
217 245 // End of class.