| @@ -1,9 +1,10 @@ | ||
| 1 | 1 | <?php |
| 2 | + | |
| 2 | 3 | if (!defined('ABSPATH') && !defined('MCDATAPATH')) exit; |
| 3 | 4 | |
| 4 | -if (!class_exists('WPRProtectRequest_V547')) : | |
| 5 | -class WPRProtectRequest_V547 { | |
| 5 | +if (!class_exists('WPRProtectRequest_V672')) : | |
| 6 | +class WPRProtectRequest_V672 { | |
| 6 | 7 | public $ip; |
| 7 | 8 | public $host = ''; |
| 8 | 9 | public $uri; |
| 9 | 10 | public $method = ''; |
| @@ -13,15 +14,35 @@ | ||
| 13 | 14 | public $post_params; |
| 14 | 15 | public $cookies; |
| 15 | 16 | public $headers = array(); |
| 16 | 17 | public $file_names = array(); |
| 18 | + public $json_params = array(); | |
| 19 | + public $raw_body = ''; | |
| 17 | 20 | public $files; |
| 18 | 21 | public $respcode; |
| 19 | - public $status = WPRProtectRequest_V547::STATUS_ALLOWED; | |
| 20 | - public $category = WPRProtectRequest_V547::CATEGORY_NORMAL; | |
| 22 | + public $status = WPRProtectRequest_V672::STATUS_ALLOWED; | |
| 23 | + public $category = WPRProtectRequest_V672::CATEGORY_NORMAL; | |
| 21 | 24 | |
| 22 | 25 | public $wp_user; |
| 23 | 26 | |
| 27 | + private $can_get_raw_body = false; | |
| 28 | + private $can_decode_json = false; | |
| 29 | + private $can_get_uploaded_file_content = false; | |
| 30 | + | |
| 31 | + private $max_raw_body_length = 1000000; | |
| 32 | + private $max_json_decode_depth = 512; | |
| 33 | + private $max_uploaded_file_content_length = 8192; | |
| 34 | + private $max_total_uploaded_file_content_length = 65536; | |
| 35 | + | |
| 36 | + private $raw_body_status = 'not_loaded'; | |
| 37 | + private $json_params_status = 'not_loaded'; | |
| 38 | + private $raw_body_truncated = false; | |
| 39 | + private $raw_body_loaded = false; | |
| 40 | + private $json_params_loaded = false; | |
| 41 | + private $uploaded_file_content_statuses = array(); | |
| 42 | + private $uploaded_file_content_cache = array(); | |
| 43 | + private $uploaded_file_content_bytes_read = 0; | |
| 44 | + | |
| 24 | 45 | #XNOTE: SHould be part of Protect. |
| 25 | 46 | const STATUS_ALLOWED = 1; |
| 26 | 47 | const STATUS_BLOCKED = 2; |
| 27 | 48 | const STATUS_BYPASSED = 3; |
| @@ -36,17 +57,46 @@ | ||
| 36 | 57 | const CATEGORY_RULE_ALLOWED = 70; |
| 37 | 58 | const CATEGORY_PRIVATEIP = 80; |
| 38 | 59 | const CATEGORY_GLOBAL_BOT_BLOCKED = 90; |
| 39 | 60 | |
| 40 | - public function __construct($ip_header) { | |
| 41 | - $this->ip = WPRProtectUtils_V547::getIP($ip_header); | |
| 61 | + public function __construct($ip_header, $config) { | |
| 62 | + $this->ip = WPRProtectUtils_V672::getIP($ip_header); | |
| 42 | 63 | $this->timestamp = time(); |
| 43 | - $this->get_params = $_GET; | |
| 64 | + $this->get_params = $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| 44 | 65 | $this->cookies = $_COOKIE; |
| 45 | - $this->post_params = $_POST; | |
| 46 | - $this->files = $_FILES; | |
| 47 | - if (!empty($_FILES)) { | |
| 48 | - foreach ($_FILES as $input => $file) { | |
| 66 | + $this->post_params = $_POST; // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 67 | + $this->files = $_FILES; // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 68 | + | |
| 69 | + if (array_key_exists('cangetrawbody', $config) && is_bool($config['cangetrawbody'])) { | |
| 70 | + $this->can_get_raw_body = $config['cangetrawbody']; | |
| 71 | + } | |
| 72 | + | |
| 73 | + if (array_key_exists('maxrawbodylength', $config) && is_int($config['maxrawbodylength'])) { | |
| 74 | + $this->max_raw_body_length = $config['maxrawbodylength']; | |
| 75 | + } | |
| 76 | + | |
| 77 | + if (array_key_exists('candecodejson', $config) && is_bool($config['candecodejson'])) { | |
| 78 | + $this->can_decode_json = $config['candecodejson']; | |
| 79 | + } | |
| 80 | + | |
| 81 | + if (array_key_exists('maxjsondecodedepth', $config) && is_int($config['maxjsondecodedepth'])) { | |
| 82 | + $this->max_json_decode_depth = $config['maxjsondecodedepth']; | |
| 83 | + } | |
| 84 | + | |
| 85 | + if (array_key_exists('cangetuploadedfilecontent', $config) && is_bool($config['cangetuploadedfilecontent'])) { | |
| 86 | + $this->can_get_uploaded_file_content = $config['cangetuploadedfilecontent']; | |
| 87 | + } | |
| 88 | + | |
| 89 | + if (array_key_exists('maxuploadedfilecontentlength', $config) && is_int($config['maxuploadedfilecontentlength'])) { | |
| 90 | + $this->max_uploaded_file_content_length = $config['maxuploadedfilecontentlength']; | |
| 91 | + } | |
| 92 | + | |
| 93 | + if (array_key_exists('maxtotaluploadedfilecontentlength', $config) && is_int($config['maxtotaluploadedfilecontentlength'])) { | |
| 94 | + $this->max_total_uploaded_file_content_length = $config['maxtotaluploadedfilecontentlength']; | |
| 95 | + } | |
| 96 | + | |
| 97 | + if (!empty($_FILES)) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 98 | + foreach ($_FILES as $input => $file) { // phpcs:ignore WordPress.Security.NonceVerification.Missing | |
| 49 | 99 | $this->file_names[$input] = $file['name']; |
| 50 | 100 | } |
| 51 | 101 | } |
| 52 | 102 | if (is_array($_SERVER)) { |
| @@ -51,53 +101,56 @@ | ||
| 51 | 101 | } |
| 52 | 102 | if (is_array($_SERVER)) { |
| 53 | 103 | foreach ($_SERVER as $key => $value) { |
| 54 | 104 | if (strpos($key, 'HTTP_') === 0) { |
| 55 | - $header = substr($key, 5); | |
| 56 | - $header = str_replace(array(' ', '_'), array('', ' '), $header); | |
| 57 | - $header = ucwords(strtolower($header)); | |
| 58 | - $header = str_replace(' ', '-', $header); | |
| 105 | + $header = $this->normalizeHeaderName($key); | |
| 59 | 106 | $this->headers[$header] = $value; |
| 60 | 107 | } |
| 61 | 108 | } |
| 62 | - if (array_key_exists('CONTENT_TYPE', $_SERVER)) { | |
| 63 | - $this->headers['Content-Type'] = $_SERVER['CONTENT_TYPE']; | |
| 109 | + $content_type = WPRHelper::getRawParam('SERVER', 'CONTENT_TYPE'); | |
| 110 | + if (isset($content_type)) { | |
| 111 | + $this->headers['Content-Type'] = $content_type; | |
| 64 | 112 | } |
| 65 | - if (array_key_exists('CONTENT_LENGTH', $_SERVER)) { | |
| 66 | - $this->headers['Content-Length'] = $_SERVER['CONTENT_LENGTH']; | |
| 113 | + $content_length = WPRHelper::getRawParam('SERVER', 'CONTENT_LENGTH'); | |
| 114 | + if (isset($content_length)) { | |
| 115 | + $this->headers['Content-Length'] = $content_length; | |
| 67 | 116 | } |
| 68 | - if (array_key_exists('REFERER', $_SERVER)) { | |
| 69 | - $this->headers['Referer'] = $_SERVER['REFERER']; | |
| 117 | + $referer = WPRHelper::getRawParam('SERVER', 'REFERER'); | |
| 118 | + if (isset($referer)) { | |
| 119 | + $this->headers['Referer'] = $referer; | |
| 70 | 120 | } |
| 71 | - if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) { | |
| 72 | - $this->headers['User-Agent'] = $_SERVER['HTTP_USER_AGENT']; | |
| 121 | + $http_user_agent = WPRHelper::getRawParam('SERVER', 'HTTP_USER_AGENT'); | |
| 122 | + if (isset($http_user_agent)) { | |
| 123 | + $this->headers['User-Agent'] = $http_user_agent; | |
| 73 | 124 | } |
| 74 | 125 | |
| 75 | 126 | if (array_key_exists('Host', $this->headers)) { |
| 76 | 127 | $this->host = $this->headers['Host']; |
| 77 | 128 | } elseif (array_key_exists('SERVER_NAME', $_SERVER)) { |
| 78 | - $this->host = $_SERVER['SERVER_NAME']; | |
| 129 | + $this->host = WPRHelper::getRawParam('SERVER', 'SERVER_NAME'); | |
| 79 | 130 | } |
| 80 | 131 | |
| 81 | - $this->method = array_key_exists('REQUEST_METHOD', $_SERVER) | |
| 82 | - ? $_SERVER['REQUEST_METHOD'] : 'GET'; | |
| 83 | - $this->uri = array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : ''; | |
| 132 | + $request_method = WPRHelper::getRawParam('SERVER', 'REQUEST_METHOD'); | |
| 133 | + $this->method = isset($request_method) ? $request_method : 'GET'; | |
| 134 | + $request_uri = WPRHelper::getRawParam('SERVER', 'REQUEST_URI'); | |
| 135 | + $this->uri = isset($request_uri) ? $request_uri : ''; | |
| 84 | 136 | $_uri = parse_url($this->uri); |
| 85 | 137 | $this->path = (is_array($_uri) && array_key_exists('path', $_uri)) ? $_uri['path'] : $this->uri; |
| 86 | 138 | } |
| 139 | + | |
| 87 | 140 | } |
| 88 | 141 | |
| 89 | 142 | public static function blacklistedCategories() { |
| 90 | 143 | return array( |
| 91 | - WPRProtectRequest_V547::CATEGORY_BOT_BLOCKED, | |
| 92 | - WPRProtectRequest_V547::CATEGORY_COUNTRY_BLOCKED, | |
| 93 | - WPRProtectRequest_V547::CATEGORY_USER_BLACKLISTED, | |
| 94 | - WPRProtectRequest_V547::CATEGORY_GLOBAL_BOT_BLOCKED | |
| 144 | + WPRProtectRequest_V672::CATEGORY_BOT_BLOCKED, | |
| 145 | + WPRProtectRequest_V672::CATEGORY_COUNTRY_BLOCKED, | |
| 146 | + WPRProtectRequest_V672::CATEGORY_USER_BLACKLISTED, | |
| 147 | + WPRProtectRequest_V672::CATEGORY_GLOBAL_BOT_BLOCKED | |
| 95 | 148 | ); |
| 96 | 149 | } |
| 97 | 150 | |
| 98 | 151 | public static function whitelistedCategories() { |
| 99 | - return array(WPRProtectRequest_V547::CATEGORY_WHITELISTED); | |
| 152 | + return array(WPRProtectRequest_V672::CATEGORY_WHITELISTED); | |
| 100 | 153 | } |
| 101 | 154 | |
| 102 | 155 | public function setRespCode($code) { |
| 103 | 156 | $this->respcode = $code; |
| @@ -136,8 +189,320 @@ | ||
| 136 | 189 | } |
| 137 | 190 | return null; |
| 138 | 191 | } |
| 139 | 192 | |
| 193 | + private function isJsonContentType($content_type) { | |
| 194 | + if (!is_string($content_type)) { | |
| 195 | + return false; | |
| 196 | + } | |
| 197 | + | |
| 198 | + return preg_match('/(^|\s|,)application\/([\w!#\$&-\^\.\+]+\+)?json(\+oembed)?($|\s|;|,)/i', $content_type) === 1; | |
| 199 | + } | |
| 200 | + | |
| 201 | + private function normalizeHeaderName($name) { | |
| 202 | + if (!is_string($name)) { | |
| 203 | + return null; | |
| 204 | + } | |
| 205 | + | |
| 206 | + $name = trim($name); | |
| 207 | + if (stripos($name, 'HTTP_') === 0) { | |
| 208 | + $name = substr($name, 5); | |
| 209 | + } | |
| 210 | + $name = str_replace(array('-', '_'), ' ', $name); | |
| 211 | + return str_replace(' ', '-', ucwords(strtolower($name))); | |
| 212 | + } | |
| 213 | + | |
| 214 | + private function isUploadedFileKey($key) { | |
| 215 | + return is_string($key) || is_int($key); | |
| 216 | + } | |
| 217 | + | |
| 218 | + private function normalizeUploadedFileIndexKeys($index) { | |
| 219 | + if ($index === null) { | |
| 220 | + return array(); | |
| 221 | + } | |
| 222 | + | |
| 223 | + if ($this->isUploadedFileKey($index)) { | |
| 224 | + return array($index); | |
| 225 | + } | |
| 226 | + | |
| 227 | + if (!is_array($index) || empty($index)) { | |
| 228 | + return null; | |
| 229 | + } | |
| 230 | + | |
| 231 | + foreach ($index as $key) { | |
| 232 | + if (!$this->isUploadedFileKey($key)) { | |
| 233 | + return null; | |
| 234 | + } | |
| 235 | + } | |
| 236 | + | |
| 237 | + return array_values($index); | |
| 238 | + } | |
| 239 | + | |
| 240 | + private function buildUploadedFileStatusKey($field_name, $index_keys) { | |
| 241 | + $status_key = (string) $field_name; | |
| 242 | + foreach ($index_keys as $key) { | |
| 243 | + $status_key .= '[' . (string) $key . ']'; | |
| 244 | + } | |
| 245 | + | |
| 246 | + return $status_key; | |
| 247 | + } | |
| 248 | + | |
| 249 | + private function setUploadedFileContentStatus($field_name, $index_keys, $status) { | |
| 250 | + $status_key = $this->buildUploadedFileStatusKey($field_name, $index_keys); | |
| 251 | + if ($status_key !== '') { | |
| 252 | + $this->uploaded_file_content_statuses[$status_key] = $status; | |
| 253 | + } | |
| 254 | + } | |
| 255 | + | |
| 256 | + private function resolveUploadedFileEntry($field_name) { | |
| 257 | + if (!$this->isUploadedFileKey($field_name)) { | |
| 258 | + return null; | |
| 259 | + } | |
| 260 | + | |
| 261 | + if (!is_array($this->files) || !array_key_exists($field_name, $this->files) || | |
| 262 | + !is_array($this->files[$field_name])) { | |
| 263 | + $this->setUploadedFileContentStatus($field_name, array(), 'missing_file'); | |
| 264 | + return null; | |
| 265 | + } | |
| 266 | + | |
| 267 | + return $this->files[$field_name]; | |
| 268 | + } | |
| 269 | + | |
| 270 | + private function getUploadedFileMetaValue($file_entry, $meta_key, $index_keys) { | |
| 271 | + if (!is_array($file_entry) || !array_key_exists($meta_key, $file_entry)) { | |
| 272 | + return null; | |
| 273 | + } | |
| 274 | + | |
| 275 | + if (empty($index_keys)) { | |
| 276 | + return $file_entry[$meta_key]; | |
| 277 | + } | |
| 278 | + | |
| 279 | + return $this->getKeyVal($file_entry[$meta_key], $index_keys); | |
| 280 | + } | |
| 281 | + | |
| 282 | + private function isUploadedFilePath($path) { | |
| 283 | + return is_string($path) && $path !== '' && is_uploaded_file($path); | |
| 284 | + } | |
| 285 | + | |
| 286 | + private function normalizeUploadedFileSize($size) { | |
| 287 | + if (is_int($size)) { | |
| 288 | + return $size; | |
| 289 | + } | |
| 290 | + | |
| 291 | + if (is_string($size) && preg_match('/^\d+$/', $size) === 1) { | |
| 292 | + return (int) $size; | |
| 293 | + } | |
| 294 | + | |
| 295 | + return null; | |
| 296 | + } | |
| 297 | + | |
| 298 | + private function resolveUploadedFileReadStatus($read_limit, $requested_limit, $per_file_limit, $limited_by_total, | |
| 299 | + $file_size, $content_length) { | |
| 300 | + | |
| 301 | + if ($content_length === 0) { | |
| 302 | + return 'empty'; | |
| 303 | + } | |
| 304 | + | |
| 305 | + if (isset($file_size) && $file_size <= $content_length) { | |
| 306 | + return 'available'; | |
| 307 | + } | |
| 308 | + | |
| 309 | + if ($limited_by_total) { | |
| 310 | + return 'truncated_by_total_limit'; | |
| 311 | + } | |
| 312 | + | |
| 313 | + if (isset($file_size) && $file_size > $read_limit) { | |
| 314 | + if ($requested_limit > $per_file_limit) { | |
| 315 | + return 'truncated_by_config_limit'; | |
| 316 | + } | |
| 317 | + | |
| 318 | + return 'truncated_by_function_limit'; | |
| 319 | + } | |
| 320 | + | |
| 321 | + if (!isset($file_size) && $content_length >= $read_limit) { | |
| 322 | + if ($requested_limit > $per_file_limit) { | |
| 323 | + return 'truncated_by_config_limit'; | |
| 324 | + } | |
| 325 | + | |
| 326 | + if ($read_limit < $requested_limit) { | |
| 327 | + return 'truncated_by_function_limit'; | |
| 328 | + } | |
| 329 | + } | |
| 330 | + | |
| 331 | + return 'available'; | |
| 332 | + } | |
| 333 | + | |
| 334 | + private function readUploadedFileContent($file_entry, $field_name, $index_keys, $max_bytes) { | |
| 335 | + if (!$this->can_get_uploaded_file_content) { | |
| 336 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'disabled_by_config'); | |
| 337 | + return null; | |
| 338 | + } | |
| 339 | + | |
| 340 | + $error = $this->getUploadedFileMetaValue($file_entry, 'error', $index_keys); | |
| 341 | + if ((string) $error !== '0') { | |
| 342 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'upload_error'); | |
| 343 | + return null; | |
| 344 | + } | |
| 345 | + | |
| 346 | + $tmp_name = $this->getUploadedFileMetaValue($file_entry, 'tmp_name', $index_keys); | |
| 347 | + if (!is_string($tmp_name) || $tmp_name === '') { | |
| 348 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'missing_tmp_name'); | |
| 349 | + return null; | |
| 350 | + } | |
| 351 | + | |
| 352 | + if (!$this->isUploadedFilePath($tmp_name)) { | |
| 353 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'not_uploaded_file'); | |
| 354 | + return null; | |
| 355 | + } | |
| 356 | + | |
| 357 | + $requested_limit = max(0, (int) $max_bytes); | |
| 358 | + $per_file_limit = max(0, $this->max_uploaded_file_content_length); | |
| 359 | + $total_limit = max(0, $this->max_total_uploaded_file_content_length); | |
| 360 | + $configured_target = min($requested_limit, $per_file_limit); | |
| 361 | + if ($configured_target <= 0) { | |
| 362 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'empty'); | |
| 363 | + return ''; | |
| 364 | + } | |
| 365 | + | |
| 366 | + $status_key = $this->buildUploadedFileStatusKey($field_name, $index_keys); | |
| 367 | + $cached_length = 0; | |
| 368 | + if (array_key_exists($status_key, $this->uploaded_file_content_cache)) { | |
| 369 | + $cached_length = strlen($this->uploaded_file_content_cache[$status_key]['content']); | |
| 370 | + } | |
| 371 | + | |
| 372 | + $remaining_limit = max(0, $total_limit - $this->uploaded_file_content_bytes_read); | |
| 373 | + $read_limit = min($configured_target, $cached_length + $remaining_limit); | |
| 374 | + $limited_by_total = $read_limit < $configured_target; | |
| 375 | + if ($read_limit <= 0) { | |
| 376 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'total_limit_exceeded'); | |
| 377 | + return null; | |
| 378 | + } | |
| 379 | + | |
| 380 | + if (array_key_exists($status_key, $this->uploaded_file_content_cache) && | |
| 381 | + $cached_length >= $read_limit) { | |
| 382 | + | |
| 383 | + $content = substr($this->uploaded_file_content_cache[$status_key]['content'], 0, $read_limit); | |
| 384 | + } else { | |
| 385 | + $content = file_get_contents($tmp_name, false, null, 0, $read_limit); | |
| 386 | + if ($content === false) { | |
| 387 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'read_failed'); | |
| 388 | + return null; | |
| 389 | + } | |
| 390 | + | |
| 391 | + $this->uploaded_file_content_bytes_read += max(0, strlen($content) - $cached_length); | |
| 392 | + $this->uploaded_file_content_cache[$status_key] = array( | |
| 393 | + 'content' => $content, | |
| 394 | + 'limit' => $read_limit | |
| 395 | + ); | |
| 396 | + } | |
| 397 | + | |
| 398 | + $file_size = $this->normalizeUploadedFileSize($this->getUploadedFileMetaValue($file_entry, 'size', $index_keys)); | |
| 399 | + $this->setUploadedFileContentStatus( | |
| 400 | + $field_name, | |
| 401 | + $index_keys, | |
| 402 | + $this->resolveUploadedFileReadStatus( | |
| 403 | + $read_limit, | |
| 404 | + $requested_limit, | |
| 405 | + $per_file_limit, | |
| 406 | + $limited_by_total, | |
| 407 | + $file_size, | |
| 408 | + strlen($content) | |
| 409 | + ) | |
| 410 | + ); | |
| 411 | + | |
| 412 | + return $content; | |
| 413 | + } | |
| 414 | + | |
| 415 | + private function readUploadedFileContents($file_entry, $field_name, $index_keys, $max_bytes) { | |
| 416 | + $tmp_name = $this->getUploadedFileMetaValue($file_entry, 'tmp_name', $index_keys); | |
| 417 | + | |
| 418 | + if (is_array($tmp_name)) { | |
| 419 | + $contents = array(); | |
| 420 | + foreach ($tmp_name as $key => $value) { | |
| 421 | + $contents[$key] = $this->readUploadedFileContents( | |
| 422 | + $file_entry, | |
| 423 | + $field_name, | |
| 424 | + array_merge($index_keys, array($key)), | |
| 425 | + $max_bytes | |
| 426 | + ); | |
| 427 | + } | |
| 428 | + return $contents; | |
| 429 | + } | |
| 430 | + | |
| 431 | + if ($tmp_name === null) { | |
| 432 | + $this->setUploadedFileContentStatus($field_name, $index_keys, 'missing_file'); | |
| 433 | + return null; | |
| 434 | + } | |
| 435 | + | |
| 436 | + return $this->readUploadedFileContent($file_entry, $field_name, $index_keys, $max_bytes); | |
| 437 | + } | |
| 438 | + | |
| 439 | + private function loadRawBody() { | |
| 440 | + if ($this->raw_body_loaded) { | |
| 441 | + return; | |
| 442 | + } | |
| 443 | + | |
| 444 | + $this->raw_body_loaded = true; | |
| 445 | + if (!$this->can_get_raw_body) { | |
| 446 | + $this->raw_body_status = 'disabled_by_config'; | |
| 447 | + return; | |
| 448 | + } | |
| 449 | + | |
| 450 | + $read_limit = max(0, $this->max_raw_body_length); | |
| 451 | + $_raw_body = file_get_contents("php://input", false, null, 0, $read_limit + 1); | |
| 452 | + if ($_raw_body === false) { | |
| 453 | + $this->raw_body_status = 'read_failed'; | |
| 454 | + return; | |
| 455 | + } | |
| 456 | + | |
| 457 | + $is_truncated = strlen($_raw_body) > $read_limit; | |
| 458 | + $this->raw_body = $_raw_body; | |
| 459 | + $this->raw_body_truncated = $is_truncated; | |
| 460 | + $this->raw_body_status = $is_truncated ? 'truncated_by_limit' : 'available'; | |
| 461 | + } | |
| 462 | + | |
| 463 | + private function loadJsonParams() { | |
| 464 | + if ($this->json_params_loaded) { | |
| 465 | + return; | |
| 466 | + } | |
| 467 | + | |
| 468 | + $this->json_params_loaded = true; | |
| 469 | + if (!$this->can_decode_json) { | |
| 470 | + $this->json_params_status = 'disabled_by_config'; | |
| 471 | + return; | |
| 472 | + } | |
| 473 | + | |
| 474 | + if (!$this->isJsonContentType($this->getContentType())) { | |
| 475 | + $this->json_params_status = 'unsupported_content_type'; | |
| 476 | + return; | |
| 477 | + } | |
| 478 | + | |
| 479 | + $this->loadRawBody(); | |
| 480 | + if (!in_array($this->raw_body_status, array('available', 'truncated_by_limit'), true)) { | |
| 481 | + $this->json_params_status = 'raw_body_unavailable'; | |
| 482 | + return; | |
| 483 | + } | |
| 484 | + | |
| 485 | + if ($this->raw_body_status === 'truncated_by_limit') { | |
| 486 | + $this->json_params_status = 'raw_body_truncated'; | |
| 487 | + return; | |
| 488 | + } | |
| 489 | + | |
| 490 | + $_json_params = WPRProtectUtils_V672::safeDecodeJSON( | |
| 491 | + $this->raw_body, | |
| 492 | + true, | |
| 493 | + $this->max_json_decode_depth | |
| 494 | + ); | |
| 495 | + if (isset($_json_params)) { | |
| 496 | + $this->json_params['JSON'] = $_json_params; | |
| 497 | + $this->json_params_status = 'available'; | |
| 498 | + } elseif (function_exists('json_last_error') && json_last_error() === JSON_ERROR_NONE) { | |
| 499 | + $this->json_params_status = 'decoded_null'; | |
| 500 | + } else { | |
| 501 | + $this->json_params_status = 'decode_failed'; | |
| 502 | + } | |
| 503 | + } | |
| 504 | + | |
| 140 | 505 | public function getPostParams() { |
| 141 | 506 | if (func_num_args() > 0) { |
| 142 | 507 | $args = func_get_args(); |
| 143 | 508 | return $this->getKeyVal($this->post_params, $args); |
| @@ -161,21 +526,23 @@ | ||
| 161 | 526 | return $this->get_params; |
| 162 | 527 | } |
| 163 | 528 | |
| 164 | 529 | public function getAllParams() { |
| 165 | - return array("getParams" => $this->get_params, "postParams" => $this->post_params); | |
| 530 | + return array("getParams" => $this->get_params, "postParams" => $this->post_params, "jsonParams" => $this->getJsonParams()); | |
| 166 | 531 | } |
| 167 | 532 | |
| 168 | 533 | public function getHeader($key) { |
| 169 | - if (array_key_exists($key, $this->headers)) { | |
| 170 | - return $this->headers[$key]; | |
| 171 | - } | |
| 172 | - return null; | |
| 534 | + $key = $this->normalizeHeaderName($key); | |
| 535 | + return isset($key) && array_key_exists($key, $this->headers) ? $this->headers[$key] : null; | |
| 173 | 536 | } |
| 174 | 537 | |
| 175 | 538 | public function getHeaders() { |
| 176 | 539 | if (func_num_args() > 0) { |
| 177 | 540 | $args = func_get_args(); |
| 541 | + $args[0] = $this->normalizeHeaderName($args[0]); | |
| 542 | + if (!isset($args[0])) { | |
| 543 | + return null; | |
| 544 | + } | |
| 178 | 545 | return $this->getKeyVal($this->headers, $args); |
| 179 | 546 | } |
| 180 | 547 | return $this->headers; |
| 181 | 548 | } |
| @@ -195,8 +562,64 @@ | ||
| 195 | 562 | } |
| 196 | 563 | return $this->file_names; |
| 197 | 564 | } |
| 198 | 565 | |
| 566 | + public function getUploadedFileContent($field_name, $max_bytes, $index = null) { | |
| 567 | + $index_keys = $this->normalizeUploadedFileIndexKeys($index); | |
| 568 | + if (!is_array($index_keys)) { | |
| 569 | + return null; | |
| 570 | + } | |
| 571 | + | |
| 572 | + $file_entry = $this->resolveUploadedFileEntry($field_name); | |
| 573 | + if (!is_array($file_entry)) { | |
| 574 | + return null; | |
| 575 | + } | |
| 576 | + | |
| 577 | + return $this->readUploadedFileContents($file_entry, $field_name, $index_keys, $max_bytes); | |
| 578 | + } | |
| 579 | + | |
| 580 | + public function getUploadedFileMeta($field_name, $meta_key, $index = null) { | |
| 581 | + if (!is_string($meta_key) || $meta_key === '') { | |
| 582 | + return null; | |
| 583 | + } | |
| 584 | + | |
| 585 | + $index_keys = $this->normalizeUploadedFileIndexKeys($index); | |
| 586 | + if (!is_array($index_keys)) { | |
| 587 | + return null; | |
| 588 | + } | |
| 589 | + | |
| 590 | + $file_entry = $this->resolveUploadedFileEntry($field_name); | |
| 591 | + if (!is_array($file_entry)) { | |
| 592 | + return null; | |
| 593 | + } | |
| 594 | + | |
| 595 | + $meta_value = $this->getUploadedFileMetaValue($file_entry, $meta_key, $index_keys); | |
| 596 | + if ($meta_key === 'size' && !is_array($meta_value)) { | |
| 597 | + return $this->normalizeUploadedFileSize($meta_value); | |
| 598 | + } | |
| 599 | + | |
| 600 | + return $meta_value; | |
| 601 | + } | |
| 602 | + | |
| 603 | + public function getUploadedFileContentStatus($field_name = null, $index = null) { | |
| 604 | + if ($field_name === null) { | |
| 605 | + return $this->uploaded_file_content_statuses; | |
| 606 | + } | |
| 607 | + | |
| 608 | + if (!$this->isUploadedFileKey($field_name)) { | |
| 609 | + return null; | |
| 610 | + } | |
| 611 | + | |
| 612 | + $index_keys = $this->normalizeUploadedFileIndexKeys($index); | |
| 613 | + if (!is_array($index_keys)) { | |
| 614 | + return null; | |
| 615 | + } | |
| 616 | + | |
| 617 | + $status_key = $this->buildUploadedFileStatusKey($field_name, $index_keys); | |
| 618 | + return array_key_exists($status_key, $this->uploaded_file_content_statuses) ? | |
| 619 | + $this->uploaded_file_content_statuses[$status_key] : null; | |
| 620 | + } | |
| 621 | + | |
| 199 | 622 | public function getHost() { |
| 200 | 623 | return $this->host; |
| 201 | 624 | } |
| 202 | 625 | |
| @@ -229,20 +652,18 @@ | ||
| 229 | 652 | return $this->timestamp; |
| 230 | 653 | } |
| 231 | 654 | |
| 232 | 655 | public function getRequestID() { |
| 233 | - if (!defined("BV_REQUEST_ID")) { | |
| 234 | - define("BV_REQUEST_ID", uniqid(mt_rand())); | |
| 656 | + if (!defined("WPR_REQUEST_ID")) { | |
| 657 | + define("WPR_REQUEST_ID", uniqid(mt_rand())); // phpcs:ignore WordPress.WP.AlternativeFunctions.rand_mt_rand | |
| 235 | 658 | } |
| 236 | 659 | |
| 237 | - return BV_REQUEST_ID; | |
| 660 | + return WPR_REQUEST_ID; | |
| 238 | 661 | } |
| 239 | 662 | |
| 240 | 663 | public function getServerValue($key) { |
| 241 | - if (isset($_SERVER) && array_key_exists($key, $_SERVER)) { | |
| 242 | - return $_SERVER[$key]; | |
| 243 | - } | |
| 244 | - return false; | |
| 664 | + $val = WPRHelper::getRawParam('SERVER', $key); | |
| 665 | + return isset($val) ? $val : false; | |
| 245 | 666 | } |
| 246 | 667 | |
| 247 | 668 | public function getHeadersV2() { |
| 248 | 669 | return $this->headers; |
| @@ -265,7 +686,37 @@ | ||
| 265 | 686 | } |
| 266 | 687 | |
| 267 | 688 | public function getCookiesV2() { |
| 268 | 689 | return $this->cookies; |
| 690 | + } | |
| 691 | + | |
| 692 | + public function getJsonParams() { | |
| 693 | + $this->loadJsonParams(); | |
| 694 | + return $this->json_params; | |
| 695 | + } | |
| 696 | + | |
| 697 | + public function getRawBody() { | |
| 698 | + $this->loadRawBody(); | |
| 699 | + return $this->raw_body; | |
| 700 | + } | |
| 701 | + | |
| 702 | + public function getBodyParserStatus() { | |
| 703 | + return array( | |
| 704 | + 'raw_body_status' => $this->raw_body_status, | |
| 705 | + 'raw_body_truncated' => $this->raw_body_truncated, | |
| 706 | + 'json_params_status' => $this->json_params_status, | |
| 707 | + 'uploaded_file_content_statuses' => $this->uploaded_file_content_statuses, | |
| 708 | + 'uploaded_file_content_bytes_read' => $this->uploaded_file_content_bytes_read, | |
| 709 | + 'max_uploaded_file_content_length' => $this->max_uploaded_file_content_length, | |
| 710 | + 'max_total_uploaded_file_content_length' => $this->max_total_uploaded_file_content_length | |
| 711 | + ); | |
| 712 | + } | |
| 713 | + | |
| 714 | + public function getContentType() { | |
| 715 | + return $this->getHeader('Content-Type'); | |
| 716 | + } | |
| 717 | + | |
| 718 | + public function getContentLength() { | |
| 719 | + return $this->getHeader('Content-Length'); | |
| 269 | 720 | } |
| 270 | 721 | } |
| 271 | 722 | endif; |