PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | jetpack_vendor/automattic/jetpack-waf/src/class-waf-request.php +57 -21 13.3.3 → 16.3 View file →
@@ -8,12 +8,14 @@
8 8 namespace Automattic\Jetpack\Waf;
9 9
10 10 require_once __DIR__ . '/functions.php';
11 11
12 +<<<'PHAN'
13 +@phan-type RequestFile = array{ name: string, filename: string }
14 +PHAN;
15 +
12 16 /**
13 17 * Request representation.
14 - *
15 - * @template RequestFile as array{ name: string, filename: string }
16 18 */
17 19 class Waf_Request {
18 20 /**
19 21 * The request URL, broken into three pieces: the host, the filename, and the query string
@@ -19,9 +21,9 @@
19 21 * The request URL, broken into three pieces: the host, the filename, and the query string
20 22 *
21 23 * @example for `https://wordpress.com/index.php?myvar=red`
22 24 * $this->url = [ 'https://wordpress.com', '/index.php', '?myvar=red' ]
23 - * @var array{ 0: string, 1: string, 2: string }|null
25 + * @var array{0: string, 1: string, 2: string}|null
24 26 */
25 27 protected $url = null;
26 28
27 29 /**
@@ -116,13 +118,12 @@
116 118
117 119 /**
118 120 * Returns the headers that were sent with this request
119 121 *
120 - * @return array{ 0: string, 1: scalar }[]
122 + * @return array{0: string, 1: scalar}[]
121 123 */
122 124 public function get_headers() {
123 125 $value = array();
124 - $has_content_type = false;
125 126 $has_content_length = false;
126 127 foreach ( $_SERVER as $k => $v ) {
127 128 $k = strtolower( $k );
128 129 if ( 'http_' === substr( $k, 0, 5 ) ) {
@@ -127,19 +128,14 @@
127 128 $k = strtolower( $k );
128 129 if ( 'http_' === substr( $k, 0, 5 ) ) {
129 130 $value[] = array( $this->normalize_header_name( substr( $k, 5 ) ), $v );
130 131 } elseif ( 'content_type' === $k && '' !== $v ) {
131 - $has_content_type = true;
132 - $value[] = array( 'content-type', $v );
132 + $value[] = array( 'content-type', $v );
133 133 } elseif ( 'content_length' === $k && '' !== $v ) {
134 134 $has_content_length = true;
135 135 $value[] = array( 'content-length', $v );
136 136 }
137 137 }
138 - if ( ! $has_content_type ) {
139 - // default Content-Type per RFC 7231 section 3.1.5.5.
140 - $value[] = array( 'content-type', 'application/octet-stream' );
141 - }
142 138 if ( ! $has_content_length ) {
143 139 $value[] = array( 'content-length', '0' );
144 140 }
145 141
@@ -197,9 +193,9 @@
197 193 /**
198 194 * Returns the URL parts for this request.
199 195 *
200 196 * @see $this->url
201 - * @return array{ 0: string, 1: string, 2: string }
197 + * @return array{0: string, 1: string, 2: string}
202 198 */
203 199 protected function get_url() {
204 200 if ( null !== $this->url ) {
205 201 return $this->url;
@@ -310,9 +306,9 @@
310 306
311 307 /**
312 308 * Returns the cookies
313 309 *
314 - * @return array<string, string>
310 + * @return array{string, scalar}[]
315 311 */
316 312 public function get_cookies() {
317 313 return flatten_array( $_COOKIE );
318 314 }
@@ -319,9 +315,9 @@
319 315
320 316 /**
321 317 * Returns the GET variables
322 318 *
323 - * @return array<string, mixed|array>
319 + * @return array{string, scalar}[]
324 320 */
325 321 public function get_get_vars() {
326 322 return flatten_array( $_GET );
327 323 }
@@ -326,20 +322,60 @@
326 322 return flatten_array( $_GET );
327 323 }
328 324
329 325 /**
326 + * Returns the POST variables from a JSON body
327 + *
328 + * @return array{string, scalar}[]
329 + */
330 + private function get_json_post_vars() {
331 + $decoded_json = json_decode( $this->get_body(), true ) ?? array();
332 + return flatten_array( $decoded_json, 'json', true );
333 + }
334 +
335 + /**
336 + * Returns the POST variables from a urlencoded body
337 + *
338 + * @return array{string, scalar}[]
339 + */
340 + private function get_urlencoded_post_vars() {
341 + parse_str( $this->get_body(), $params );
342 + return flatten_array( $params );
343 + }
344 +
345 + /**
330 346 * Returns the POST variables
331 347 *
332 - * @return array<string, mixed|array>
348 + * @param string $body_processor Manually specifiy the method to use to process the body. Options are 'URLENCODED' and 'JSON'.
349 + *
350 + * @return array{string, scalar}[]
333 351 */
334 - public function get_post_vars() {
335 - // Attempt to decode JSON requests.
336 - if ( strpos( $this->get_header( 'content-type' ), 'application/json' ) !== false ) {
337 - $decoded_json = json_decode( $this->get_body(), true ) ?? array();
338 - return flatten_array( $decoded_json, 'json', true );
352 + public function get_post_vars( string $body_processor = '' ) {
353 + $content_type = $this->get_header( 'content-type' );
354 +
355 + // If the body processor is specified by the rules file, trust it.
356 + if ( 'URLENCODED' === $body_processor ) {
357 + return $this->get_urlencoded_post_vars();
339 358 }
359 + if ( 'JSON' === $body_processor ) {
360 + return $this->get_json_post_vars();
361 + }
340 362
341 - return flatten_array( $_POST );
363 + // Otherwise, use $_POST if it's not empty.
364 + if ( ! empty( $_POST ) ) {
365 + return flatten_array( $_POST );
366 + }
367 +
368 + // Lastly, try to parse the body based on the content type.
369 + if ( strpos( $content_type, 'application/json' ) !== false ) {
370 + return $this->get_json_post_vars();
371 + }
372 + if ( strpos( $content_type, 'application/x-www-form-urlencoded' ) !== false ) {
373 + return $this->get_urlencoded_post_vars();
374 + }
375 +
376 + // Don't try to parse any other content types.
377 + return array();
342 378 }
343 379
344 380 /**
345 381 * Returns the files that were uploaded with this request (i.e. what's in the $_FILES superglobal)